~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/selftest/blackbox.py

Added support for branch nicks

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005, 2007 Canonical Ltd
2
 
#
 
1
# Copyright (C) 2005 by Canonical Ltd
 
2
# -*- coding: utf-8 -*-
 
3
 
3
4
# This program is free software; you can redistribute it and/or modify
4
5
# it under the terms of the GNU General Public License as published by
5
6
# the Free Software Foundation; either version 2 of the License, or
6
7
# (at your option) any later version.
7
 
#
 
8
 
8
9
# This program is distributed in the hope that it will be useful,
9
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
12
# GNU General Public License for more details.
12
 
#
 
13
 
13
14
# You should have received a copy of the GNU General Public License
14
15
# along with this program; if not, write to the Free Software
15
 
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 
16
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
17
 
17
 
# Mr. Smoketoomuch: I'm sorry?
18
 
# Mr. Bounder: You'd better cut down a little then.
19
 
# Mr. Smoketoomuch: Oh, I see! Smoke too much so I'd better cut down a little
20
 
#                   then!
21
18
 
22
19
"""Black-box tests for bzr.
23
20
 
24
21
These check that it behaves properly when it's invoked through the regular
25
 
command-line interface. This doesn't actually run a new interpreter but
 
22
command-line interface. This doesn't actually run a new interpreter but 
26
23
rather starts again from the run_bzr function.
27
24
"""
28
25
 
29
26
 
30
 
# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
31
 
# Note: Please don't add new tests here, it's too big and bulky.  Instead add
32
 
# them into small suites in bzrlib.tests.blackbox.test_FOO for the particular
33
 
# UI command/aspect that is being tested.
34
 
 
35
 
 
36
27
from cStringIO import StringIO
37
28
import os
38
29
import re
 
30
import shutil
39
31
import sys
40
32
 
41
 
import bzrlib
42
 
from bzrlib import (
43
 
    osutils,
44
 
    )
45
33
from bzrlib.branch import Branch
 
34
from bzrlib.clone import copy_branch
46
35
from bzrlib.errors import BzrCommandError
47
 
from bzrlib.osutils import (
48
 
    has_symlinks,
49
 
    pathjoin,
50
 
    terminal_width,
51
 
    )
52
 
from bzrlib.tests.http_utils import TestCaseWithWebserver
53
 
from bzrlib.tests.test_sftp_transport import TestCaseWithSFTPServer
54
 
from bzrlib.tests.blackbox import ExternalBase
55
 
from bzrlib.workingtree import WorkingTree
 
36
from bzrlib.osutils import has_symlinks
 
37
from bzrlib.selftest import TestCaseInTempDir, BzrTestBase
 
38
from bzrlib.selftest.HTTPTestUtil import TestCaseWithWebserver
 
39
 
 
40
 
 
41
class ExternalBase(TestCaseInTempDir):
 
42
 
 
43
    def runbzr(self, args, retcode=0, backtick=False):
 
44
        if isinstance(args, basestring):
 
45
            args = args.split()
 
46
 
 
47
        if backtick:
 
48
            return self.run_bzr_captured(args, retcode=retcode)[0]
 
49
        else:
 
50
            return self.run_bzr_captured(args, retcode=retcode)
56
51
 
57
52
 
58
53
class TestCommands(ExternalBase):
59
54
 
 
55
    def test_help_commands(self):
 
56
        self.runbzr('--help')
 
57
        self.runbzr('help')
 
58
        self.runbzr('help commands')
 
59
        self.runbzr('help help')
 
60
        self.runbzr('commit -h')
 
61
 
 
62
    def test_init_branch(self):
 
63
        self.runbzr(['init'])
 
64
 
 
65
        # Can it handle subdirectories as well?
 
66
        self.runbzr('init subdir1')
 
67
        self.assert_(os.path.exists('subdir1'))
 
68
        self.assert_(os.path.exists('subdir1/.bzr'))
 
69
 
 
70
        self.runbzr('init subdir2/nothere', retcode=2)
 
71
        
 
72
        os.mkdir('subdir2')
 
73
        self.runbzr('init subdir2')
 
74
        self.runbzr('init subdir2', retcode=1)
 
75
 
 
76
        self.runbzr('init subdir2/subsubdir1')
 
77
        self.assert_(os.path.exists('subdir2/subsubdir1/.bzr'))
 
78
 
 
79
    def test_whoami(self):
 
80
        # this should always identify something, if only "john@localhost"
 
81
        self.runbzr("whoami")
 
82
        self.runbzr("whoami --email")
 
83
 
 
84
        self.assertEquals(self.runbzr("whoami --email",
 
85
                                      backtick=True).count('@'), 1)
 
86
        
 
87
    def test_whoami_branch(self):
 
88
        """branch specific user identity works."""
 
89
        self.runbzr('init')
 
90
        f = file('.bzr/email', 'wt')
 
91
        f.write('Branch Identity <branch@identi.ty>')
 
92
        f.close()
 
93
        bzr_email = os.environ.get('BZREMAIL')
 
94
        if bzr_email is not None:
 
95
            del os.environ['BZREMAIL']
 
96
        whoami = self.runbzr("whoami",backtick=True)
 
97
        whoami_email = self.runbzr("whoami --email",backtick=True)
 
98
        self.assertTrue(whoami.startswith('Branch Identity <branch@identi.ty>'))
 
99
        self.assertTrue(whoami_email.startswith('branch@identi.ty'))
 
100
        # Verify that the environment variable overrides the value 
 
101
        # in the file
 
102
        os.environ['BZREMAIL'] = 'Different ID <other@environ.ment>'
 
103
        whoami = self.runbzr("whoami",backtick=True)
 
104
        whoami_email = self.runbzr("whoami --email",backtick=True)
 
105
        self.assertTrue(whoami.startswith('Different ID <other@environ.ment>'))
 
106
        self.assertTrue(whoami_email.startswith('other@environ.ment'))
 
107
        if bzr_email is not None:
 
108
            os.environ['BZREMAIL'] = bzr_email
 
109
 
60
110
    def test_invalid_commands(self):
61
 
        self.run_bzr("pants", retcode=3)
62
 
        self.run_bzr("--pants off", retcode=3)
63
 
        self.run_bzr("diff --message foo", retcode=3)
 
111
        self.runbzr("pants", retcode=1)
 
112
        self.runbzr("--pants off", retcode=1)
 
113
        self.runbzr("diff --message foo", retcode=1)
 
114
 
 
115
    def test_empty_commit(self):
 
116
        self.runbzr("init")
 
117
        self.build_tree(['hello.txt'])
 
118
        self.runbzr("commit -m empty", retcode=1)
 
119
        self.runbzr("add hello.txt")
 
120
        self.runbzr("commit -m added")
 
121
 
 
122
    def test_empty_commit_message(self):
 
123
        self.runbzr("init")
 
124
        file('foo.c', 'wt').write('int main() {}')
 
125
        self.runbzr(['add', 'foo.c'])
 
126
        self.runbzr(["commit", "-m", ""] , retcode=1) 
 
127
 
 
128
    def test_other_branch_commit(self):
 
129
        # this branch is to ensure consistent behaviour, whether we're run
 
130
        # inside a branch, or not.
 
131
        os.mkdir('empty_branch')
 
132
        os.chdir('empty_branch')
 
133
        self.runbzr('init')
 
134
        os.mkdir('branch')
 
135
        os.chdir('branch')
 
136
        self.runbzr('init')
 
137
        file('foo.c', 'wt').write('int main() {}')
 
138
        file('bar.c', 'wt').write('int main() {}')
 
139
        os.chdir('..')
 
140
        self.runbzr(['add', 'branch/foo.c'])
 
141
        self.runbzr(['add', 'branch'])
 
142
        # can't commit files in different trees; sane error
 
143
        self.runbzr('commit -m newstuff branch/foo.c .', retcode=1)
 
144
        self.runbzr('commit -m newstuff branch/foo.c')
 
145
        self.runbzr('commit -m newstuff branch')
 
146
        self.runbzr('commit -m newstuff branch', retcode=1)
 
147
 
 
148
 
 
149
    def test_ignore_patterns(self):
 
150
        from bzrlib.branch import Branch
 
151
        
 
152
        b = Branch.initialize('.')
 
153
        self.assertEquals(list(b.unknowns()), [])
 
154
 
 
155
        file('foo.tmp', 'wt').write('tmp files are ignored')
 
156
        self.assertEquals(list(b.unknowns()), [])
 
157
        assert self.capture('unknowns') == ''
 
158
 
 
159
        file('foo.c', 'wt').write('int main() {}')
 
160
        self.assertEquals(list(b.unknowns()), ['foo.c'])
 
161
        assert self.capture('unknowns') == 'foo.c\n'
 
162
 
 
163
        self.runbzr(['add', 'foo.c'])
 
164
        assert self.capture('unknowns') == ''
 
165
 
 
166
        # 'ignore' works when creating the .bzignore file
 
167
        file('foo.blah', 'wt').write('blah')
 
168
        self.assertEquals(list(b.unknowns()), ['foo.blah'])
 
169
        self.runbzr('ignore *.blah')
 
170
        self.assertEquals(list(b.unknowns()), [])
 
171
        assert file('.bzrignore', 'rU').read() == '*.blah\n'
 
172
 
 
173
        # 'ignore' works when then .bzrignore file already exists
 
174
        file('garh', 'wt').write('garh')
 
175
        self.assertEquals(list(b.unknowns()), ['garh'])
 
176
        assert self.capture('unknowns') == 'garh\n'
 
177
        self.runbzr('ignore garh')
 
178
        self.assertEquals(list(b.unknowns()), [])
 
179
        assert file('.bzrignore', 'rU').read() == '*.blah\ngarh\n'
64
180
 
65
181
    def test_revert(self):
66
 
        self.run_bzr('init')
 
182
        self.runbzr('init')
67
183
 
68
184
        file('hello', 'wt').write('foo')
69
 
        self.run_bzr('add hello')
70
 
        self.run_bzr('commit -m setup hello')
 
185
        self.runbzr('add hello')
 
186
        self.runbzr('commit -m setup hello')
71
187
 
72
188
        file('goodbye', 'wt').write('baz')
73
 
        self.run_bzr('add goodbye')
74
 
        self.run_bzr('commit -m setup goodbye')
 
189
        self.runbzr('add goodbye')
 
190
        self.runbzr('commit -m setup goodbye')
75
191
 
76
192
        file('hello', 'wt').write('bar')
77
193
        file('goodbye', 'wt').write('qux')
78
 
        self.run_bzr('revert hello')
 
194
        self.runbzr('revert hello')
79
195
        self.check_file_contents('hello', 'foo')
80
196
        self.check_file_contents('goodbye', 'qux')
81
 
        self.run_bzr('revert')
 
197
        self.runbzr('revert')
82
198
        self.check_file_contents('goodbye', 'baz')
83
199
 
84
200
        os.mkdir('revertdir')
85
 
        self.run_bzr('add revertdir')
86
 
        self.run_bzr('commit -m f')
 
201
        self.runbzr('add revertdir')
 
202
        self.runbzr('commit -m f')
87
203
        os.rmdir('revertdir')
88
 
        self.run_bzr('revert')
89
 
 
90
 
        if has_symlinks():
91
 
            os.symlink('/unlikely/to/exist', 'symlink')
92
 
            self.run_bzr('add symlink')
93
 
            self.run_bzr('commit -m f')
94
 
            os.unlink('symlink')
95
 
            self.run_bzr('revert')
96
 
            self.failUnlessExists('symlink')
97
 
            os.unlink('symlink')
98
 
            os.symlink('a-different-path', 'symlink')
99
 
            self.run_bzr('revert')
100
 
            self.assertEqual('/unlikely/to/exist',
101
 
                             os.readlink('symlink'))
102
 
        else:
103
 
            self.log("skipping revert symlink tests")
104
 
 
 
204
        self.runbzr('revert')
 
205
 
 
206
        os.symlink('/unlikely/to/exist', 'symlink')
 
207
        self.runbzr('add symlink')
 
208
        self.runbzr('commit -m f')
 
209
        os.unlink('symlink')
 
210
        self.runbzr('revert')
 
211
        self.failUnlessExists('symlink')
 
212
        os.unlink('symlink')
 
213
        os.symlink('a-different-path', 'symlink')
 
214
        self.runbzr('revert')
 
215
        self.assertEqual('/unlikely/to/exist',
 
216
                         os.readlink('symlink'))
 
217
        
105
218
        file('hello', 'wt').write('xyz')
106
 
        self.run_bzr('commit -m xyz hello')
107
 
        self.run_bzr('revert -r 1 hello')
 
219
        self.runbzr('commit -m xyz hello')
 
220
        self.runbzr('revert -r 1 hello')
108
221
        self.check_file_contents('hello', 'foo')
109
 
        self.run_bzr('revert hello')
 
222
        self.runbzr('revert hello')
110
223
        self.check_file_contents('hello', 'xyz')
111
224
        os.chdir('revertdir')
112
 
        self.run_bzr('revert')
 
225
        self.runbzr('revert')
113
226
        os.chdir('..')
114
227
 
 
228
 
 
229
    def test_mv_modes(self):
 
230
        """Test two modes of operation for mv"""
 
231
        from bzrlib.branch import Branch
 
232
        b = Branch.initialize('.')
 
233
        self.build_tree(['a', 'c', 'subdir/'])
 
234
        self.run_bzr_captured(['add', self.test_dir])
 
235
        self.run_bzr_captured(['mv', 'a', 'b'])
 
236
        self.run_bzr_captured(['mv', 'b', 'subdir'])
 
237
        self.run_bzr_captured(['mv', 'subdir/b', 'a'])
 
238
        self.run_bzr_captured(['mv', 'a', 'c', 'subdir'])
 
239
        self.run_bzr_captured(['mv', 'subdir/a', 'subdir/newa'])
 
240
 
115
241
    def test_main_version(self):
116
242
        """Check output from version command and master option is reasonable"""
117
243
        # output is intentionally passed through to stdout so that we
118
244
        # can see the version being tested
119
 
        output = self.run_bzr('version')[0]
 
245
        output = self.runbzr('version', backtick=1)
120
246
        self.log('bzr version output:')
121
247
        self.log(output)
122
 
        self.assert_(output.startswith('Bazaar (bzr) '))
 
248
        self.assert_(output.startswith('bzr (bazaar-ng) '))
123
249
        self.assertNotEqual(output.index('Canonical'), -1)
124
250
        # make sure --version is consistent
125
 
        tmp_output = self.run_bzr('--version')[0]
 
251
        tmp_output = self.runbzr('--version', backtick=1)
 
252
        self.log('bzr --version output:')
 
253
        self.log(tmp_output)
126
254
        self.assertEquals(output, tmp_output)
127
255
 
128
256
    def example_branch(test):
129
 
        test.run_bzr('init')
 
257
        test.runbzr('init')
130
258
        file('hello', 'wt').write('foo')
131
 
        test.run_bzr('add hello')
132
 
        test.run_bzr('commit -m setup hello')
 
259
        test.runbzr('add hello')
 
260
        test.runbzr('commit -m setup hello')
133
261
        file('goodbye', 'wt').write('baz')
134
 
        test.run_bzr('add goodbye')
135
 
        test.run_bzr('commit -m setup goodbye')
136
 
 
137
 
    def test_pull_verbose(self):
138
 
        """Pull changes from one branch to another and watch the output."""
139
 
 
140
 
        os.mkdir('a')
141
 
        os.chdir('a')
142
 
 
143
 
        self.example_branch()
144
 
 
145
 
        os.chdir('..')
146
 
        self.run_bzr('branch a b')
147
 
        os.chdir('b')
148
 
        open('b', 'wb').write('else\n')
149
 
        self.run_bzr('add b')
150
 
        self.run_bzr(['commit', '-m', 'added b'])
151
 
 
152
 
        os.chdir('../a')
153
 
        out = self.run_bzr('pull --verbose ../b')[0]
154
 
        self.failIfEqual(out.find('Added Revisions:'), -1)
155
 
        self.failIfEqual(out.find('message:\n  added b'), -1)
156
 
        self.failIfEqual(out.find('added b'), -1)
157
 
 
158
 
        # Check that --overwrite --verbose prints out the removed entries
159
 
        self.run_bzr('commit -m foo --unchanged')
160
 
        os.chdir('../b')
161
 
        self.run_bzr('commit -m baz --unchanged')
162
 
        self.run_bzr('pull ../a', retcode=3)
163
 
        out = self.run_bzr('pull --overwrite --verbose ../a')[0]
164
 
 
165
 
        remove_loc = out.find('Removed Revisions:')
166
 
        self.failIfEqual(remove_loc, -1)
167
 
        added_loc = out.find('Added Revisions:')
168
 
        self.failIfEqual(added_loc, -1)
169
 
 
170
 
        removed_message = out.find('message:\n  baz')
171
 
        self.failIfEqual(removed_message, -1)
172
 
        self.failUnless(remove_loc < removed_message < added_loc)
173
 
 
174
 
        added_message = out.find('message:\n  foo')
175
 
        self.failIfEqual(added_message, -1)
176
 
        self.failUnless(added_loc < added_message)
 
262
        test.runbzr('add goodbye')
 
263
        test.runbzr('commit -m setup goodbye')
 
264
 
 
265
    def test_export(self):
 
266
        os.mkdir('branch')
 
267
        os.chdir('branch')
 
268
        self.example_branch()
 
269
        self.runbzr('export ../latest')
 
270
        self.assertEqual(file('../latest/goodbye', 'rt').read(), 'baz')
 
271
        self.runbzr('export ../first -r 1')
 
272
        assert not os.path.exists('../first/goodbye')
 
273
        self.assertEqual(file('../first/hello', 'rt').read(), 'foo')
 
274
        self.runbzr('export ../first.gz -r 1')
 
275
        self.assertEqual(file('../first.gz/hello', 'rt').read(), 'foo')
 
276
        self.runbzr('export ../first.bz2 -r 1')
 
277
        self.assertEqual(file('../first.bz2/hello', 'rt').read(), 'foo')
 
278
        self.runbzr('export ../first.tar -r 1')
 
279
        assert os.path.isfile('../first.tar')
 
280
        from tarfile import TarFile
 
281
        tf = TarFile('../first.tar')
 
282
        assert 'first/hello' in tf.getnames(), tf.getnames()
 
283
        self.assertEqual(tf.extractfile('first/hello').read(), 'foo')
 
284
        self.runbzr('export ../first.tar.gz -r 1')
 
285
        assert os.path.isfile('../first.tar.gz')
 
286
        self.runbzr('export ../first.tbz2 -r 1')
 
287
        assert os.path.isfile('../first.tbz2')
 
288
        self.runbzr('export ../first.tar.bz2 -r 1')
 
289
        assert os.path.isfile('../first.tar.bz2')
 
290
        self.runbzr('export ../first.tar.tbz2 -r 1')
 
291
        assert os.path.isfile('../first.tar.tbz2')
 
292
        from bz2 import BZ2File
 
293
        tf = TarFile('../first.tar.tbz2', 
 
294
                     fileobj=BZ2File('../first.tar.tbz2', 'r'))
 
295
        assert 'first.tar/hello' in tf.getnames(), tf.getnames()
 
296
        self.assertEqual(tf.extractfile('first.tar/hello').read(), 'foo')
 
297
        self.runbzr('export ../first2.tar -r 1 --root pizza')
 
298
        tf = TarFile('../first2.tar')
 
299
        assert 'pizza/hello' in tf.getnames(), tf.getnames()
 
300
 
 
301
    def test_diff(self):
 
302
        self.example_branch()
 
303
        file('hello', 'wt').write('hello world!')
 
304
        self.runbzr('commit -m fixing hello')
 
305
        output = self.runbzr('diff -r 2..3', backtick=1)
 
306
        self.assert_('\n+hello world!' in output)
 
307
        output = self.runbzr('diff -r last:3..last:1', backtick=1)
 
308
        self.assert_('\n+baz' in output)
 
309
 
 
310
    def test_diff_branches(self):
 
311
        self.build_tree(['branch1/', 'branch1/file', 'branch2/'])
 
312
        branch = Branch.initialize('branch1')
 
313
        branch.add(['file'])
 
314
        branch.commit('add file')
 
315
        copy_branch(branch, 'branch2')
 
316
        print >> open('branch2/file', 'w'), 'new content'
 
317
        branch2 = Branch.open('branch2')
 
318
        branch2.commit('update file')
 
319
        # should open branch1 and diff against branch2, 
 
320
        output = self.run_bzr_captured(['diff', '-r', 'branch:branch2', 'branch1'])
 
321
        self.assertEquals(("=== modified file 'file'\n"
 
322
                           "--- file\n"
 
323
                           "+++ file\n"
 
324
                           "@@ -1,1 +1,1 @@\n"
 
325
                           "-new content\n"
 
326
                           "+contents of branch1/file\n"
 
327
                           "\n", ''), output)
 
328
 
 
329
    def test_branch(self):
 
330
        """Branch from one branch to another."""
 
331
        os.mkdir('a')
 
332
        os.chdir('a')
 
333
        self.example_branch()
 
334
        os.chdir('..')
 
335
        self.runbzr('branch a b')
 
336
        self.assertFileEqual('b\n', 'b/.bzr/branch-name')
 
337
        self.runbzr('branch a c -r 1')
 
338
        os.chdir('b')
 
339
        self.runbzr('commit -m foo --unchanged')
 
340
        os.chdir('..')
 
341
        # naughty - abstraction violations RBC 20050928  
 
342
        print "test_branch used to delete the stores, how is this meant to work ?"
 
343
        #shutil.rmtree('a/.bzr/revision-store')
 
344
        #shutil.rmtree('a/.bzr/inventory-store', ignore_errors=True)
 
345
        #shutil.rmtree('a/.bzr/text-store', ignore_errors=True)
 
346
        self.runbzr('branch a d --basis b')
 
347
 
 
348
    def test_merge(self):
 
349
        from bzrlib.branch import Branch
 
350
        
 
351
        os.mkdir('a')
 
352
        os.chdir('a')
 
353
        self.example_branch()
 
354
        os.chdir('..')
 
355
        self.runbzr('branch a b')
 
356
        os.chdir('b')
 
357
        file('goodbye', 'wt').write('quux')
 
358
        self.runbzr(['commit',  '-m',  "more u's are always good"])
 
359
 
 
360
        os.chdir('../a')
 
361
        file('hello', 'wt').write('quuux')
 
362
        # We can't merge when there are in-tree changes
 
363
        self.runbzr('merge ../b', retcode=1)
 
364
        self.runbzr(['commit', '-m', "Like an epidemic of u's"])
 
365
        self.runbzr('merge ../b -r last:1..last:1 --merge-type blooof',
 
366
                    retcode=1)
 
367
        self.runbzr('merge ../b -r last:1..last:1 --merge-type merge3')
 
368
        self.runbzr('revert --no-backup')
 
369
        self.runbzr('merge ../b -r last:1..last:1 --merge-type weave')
 
370
        self.runbzr('revert --no-backup')
 
371
        self.runbzr('merge ../b -r last:1..last:1 --reprocess')
 
372
        self.runbzr('revert --no-backup')
 
373
        self.runbzr('merge ../b -r last:1')
 
374
        self.check_file_contents('goodbye', 'quux')
 
375
        # Merging a branch pulls its revision into the tree
 
376
        a = Branch.open('.')
 
377
        b = Branch.open('../b')
 
378
        a.get_revision_xml(b.last_revision())
 
379
        self.log('pending merges: %s', a.pending_merges())
 
380
        assert a.pending_merges() == [b.last_revision()], "Assertion %s %s" \
 
381
            % (a.pending_merges(), b.last_patch())
 
382
        self.runbzr('commit -m merged')
 
383
        self.runbzr('merge ../b -r last:1')
 
384
        self.assertEqual(Branch.open('.').pending_merges(), [])
 
385
 
 
386
 
 
387
    def test_merge_with_missing_file(self):
 
388
        """Merge handles missing file conflicts"""
 
389
        os.mkdir('a')
 
390
        os.chdir('a')
 
391
        os.mkdir('sub')
 
392
        print >> file('sub/a.txt', 'wb'), "hello"
 
393
        print >> file('b.txt', 'wb'), "hello"
 
394
        print >> file('sub/c.txt', 'wb'), "hello"
 
395
        self.runbzr('init')
 
396
        self.runbzr('add')
 
397
        self.runbzr(('commit', '-m', 'added a'))
 
398
        self.runbzr('branch . ../b')
 
399
        print >> file('sub/a.txt', 'ab'), "there"
 
400
        print >> file('b.txt', 'ab'), "there"
 
401
        print >> file('sub/c.txt', 'ab'), "there"
 
402
        self.runbzr(('commit', '-m', 'Added there'))
 
403
        os.unlink('sub/a.txt')
 
404
        os.unlink('sub/c.txt')
 
405
        os.rmdir('sub')
 
406
        os.unlink('b.txt')
 
407
        self.runbzr(('commit', '-m', 'Removed a.txt'))
 
408
        os.chdir('../b')
 
409
        print >> file('sub/a.txt', 'ab'), "something"
 
410
        print >> file('b.txt', 'ab'), "something"
 
411
        print >> file('sub/c.txt', 'ab'), "something"
 
412
        self.runbzr(('commit', '-m', 'Modified a.txt'))
 
413
        self.runbzr('merge ../a/', retcode=1)
 
414
        assert os.path.exists('sub/a.txt.THIS')
 
415
        assert os.path.exists('sub/a.txt.BASE')
 
416
        os.chdir('../a')
 
417
        self.runbzr('merge ../b/', retcode=1)
 
418
        assert os.path.exists('sub/a.txt.OTHER')
 
419
        assert os.path.exists('sub/a.txt.BASE')
 
420
 
 
421
    def test_pull(self):
 
422
        """Pull changes from one branch to another."""
 
423
        os.mkdir('a')
 
424
        os.chdir('a')
 
425
 
 
426
        self.example_branch()
 
427
        self.runbzr('pull', retcode=1)
 
428
        self.runbzr('missing', retcode=1)
 
429
        self.runbzr('missing .')
 
430
        self.runbzr('missing')
 
431
        self.runbzr('pull')
 
432
        self.runbzr('pull /', retcode=1)
 
433
        self.runbzr('pull')
 
434
 
 
435
        os.chdir('..')
 
436
        self.runbzr('branch a b')
 
437
        os.chdir('b')
 
438
        self.runbzr('pull')
 
439
        os.mkdir('subdir')
 
440
        self.runbzr('add subdir')
 
441
        self.runbzr('commit -m blah --unchanged')
 
442
        os.chdir('../a')
 
443
        a = Branch.open('.')
 
444
        b = Branch.open('../b')
 
445
        assert a.revision_history() == b.revision_history()[:-1]
 
446
        self.runbzr('pull ../b')
 
447
        assert a.revision_history() == b.revision_history()
 
448
        self.runbzr('commit -m blah2 --unchanged')
 
449
        os.chdir('../b')
 
450
        self.runbzr('commit -m blah3 --unchanged')
 
451
        # no overwrite
 
452
        self.runbzr('pull ../a', retcode=1)
 
453
        os.chdir('..')
 
454
        self.runbzr('branch b overwriteme')
 
455
        os.chdir('overwriteme')
 
456
        self.runbzr('pull --overwrite ../a')
 
457
        overwritten = Branch.open('.')
 
458
        self.assertEqual(overwritten.revision_history(),
 
459
                         a.revision_history())
 
460
        os.chdir('../a')
 
461
        self.runbzr('merge ../b')
 
462
        self.runbzr('commit -m blah4 --unchanged')
 
463
        os.chdir('../b/subdir')
 
464
        self.runbzr('pull ../../a')
 
465
        assert a.revision_history()[-1] == b.revision_history()[-1]
 
466
        self.runbzr('commit -m blah5 --unchanged')
 
467
        self.runbzr('commit -m blah6 --unchanged')
 
468
        os.chdir('..')
 
469
        self.runbzr('pull ../a')
 
470
        os.chdir('../a')
 
471
        self.runbzr('commit -m blah7 --unchanged')
 
472
        self.runbzr('merge ../b')
 
473
        self.runbzr('commit -m blah8 --unchanged')
 
474
        self.runbzr('pull ../b')
 
475
        self.runbzr('pull ../b')
 
476
 
 
477
    def test_ls(self):
 
478
        """Test the abilities of 'bzr ls'"""
 
479
        bzr = self.runbzr
 
480
        def bzrout(*args, **kwargs):
 
481
            kwargs['backtick'] = True
 
482
            return self.runbzr(*args, **kwargs)
 
483
 
 
484
        def ls_equals(value, *args):
 
485
            out = self.runbzr(['ls'] + list(args), backtick=True)
 
486
            self.assertEquals(out, value)
 
487
 
 
488
        bzr('init')
 
489
        open('a', 'wb').write('hello\n')
 
490
 
 
491
        # Can't supply both
 
492
        bzr('ls --verbose --null', retcode=1)
 
493
 
 
494
        ls_equals('a\n')
 
495
        ls_equals('?        a\n', '--verbose')
 
496
        ls_equals('a\n', '--unknown')
 
497
        ls_equals('', '--ignored')
 
498
        ls_equals('', '--versioned')
 
499
        ls_equals('a\n', '--unknown', '--ignored', '--versioned')
 
500
        ls_equals('', '--ignored', '--versioned')
 
501
        ls_equals('a\0', '--null')
 
502
 
 
503
        bzr('add a')
 
504
        ls_equals('V        a\n', '--verbose')
 
505
        bzr('commit -m add')
 
506
        
 
507
        os.mkdir('subdir')
 
508
        ls_equals('V        a\n'
 
509
                  '?        subdir/\n'
 
510
                  , '--verbose')
 
511
        open('subdir/b', 'wb').write('b\n')
 
512
        bzr('add')
 
513
        ls_equals('V        a\n'
 
514
                  'V        subdir/\n'
 
515
                  'V        subdir/b\n'
 
516
                  , '--verbose')
 
517
        bzr('commit -m subdir')
 
518
 
 
519
        ls_equals('a\n'
 
520
                  'subdir\n'
 
521
                  , '--non-recursive')
 
522
 
 
523
        ls_equals('V        a\n'
 
524
                  'V        subdir/\n'
 
525
                  , '--verbose', '--non-recursive')
 
526
 
 
527
        # Check what happens in a sub-directory
 
528
        os.chdir('subdir')
 
529
        ls_equals('b\n')
 
530
        ls_equals('b\0'
 
531
                  , '--null')
 
532
        ls_equals('a\n'
 
533
                  'subdir\n'
 
534
                  'subdir/b\n'
 
535
                  , '--from-root')
 
536
        ls_equals('a\0'
 
537
                  'subdir\0'
 
538
                  'subdir/b\0'
 
539
                  , '--from-root', '--null')
 
540
        ls_equals('a\n'
 
541
                  'subdir\n'
 
542
                  , '--from-root', '--non-recursive')
 
543
 
 
544
        os.chdir('..')
 
545
 
 
546
        # Check what happens when we supply a specific revision
 
547
        ls_equals('a\n', '--revision', '1')
 
548
        ls_equals('V        a\n'
 
549
                  , '--verbose', '--revision', '1')
 
550
 
 
551
        os.chdir('subdir')
 
552
        ls_equals('', '--revision', '1')
 
553
 
 
554
        # Now try to do ignored files.
 
555
        os.chdir('..')
 
556
        open('blah.py', 'wb').write('unknown\n')
 
557
        open('blah.pyo', 'wb').write('ignored\n')
 
558
        ls_equals('a\n'
 
559
                  'blah.py\n'
 
560
                  'blah.pyo\n'
 
561
                  'subdir\n'
 
562
                  'subdir/b\n')
 
563
        ls_equals('V        a\n'
 
564
                  '?        blah.py\n'
 
565
                  'I        blah.pyo\n'
 
566
                  'V        subdir/\n'
 
567
                  'V        subdir/b\n'
 
568
                  , '--verbose')
 
569
        ls_equals('blah.pyo\n'
 
570
                  , '--ignored')
 
571
        ls_equals('blah.py\n'
 
572
                  , '--unknown')
 
573
        ls_equals('a\n'
 
574
                  'subdir\n'
 
575
                  'subdir/b\n'
 
576
                  , '--versioned')
 
577
 
177
578
 
178
579
    def test_locations(self):
179
580
        """Using and remembering different locations"""
180
581
        os.mkdir('a')
181
582
        os.chdir('a')
182
 
        self.run_bzr('init')
183
 
        self.run_bzr('commit -m unchanged --unchanged')
184
 
        self.run_bzr('pull', retcode=3)
185
 
        self.run_bzr('merge', retcode=3)
186
 
        self.run_bzr('branch . ../b')
 
583
        self.runbzr('init')
 
584
        self.runbzr('commit -m unchanged --unchanged')
 
585
        self.runbzr('pull', retcode=1)
 
586
        self.runbzr('merge', retcode=1)
 
587
        self.runbzr('branch . ../b')
187
588
        os.chdir('../b')
188
 
        self.run_bzr('pull')
189
 
        self.run_bzr('branch . ../c')
190
 
        self.run_bzr('pull ../c')
191
 
        self.run_bzr('merge')
 
589
        self.runbzr('pull')
 
590
        self.runbzr('branch . ../c')
 
591
        self.runbzr('pull ../c')
 
592
        self.runbzr('merge')
192
593
        os.chdir('../a')
193
 
        self.run_bzr('pull ../b')
194
 
        self.run_bzr('pull')
195
 
        self.run_bzr('pull ../c')
196
 
        self.run_bzr('branch ../c ../d')
197
 
        osutils.rmtree('../c')
198
 
        self.run_bzr('pull')
 
594
        self.runbzr('pull ../b')
 
595
        self.runbzr('pull')
 
596
        self.runbzr('pull ../c')
 
597
        self.runbzr('branch ../c ../d')
 
598
        shutil.rmtree('../c')
 
599
        self.runbzr('pull')
199
600
        os.chdir('../b')
200
 
        self.run_bzr('pull')
 
601
        self.runbzr('pull')
201
602
        os.chdir('../d')
202
 
        self.run_bzr('pull', retcode=3)
203
 
        self.run_bzr('pull ../a --remember')
204
 
        self.run_bzr('pull')
 
603
        self.runbzr('pull', retcode=1)
 
604
        self.runbzr('pull ../a --remember')
 
605
        self.runbzr('pull')
 
606
        
 
607
    def test_add_reports(self):
 
608
        """add command prints the names of added files."""
 
609
        b = Branch.initialize('.')
 
610
        self.build_tree(['top.txt', 'dir/', 'dir/sub.txt'])
 
611
        out = self.run_bzr_captured(['add'], retcode = 0)[0]
 
612
        # the ordering is not defined at the moment
 
613
        results = sorted(out.rstrip('\n').split('\n'))
 
614
        self.assertEquals(['added dir',
 
615
                           'added dir'+os.sep+'sub.txt',
 
616
                           'added top.txt',],
 
617
                          results)
 
618
 
 
619
    def test_add_quiet_is(self):
 
620
        """add -q does not print the names of added files."""
 
621
        b = Branch.initialize('.')
 
622
        self.build_tree(['top.txt', 'dir/', 'dir/sub.txt'])
 
623
        out = self.run_bzr_captured(['add', '-q'], retcode = 0)[0]
 
624
        # the ordering is not defined at the moment
 
625
        results = sorted(out.rstrip('\n').split('\n'))
 
626
        self.assertEquals([''], results)
205
627
 
206
628
    def test_unknown_command(self):
207
629
        """Handling of unknown command."""
208
 
        out, err = self.run_bzr('fluffy-badger', retcode=3)
 
630
        out, err = self.run_bzr_captured(['fluffy-badger'],
 
631
                                         retcode=1)
209
632
        self.assertEquals(out, '')
210
633
        err.index('unknown command')
211
634
 
215
638
        os.chdir('base')
216
639
        file('hello', 'wb').write("hi world")
217
640
        file('answer', 'wb').write("42")
218
 
        self.run_bzr('init')
219
 
        self.run_bzr('add')
220
 
        self.run_bzr('commit -m base')
221
 
        self.run_bzr('branch . ../other')
222
 
        self.run_bzr('branch . ../this')
 
641
        self.runbzr('init')
 
642
        self.runbzr('add')
 
643
        self.runbzr('commit -m base')
 
644
        self.runbzr('branch . ../other')
 
645
        self.runbzr('branch . ../this')
223
646
        os.chdir('../other')
224
647
        file('hello', 'wb').write("Hello.")
225
648
        file('answer', 'wb').write("Is anyone there?")
226
 
        self.run_bzr('commit -m other')
 
649
        self.runbzr('commit -m other')
227
650
        os.chdir('../this')
228
651
        file('hello', 'wb').write("Hello, world")
229
 
        self.run_bzr('mv answer question')
 
652
        self.runbzr('mv answer question')
230
653
        file('question', 'wb').write("What do you get when you multiply six"
231
654
                                   "times nine?")
232
 
        self.run_bzr('commit -m this')
 
655
        self.runbzr('commit -m this')
233
656
 
234
 
    def test_status(self):
235
 
        os.mkdir('branch1')
236
 
        os.chdir('branch1')
237
 
        self.run_bzr('init')
238
 
        self.run_bzr('commit --unchanged --message f')
239
 
        self.run_bzr('branch . ../branch2')
240
 
        self.run_bzr('branch . ../branch3')
241
 
        self.run_bzr('commit --unchanged --message peter')
242
 
        os.chdir('../branch2')
243
 
        self.run_bzr('merge ../branch1')
244
 
        self.run_bzr('commit --unchanged --message pumpkin')
245
 
        os.chdir('../branch3')
246
 
        self.run_bzr('merge ../branch2')
247
 
        message = self.run_bzr('status')[0]
 
657
    def test_remerge(self):
 
658
        """Remerge command works as expected"""
 
659
        self.create_conflicts()
 
660
        self.runbzr('merge ../other --show-base', retcode=1)
 
661
        conflict_text = file('hello').read()
 
662
        assert '|||||||' in conflict_text
 
663
        assert 'hi world' in conflict_text
 
664
        self.runbzr('remerge', retcode=1)
 
665
        conflict_text = file('hello').read()
 
666
        assert '|||||||' not in conflict_text
 
667
        assert 'hi world' not in conflict_text
 
668
        os.unlink('hello.OTHER')
 
669
        self.runbzr('remerge hello --merge-type weave', retcode=1)
 
670
        assert os.path.exists('hello.OTHER')
 
671
        file_id = self.runbzr('file-id hello')
 
672
        file_id = self.runbzr('file-id hello.THIS', retcode=1)
 
673
        self.runbzr('remerge --merge-type weave', retcode=1)
 
674
        assert os.path.exists('hello.OTHER')
 
675
        assert not os.path.exists('hello.BASE')
 
676
        assert '|||||||' not in conflict_text
 
677
        assert 'hi world' not in conflict_text
 
678
        self.runbzr('remerge . --merge-type weave --show-base', retcode=2)
 
679
        self.runbzr('remerge . --merge-type weave --reprocess', retcode=2)
 
680
        self.runbzr('remerge . --show-base --reprocess', retcode=1)
 
681
        self.runbzr('remerge hello --show-base', retcode=1)
 
682
        self.runbzr('remerge hello --reprocess', retcode=1)
 
683
        self.runbzr('resolve --all')
 
684
        self.runbzr('commit -m done',)
 
685
        self.runbzr('remerge', retcode=1)
248
686
 
249
687
 
250
688
    def test_conflicts(self):
251
689
        """Handling of merge conflicts"""
252
690
        self.create_conflicts()
253
 
        self.run_bzr('merge ../other --show-base', retcode=1)
254
 
        conflict_text = file('hello').read()
255
 
        self.assert_('<<<<<<<' in conflict_text)
256
 
        self.assert_('>>>>>>>' in conflict_text)
257
 
        self.assert_('=======' in conflict_text)
258
 
        self.assert_('|||||||' in conflict_text)
259
 
        self.assert_('hi world' in conflict_text)
260
 
        self.run_bzr('revert')
261
 
        self.run_bzr('resolve --all')
262
 
        self.run_bzr('merge ../other', retcode=1)
263
 
        conflict_text = file('hello').read()
264
 
        self.assert_('|||||||' not in conflict_text)
265
 
        self.assert_('hi world' not in conflict_text)
266
 
        result = self.run_bzr('conflicts')[0]
267
 
        self.assertEquals(result, "Text conflict in hello\nText conflict in"
268
 
                                  " question\n")
269
 
        result = self.run_bzr('status')[0]
270
 
        self.assert_("conflicts:\n  Text conflict in hello\n"
271
 
                     "  Text conflict in question\n" in result, result)
272
 
        self.run_bzr('resolve hello')
273
 
        result = self.run_bzr('conflicts')[0]
274
 
        self.assertEquals(result, "Text conflict in question\n")
275
 
        self.run_bzr('commit -m conflicts', retcode=3)
276
 
        self.run_bzr('resolve --all')
277
 
        result = self.run_bzr('conflicts')[0]
278
 
        self.run_bzr('commit -m conflicts')
 
691
        self.runbzr('merge ../other --show-base', retcode=1)
 
692
        conflict_text = file('hello').read()
 
693
        assert '<<<<<<<' in conflict_text
 
694
        assert '>>>>>>>' in conflict_text
 
695
        assert '=======' in conflict_text
 
696
        assert '|||||||' in conflict_text
 
697
        assert 'hi world' in conflict_text
 
698
        self.runbzr('revert')
 
699
        self.runbzr('resolve --all')
 
700
        self.runbzr('merge ../other', retcode=1)
 
701
        conflict_text = file('hello').read()
 
702
        assert '|||||||' not in conflict_text
 
703
        assert 'hi world' not in conflict_text
 
704
        result = self.runbzr('conflicts', backtick=1)
 
705
        self.assertEquals(result, "hello\nquestion\n")
 
706
        result = self.runbzr('status', backtick=1)
 
707
        assert "conflicts:\n  hello\n  question\n" in result, result
 
708
        self.runbzr('resolve hello')
 
709
        result = self.runbzr('conflicts', backtick=1)
 
710
        self.assertEquals(result, "question\n")
 
711
        self.runbzr('commit -m conflicts', retcode=1)
 
712
        self.runbzr('resolve --all')
 
713
        result = self.runbzr('conflicts', backtick=1)
 
714
        self.runbzr('commit -m conflicts')
279
715
        self.assertEquals(result, "")
280
716
 
281
 
    def test_push(self):
282
 
        # create a source branch
283
 
        self.thisFailsStrictLockCheck()
284
 
        os.mkdir('my-branch')
285
 
        os.chdir('my-branch')
286
 
        self.example_branch()
287
 
 
288
 
        # with no push target, fail
289
 
        self.run_bzr('push', retcode=3)
290
 
        # with an explicit target work
291
 
        self.run_bzr('push ../output-branch')
292
 
        # with an implicit target work
293
 
        self.run_bzr('push')
294
 
        # nothing missing
295
 
        self.run_bzr('missing ../output-branch')
296
 
        # advance this branch
297
 
        self.run_bzr('commit --unchanged -m unchanged')
298
 
 
299
 
        os.chdir('../output-branch')
300
 
        # There is no longer a difference as long as we have
301
 
        # access to the working tree
302
 
        self.run_bzr('diff')
303
 
 
304
 
        # But we should be missing a revision
305
 
        self.run_bzr('missing ../my-branch', retcode=1)
306
 
 
307
 
        # diverge the branches
308
 
        self.run_bzr('commit --unchanged -m unchanged')
309
 
        os.chdir('../my-branch')
310
 
        # cannot push now
311
 
        self.run_bzr('push', retcode=3)
312
 
        # and there are difference
313
 
        self.run_bzr('missing ../output-branch', retcode=1)
314
 
        self.run_bzr('missing --verbose ../output-branch', retcode=1)
315
 
        # but we can force a push
316
 
        self.run_bzr('push --overwrite')
317
 
        # nothing missing
318
 
        self.run_bzr('missing ../output-branch')
319
 
 
320
 
        # pushing to a new dir with no parent should fail
321
 
        self.run_bzr('push ../missing/new-branch', retcode=3)
322
 
        # unless we provide --create-prefix
323
 
        self.run_bzr('push --create-prefix ../missing/new-branch')
324
 
        # nothing missing
325
 
        self.run_bzr('missing ../missing/new-branch')
326
 
 
327
 
    def test_external_command(self):
328
 
        """Test that external commands can be run by setting the path
329
 
        """
330
 
        # We don't at present run bzr in a subprocess for blackbox tests, and so
331
 
        # don't really capture stdout, only the internal python stream.
332
 
        # Therefore we don't use a subcommand that produces any output or does
333
 
        # anything -- we just check that it can be run successfully.
334
 
        cmd_name = 'test-command'
335
 
        if sys.platform == 'win32':
336
 
            cmd_name += '.bat'
337
 
        oldpath = os.environ.get('BZRPATH', None)
338
 
        try:
339
 
            if 'BZRPATH' in os.environ:
340
 
                del os.environ['BZRPATH']
341
 
 
342
 
            f = file(cmd_name, 'wb')
343
 
            if sys.platform == 'win32':
344
 
                f.write('@echo off\n')
345
 
            else:
346
 
                f.write('#!/bin/sh\n')
347
 
            # f.write('echo Hello from test-command')
348
 
            f.close()
349
 
            os.chmod(cmd_name, 0755)
350
 
 
351
 
            # It should not find the command in the local
352
 
            # directory by default, since it is not in my path
353
 
            self.run_bzr(cmd_name, retcode=3)
354
 
 
355
 
            # Now put it into my path
356
 
            os.environ['BZRPATH'] = '.'
357
 
 
358
 
            self.run_bzr(cmd_name)
359
 
 
360
 
            # Make sure empty path elements are ignored
361
 
            os.environ['BZRPATH'] = os.pathsep
362
 
 
363
 
            self.run_bzr(cmd_name, retcode=3)
364
 
 
365
 
        finally:
366
 
            if oldpath:
367
 
                os.environ['BZRPATH'] = oldpath
 
717
    def test_resign(self):
 
718
        """Test re signing of data."""
 
719
        import bzrlib.gpg
 
720
        oldstrategy = bzrlib.gpg.GPGStrategy
 
721
        branch = Branch.initialize('.')
 
722
        branch.commit("base", allow_pointless=True, rev_id='A')
 
723
        try:
 
724
            # monkey patch gpg signing mechanism
 
725
            from bzrlib.testament import Testament
 
726
            bzrlib.gpg.GPGStrategy = bzrlib.gpg.LoopbackGPGStrategy
 
727
            self.runbzr('re-sign -r revid:A')
 
728
            self.assertEqual(Testament.from_revision(branch,'A').as_short_text(),
 
729
                             branch.revision_store.get('A', 'sig').read())
 
730
        finally:
 
731
            bzrlib.gpg.GPGStrategy = oldstrategy
 
732
            
 
733
    def test_resign_range(self):
 
734
        import bzrlib.gpg
 
735
        oldstrategy = bzrlib.gpg.GPGStrategy
 
736
        branch = Branch.initialize('.')
 
737
        branch.commit("base", allow_pointless=True, rev_id='A')
 
738
        branch.commit("base", allow_pointless=True, rev_id='B')
 
739
        branch.commit("base", allow_pointless=True, rev_id='C')
 
740
        try:
 
741
            # monkey patch gpg signing mechanism
 
742
            from bzrlib.testament import Testament
 
743
            bzrlib.gpg.GPGStrategy = bzrlib.gpg.LoopbackGPGStrategy
 
744
            self.runbzr('re-sign -r 1..')
 
745
            self.assertEqual(Testament.from_revision(branch,'A').as_short_text(),
 
746
                             branch.revision_store.get('A', 'sig').read())
 
747
            self.assertEqual(Testament.from_revision(branch,'B').as_short_text(),
 
748
                             branch.revision_store.get('B', 'sig').read())
 
749
            self.assertEqual(Testament.from_revision(branch,'C').as_short_text(),
 
750
                             branch.revision_store.get('C', 'sig').read())
 
751
        finally:
 
752
            bzrlib.gpg.GPGStrategy = oldstrategy
368
753
 
369
754
 
370
755
def listdir_sorted(dir):
380
765
        from os import chdir, mkdir
381
766
        from os.path import exists
382
767
 
 
768
        runbzr = self.runbzr
 
769
        capture = self.capture
383
770
        progress = self.log
384
771
 
385
772
        progress("basic branch creation")
386
773
        mkdir('branch1')
387
774
        chdir('branch1')
388
 
        self.run_bzr('init')
 
775
        runbzr('init')
389
776
 
390
 
        self.assertIsSameRealPath(self.run_bzr('root')[0].rstrip(),
391
 
                                  pathjoin(self.test_dir, 'branch1'))
 
777
        self.assertEquals(capture('root').rstrip(),
 
778
                          os.path.join(self.test_dir, 'branch1'))
392
779
 
393
780
        progress("status of new file")
394
781
 
396
783
        f.write('hello world!\n')
397
784
        f.close()
398
785
 
399
 
        self.assertEquals(self.run_bzr('unknowns')[0], 'test.txt\n')
400
 
 
401
 
        out = self.run_bzr("status")[0]
402
 
        self.assertEquals(out, 'unknown:\n  test.txt\n')
 
786
        self.assertEquals(capture('unknowns'), 'test.txt\n')
 
787
 
 
788
        out = capture("status")
 
789
        assert out == 'unknown:\n  test.txt\n'
 
790
 
 
791
        out = capture("status --all")
 
792
        assert out == "unknown:\n  test.txt\n"
 
793
 
 
794
        out = capture("status test.txt --all")
 
795
        assert out == "unknown:\n  test.txt\n"
403
796
 
404
797
        f = file('test2.txt', 'wt')
405
798
        f.write('goodbye cruel world...\n')
406
799
        f.close()
407
800
 
408
 
        out = self.run_bzr("status test.txt")[0]
409
 
        self.assertEquals(out, "unknown:\n  test.txt\n")
 
801
        out = capture("status test.txt")
 
802
        assert out == "unknown:\n  test.txt\n"
410
803
 
411
 
        out = self.run_bzr("status")[0]
412
 
        self.assertEquals(out, ("unknown:\n" "  test.txt\n" "  test2.txt\n"))
 
804
        out = capture("status")
 
805
        assert out == ("unknown:\n"
 
806
                       "  test.txt\n"
 
807
                       "  test2.txt\n")
413
808
 
414
809
        os.unlink('test2.txt')
415
810
 
416
811
        progress("command aliases")
417
 
        out = self.run_bzr("st")[0]
418
 
        self.assertEquals(out, ("unknown:\n" "  test.txt\n"))
 
812
        out = capture("st --all")
 
813
        assert out == ("unknown:\n"
 
814
                       "  test.txt\n")
419
815
 
420
 
        out = self.run_bzr("stat")[0]
421
 
        self.assertEquals(out, ("unknown:\n" "  test.txt\n"))
 
816
        out = capture("stat")
 
817
        assert out == ("unknown:\n"
 
818
                       "  test.txt\n")
422
819
 
423
820
        progress("command help")
424
 
        self.run_bzr("help st")
425
 
        self.run_bzr("help")
426
 
        self.run_bzr("help commands")
427
 
        self.run_bzr("help slartibartfast", retcode=3)
428
 
 
429
 
        out = self.run_bzr("help ci")[0]
430
 
        out.index('Aliases:  ci, checkin\n')
 
821
        runbzr("help st")
 
822
        runbzr("help")
 
823
        runbzr("help commands")
 
824
        runbzr("help slartibartfast", 1)
 
825
 
 
826
        out = capture("help ci")
 
827
        out.index('aliases: ')
 
828
 
 
829
        progress("can't rename unversioned file")
 
830
        runbzr("rename test.txt new-test.txt", 1)
 
831
 
 
832
        progress("adding a file")
 
833
 
 
834
        runbzr("add test.txt")
 
835
        assert capture("unknowns") == ''
 
836
        assert capture("status --all") == ("added:\n"
 
837
                                                "  test.txt\n")
 
838
 
 
839
        progress("rename newly-added file")
 
840
        runbzr("rename test.txt hello.txt")
 
841
        assert os.path.exists("hello.txt")
 
842
        assert not os.path.exists("test.txt")
 
843
 
 
844
        assert capture("revno") == '0\n'
 
845
 
 
846
        progress("add first revision")
 
847
        runbzr(['commit', '-m', 'add first revision'])
 
848
 
 
849
        progress("more complex renames")
 
850
        os.mkdir("sub1")
 
851
        runbzr("rename hello.txt sub1", 1)
 
852
        runbzr("rename hello.txt sub1/hello.txt", 1)
 
853
        runbzr("move hello.txt sub1", 1)
 
854
 
 
855
        runbzr("add sub1")
 
856
        runbzr("rename sub1 sub2")
 
857
        runbzr("move hello.txt sub2")
 
858
        self.assertEqual(capture("relpath sub2/hello.txt"),
 
859
                         os.path.join("sub2", "hello.txt\n"))
 
860
 
 
861
        assert exists("sub2")
 
862
        assert exists("sub2/hello.txt")
 
863
        assert not exists("sub1")
 
864
        assert not exists("hello.txt")
 
865
 
 
866
        runbzr(['commit', '-m', 'commit with some things moved to subdirs'])
 
867
 
 
868
        mkdir("sub1")
 
869
        runbzr('add sub1')
 
870
        runbzr('move sub2/hello.txt sub1')
 
871
        assert not exists('sub2/hello.txt')
 
872
        assert exists('sub1/hello.txt')
 
873
        runbzr('move sub2 sub1')
 
874
        assert not exists('sub2')
 
875
        assert exists('sub1/sub2')
 
876
 
 
877
        runbzr(['commit', '-m', 'rename nested subdirectories'])
 
878
 
 
879
        chdir('sub1/sub2')
 
880
        self.assertEquals(capture('root')[:-1],
 
881
                          os.path.join(self.test_dir, 'branch1'))
 
882
        runbzr('move ../hello.txt .')
 
883
        assert exists('./hello.txt')
 
884
        self.assertEquals(capture('relpath hello.txt'),
 
885
                          os.path.join('sub1', 'sub2', 'hello.txt') + '\n')
 
886
        assert capture('relpath ../../sub1/sub2/hello.txt') == os.path.join('sub1', 'sub2', 'hello.txt\n')
 
887
        runbzr(['commit', '-m', 'move to parent directory'])
 
888
        chdir('..')
 
889
        assert capture('relpath sub2/hello.txt') == os.path.join('sub1', 'sub2', 'hello.txt\n')
 
890
 
 
891
        runbzr('move sub2/hello.txt .')
 
892
        assert exists('hello.txt')
431
893
 
432
894
        f = file('hello.txt', 'wt')
433
895
        f.write('some nice new content\n')
434
896
        f.close()
435
897
 
436
 
        self.run_bzr("add hello.txt")
437
 
 
438
898
        f = file('msg.tmp', 'wt')
439
899
        f.write('this is my new commit\nand it has multiple lines, for fun')
440
900
        f.close()
441
901
 
442
 
        self.run_bzr('commit -F msg.tmp')
443
 
 
444
 
        self.assertEquals(self.run_bzr('revno')[0], '1\n')
445
 
        self.run_bzr('export -r 1 export-1.tmp')
446
 
        self.run_bzr('export export.tmp')
447
 
 
448
 
        self.run_bzr('log')
449
 
        self.run_bzr('log -v')
450
 
        self.run_bzr('log -v --forward')
451
 
        self.run_bzr('log -m', retcode=3)
452
 
        log_out = self.run_bzr('log -m commit')[0]
453
 
        self.assert_("this is my new commit\n  and" in log_out)
454
 
        self.assert_("rename nested" not in log_out)
455
 
        self.assert_('revision-id' not in log_out)
456
 
        self.assert_('revision-id' in self.run_bzr('log --show-ids -m commit')[0])
457
 
 
458
 
        log_out = self.run_bzr('log --line')[0]
459
 
        # determine the widest line we want
460
 
        max_width = terminal_width() - 1
 
902
        runbzr('commit -F msg.tmp')
 
903
 
 
904
        assert capture('revno') == '5\n'
 
905
        runbzr('export -r 5 export-5.tmp')
 
906
        runbzr('export export.tmp')
 
907
 
 
908
        runbzr('log')
 
909
        runbzr('log -v')
 
910
        runbzr('log -v --forward')
 
911
        runbzr('log -m', retcode=1)
 
912
        log_out = capture('log -m commit')
 
913
        assert "this is my new commit\n  and" in log_out
 
914
        assert "rename nested" not in log_out
 
915
        assert 'revision-id' not in log_out
 
916
        assert 'revision-id' in capture('log --show-ids -m commit')
 
917
 
 
918
        log_out = capture('log --line')
461
919
        for line in log_out.splitlines():
462
 
            self.assert_(len(line) <= max_width, len(line))
463
 
        self.assert_("this is my new commit and" not in log_out)
464
 
        self.assert_("this is my new commit" in log_out)
 
920
            assert len(line) <= 79, len(line)
 
921
        assert "this is my new commit and" in log_out
 
922
 
465
923
 
466
924
        progress("file with spaces in name")
467
925
        mkdir('sub directory')
468
926
        file('sub directory/file with spaces ', 'wt').write('see how this works\n')
469
 
        self.run_bzr('add .')
470
 
        self.run_bzr('diff', retcode=1)
471
 
        self.run_bzr('commit -m add-spaces')
472
 
        self.run_bzr('check')
473
 
 
474
 
        self.run_bzr('log')
475
 
        self.run_bzr('log --forward')
476
 
 
477
 
        self.run_bzr('info')
 
927
        runbzr('add .')
 
928
        runbzr('diff')
 
929
        runbzr('commit -m add-spaces')
 
930
        runbzr('check')
 
931
 
 
932
        runbzr('log')
 
933
        runbzr('log --forward')
 
934
 
 
935
        runbzr('info')
478
936
 
479
937
        if has_symlinks():
480
938
            progress("symlinks")
481
939
            mkdir('symlinks')
482
940
            chdir('symlinks')
483
 
            self.run_bzr('init')
 
941
            runbzr('init')
484
942
            os.symlink("NOWHERE1", "link1")
485
 
            self.run_bzr('add link1')
486
 
            self.assertEquals(self.run_bzr('unknowns')[0], '')
487
 
            self.run_bzr(['commit', '-m', '1: added symlink link1'])
488
 
 
 
943
            runbzr('add link1')
 
944
            assert self.capture('unknowns') == ''
 
945
            runbzr(['commit', '-m', '1: added symlink link1'])
 
946
    
489
947
            mkdir('d1')
490
 
            self.run_bzr('add d1')
491
 
            self.assertEquals(self.run_bzr('unknowns')[0], '')
 
948
            runbzr('add d1')
 
949
            assert self.capture('unknowns') == ''
492
950
            os.symlink("NOWHERE2", "d1/link2")
493
 
            self.assertEquals(self.run_bzr('unknowns')[0], 'd1/link2\n')
 
951
            assert self.capture('unknowns') == 'd1/link2\n'
494
952
            # is d1/link2 found when adding d1
495
 
            self.run_bzr('add d1')
496
 
            self.assertEquals(self.run_bzr('unknowns')[0], '')
 
953
            runbzr('add d1')
 
954
            assert self.capture('unknowns') == ''
497
955
            os.symlink("NOWHERE3", "d1/link3")
498
 
            self.assertEquals(self.run_bzr('unknowns')[0], 'd1/link3\n')
499
 
            self.run_bzr(['commit', '-m', '2: added dir, symlink'])
500
 
 
501
 
            self.run_bzr('rename d1 d2')
502
 
            self.run_bzr('move d2/link2 .')
503
 
            self.run_bzr('move link1 d2')
504
 
            self.assertEquals(os.readlink("./link2"), "NOWHERE2")
505
 
            self.assertEquals(os.readlink("d2/link1"), "NOWHERE1")
506
 
            self.run_bzr('add d2/link3')
507
 
            self.run_bzr('diff', retcode=1)
508
 
            self.run_bzr(['commit', '-m',
509
 
                          '3: rename of dir, move symlinks, add link3'])
510
 
 
 
956
            assert self.capture('unknowns') == 'd1/link3\n'
 
957
            runbzr(['commit', '-m', '2: added dir, symlink'])
 
958
    
 
959
            runbzr('rename d1 d2')
 
960
            runbzr('move d2/link2 .')
 
961
            runbzr('move link1 d2')
 
962
            assert os.readlink("./link2") == "NOWHERE2"
 
963
            assert os.readlink("d2/link1") == "NOWHERE1"
 
964
            runbzr('add d2/link3')
 
965
            runbzr('diff')
 
966
            runbzr(['commit', '-m', '3: rename of dir, move symlinks, add link3'])
 
967
    
511
968
            os.unlink("link2")
512
969
            os.symlink("TARGET 2", "link2")
513
970
            os.unlink("d2/link1")
514
971
            os.symlink("TARGET 1", "d2/link1")
515
 
            self.run_bzr('diff', retcode=1)
516
 
            self.assertEquals(self.run_bzr("relpath d2/link1")[0], "d2/link1\n")
517
 
            self.run_bzr(['commit', '-m', '4: retarget of two links'])
518
 
 
519
 
            self.run_bzr('remove --keep d2/link1')
520
 
            self.assertEquals(self.run_bzr('unknowns')[0], 'd2/link1\n')
521
 
            self.run_bzr(['commit', '-m', '5: remove d2/link1'])
 
972
            runbzr('diff')
 
973
            assert self.capture("relpath d2/link1") == "d2/link1\n"
 
974
            runbzr(['commit', '-m', '4: retarget of two links'])
 
975
    
 
976
            runbzr('remove d2/link1')
 
977
            assert self.capture('unknowns') == 'd2/link1\n'
 
978
            runbzr(['commit', '-m', '5: remove d2/link1'])
522
979
            # try with the rm alias
523
 
            self.run_bzr('add d2/link1')
524
 
            self.run_bzr(['commit', '-m', '6: add d2/link1'])
525
 
            self.run_bzr('rm --keep d2/link1')
526
 
            self.assertEquals(self.run_bzr('unknowns')[0], 'd2/link1\n')
527
 
            self.run_bzr(['commit', '-m', '7: remove d2/link1'])
528
 
 
 
980
            runbzr('add d2/link1')
 
981
            runbzr(['commit', '-m', '6: add d2/link1'])
 
982
            runbzr('rm d2/link1')
 
983
            assert self.capture('unknowns') == 'd2/link1\n'
 
984
            runbzr(['commit', '-m', '7: remove d2/link1'])
 
985
    
529
986
            os.mkdir("d1")
530
 
            self.run_bzr('add d1')
531
 
            self.run_bzr('rename d2/link3 d1/link3new')
532
 
            self.assertEquals(self.run_bzr('unknowns')[0], 'd2/link1\n')
533
 
            self.run_bzr(['commit', '-m',
534
 
                          '8: remove d2/link1, move/rename link3'])
535
 
 
536
 
            self.run_bzr('check')
537
 
 
538
 
            self.run_bzr('export -r 1 exp1.tmp')
 
987
            runbzr('add d1')
 
988
            runbzr('rename d2/link3 d1/link3new')
 
989
            assert self.capture('unknowns') == 'd2/link1\n'
 
990
            runbzr(['commit', '-m', '8: remove d2/link1, move/rename link3'])
 
991
            
 
992
            runbzr(['check'])
 
993
            
 
994
            runbzr(['export', '-r', '1', 'exp1.tmp'])
539
995
            chdir("exp1.tmp")
540
 
            self.assertEquals(listdir_sorted("."), [ "link1" ])
541
 
            self.assertEquals(os.readlink("link1"), "NOWHERE1")
 
996
            assert listdir_sorted(".") == [ "link1" ]
 
997
            assert os.readlink("link1") == "NOWHERE1"
542
998
            chdir("..")
543
 
 
544
 
            self.run_bzr('export -r 2 exp2.tmp')
 
999
            
 
1000
            runbzr(['export', '-r', '2', 'exp2.tmp'])
545
1001
            chdir("exp2.tmp")
546
 
            self.assertEquals(listdir_sorted("."), [ "d1", "link1" ])
 
1002
            assert listdir_sorted(".") == [ "d1", "link1" ]
547
1003
            chdir("..")
548
 
 
549
 
            self.run_bzr('export -r 3 exp3.tmp')
 
1004
            
 
1005
            runbzr(['export', '-r', '3', 'exp3.tmp'])
550
1006
            chdir("exp3.tmp")
551
 
            self.assertEquals(listdir_sorted("."), [ "d2", "link2" ])
552
 
            self.assertEquals(listdir_sorted("d2"), [ "link1", "link3" ])
553
 
            self.assertEquals(os.readlink("d2/link1"), "NOWHERE1")
554
 
            self.assertEquals(os.readlink("link2")   , "NOWHERE2")
 
1007
            assert listdir_sorted(".") == [ "d2", "link2" ]
 
1008
            assert listdir_sorted("d2") == [ "link1", "link3" ]
 
1009
            assert os.readlink("d2/link1") == "NOWHERE1"
 
1010
            assert os.readlink("link2")    == "NOWHERE2"
555
1011
            chdir("..")
556
 
 
557
 
            self.run_bzr('export -r 4 exp4.tmp')
 
1012
            
 
1013
            runbzr(['export', '-r', '4', 'exp4.tmp'])
558
1014
            chdir("exp4.tmp")
559
 
            self.assertEquals(listdir_sorted("."), [ "d2", "link2" ])
560
 
            self.assertEquals(os.readlink("d2/link1"), "TARGET 1")
561
 
            self.assertEquals(os.readlink("link2")   , "TARGET 2")
562
 
            self.assertEquals(listdir_sorted("d2"), [ "link1", "link3" ])
 
1015
            assert listdir_sorted(".") == [ "d2", "link2" ]
 
1016
            assert os.readlink("d2/link1") == "TARGET 1"
 
1017
            assert os.readlink("link2")    == "TARGET 2"
 
1018
            assert listdir_sorted("d2") == [ "link1", "link3" ]
563
1019
            chdir("..")
564
 
 
565
 
            self.run_bzr('export -r 5 exp5.tmp')
 
1020
            
 
1021
            runbzr(['export', '-r', '5', 'exp5.tmp'])
566
1022
            chdir("exp5.tmp")
567
 
            self.assertEquals(listdir_sorted("."), [ "d2", "link2" ])
568
 
            self.assert_(os.path.islink("link2"))
569
 
            self.assert_(listdir_sorted("d2")== [ "link3" ])
 
1023
            assert listdir_sorted(".") == [ "d2", "link2" ]
 
1024
            assert os.path.islink("link2")
 
1025
            assert listdir_sorted("d2")== [ "link3" ]
570
1026
            chdir("..")
571
 
 
572
 
            self.run_bzr('export -r 8 exp6.tmp')
 
1027
            
 
1028
            runbzr(['export', '-r', '8', 'exp6.tmp'])
573
1029
            chdir("exp6.tmp")
574
1030
            self.assertEqual(listdir_sorted("."), [ "d1", "d2", "link2"])
575
 
            self.assertEquals(listdir_sorted("d1"), [ "link3new" ])
576
 
            self.assertEquals(listdir_sorted("d2"), [])
577
 
            self.assertEquals(os.readlink("d1/link3new"), "NOWHERE3")
 
1031
            assert listdir_sorted("d1") == [ "link3new" ]
 
1032
            assert listdir_sorted("d2") == []
 
1033
            assert os.readlink("d1/link3new") == "NOWHERE3"
578
1034
            chdir("..")
579
1035
        else:
580
1036
            progress("skipping symlink tests")
581
1037
 
582
1038
 
583
 
class RemoteTests(object):
 
1039
class HttpTests(TestCaseWithWebserver):
584
1040
    """Test bzr ui commands against remote branches."""
585
1041
 
586
1042
    def test_branch(self):
587
1043
        os.mkdir('from')
588
 
        wt = self.make_branch_and_tree('from')
589
 
        branch = wt.branch
590
 
        wt.commit('empty commit for nonsense', allow_pointless=True)
591
 
        url = self.get_readonly_url('from')
592
 
        self.run_bzr(['branch', url, 'to'])
 
1044
        branch = Branch.initialize('from')
 
1045
        branch.commit('empty commit for nonsense', allow_pointless=True)
 
1046
        url = self.get_remote_url('from')
 
1047
        self.run_bzr('branch', url, 'to')
593
1048
        branch = Branch.open('to')
594
1049
        self.assertEqual(1, len(branch.revision_history()))
595
 
        # the branch should be set in to to from
596
 
        self.assertEqual(url + '/', branch.get_parent())
597
1050
 
598
1051
    def test_log(self):
599
1052
        self.build_tree(['branch/', 'branch/file'])
600
 
        self.run_bzr('init branch')[0]
601
 
        self.run_bzr('add branch/file')[0]
602
 
        self.run_bzr('commit -m foo branch')[0]
603
 
        url = self.get_readonly_url('branch/file')
604
 
        output = self.run_bzr('log %s' % url)[0]
605
 
        self.assertEqual(8, len(output.split('\n')))
606
 
 
607
 
    def test_check(self):
608
 
        self.build_tree(['branch/', 'branch/file'])
609
 
        self.run_bzr('init branch')[0]
610
 
        self.run_bzr('add branch/file')[0]
611
 
        self.run_bzr('commit -m foo branch')[0]
612
 
        url = self.get_readonly_url('branch/')
613
 
        self.run_bzr(['check', url])
614
 
 
615
 
    def test_push(self):
616
 
        self.thisFailsStrictLockCheck()
617
 
        # create a source branch
618
 
        os.mkdir('my-branch')
619
 
        os.chdir('my-branch')
620
 
        self.run_bzr('init')
621
 
        file('hello', 'wt').write('foo')
622
 
        self.run_bzr('add hello')
623
 
        self.run_bzr('commit -m setup')
624
 
 
625
 
        # with an explicit target work
626
 
        self.run_bzr(['push', self.get_url('output-branch')])
627
 
 
628
 
 
629
 
class HTTPTests(TestCaseWithWebserver, RemoteTests):
630
 
    """Test various commands against a HTTP server."""
631
 
 
632
 
 
633
 
class SFTPTestsAbsolute(TestCaseWithSFTPServer, RemoteTests):
634
 
    """Test various commands against a SFTP server using abs paths."""
635
 
 
636
 
 
637
 
class SFTPTestsAbsoluteSibling(TestCaseWithSFTPServer, RemoteTests):
638
 
    """Test various commands against a SFTP server using abs paths."""
639
 
 
640
 
    def setUp(self):
641
 
        super(SFTPTestsAbsoluteSibling, self).setUp()
642
 
        self._override_home = '/dev/noone/runs/tests/here'
643
 
 
644
 
 
645
 
class SFTPTestsRelative(TestCaseWithSFTPServer, RemoteTests):
646
 
    """Test various commands against a SFTP server using homedir rel paths."""
647
 
 
648
 
    def setUp(self):
649
 
        super(SFTPTestsRelative, self).setUp()
650
 
        self._get_remote_is_absolute = False
 
1053
        branch = Branch.initialize('branch')
 
1054
        branch.add(['file'])
 
1055
        branch.commit('add file', rev_id='A')
 
1056
        url = self.get_remote_url('branch/file')
 
1057
        output = self.capture('log %s' % url)
 
1058
        self.assertEqual(7, len(output.split('\n')))
 
1059
        
 
1060
 
 
1061
 
 
1062