~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/selftest/blackbox.py

  • Committer: Martin Pool
  • Date: 2005-09-13 05:22:41 UTC
  • Revision ID: mbp@sourcefrog.net-20050913052241-52dbd8e8ced620f6
- better BZR_DEBUG trace output

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005 Canonical Ltd
 
1
# Copyright (C) 2005 by Canonical Ltd
2
2
# -*- coding: utf-8 -*-
3
 
#
 
3
 
4
4
# This program is free software; you can redistribute it and/or modify
5
5
# it under the terms of the GNU General Public License as published by
6
6
# the Free Software Foundation; either version 2 of the License, or
7
7
# (at your option) any later version.
8
 
#
 
8
 
9
9
# This program is distributed in the hope that it will be useful,
10
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
12
# GNU General Public License for more details.
13
 
#
 
13
 
14
14
# You should have received a copy of the GNU General Public License
15
15
# along with this program; if not, write to the Free Software
16
16
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17
17
 
18
 
# Mr. Smoketoomuch: I'm sorry?
19
 
# Mr. Bounder: You'd better cut down a little then.
20
 
# Mr. Smoketoomuch: Oh, I see! Smoke too much so I'd better cut down a little
21
 
#                   then!
22
18
 
23
19
"""Black-box tests for bzr.
24
20
 
25
21
These check that it behaves properly when it's invoked through the regular
26
 
command-line interface. This doesn't actually run a new interpreter but 
27
 
rather starts again from the run_bzr function.
 
22
command-line interface.
 
23
 
 
24
This always reinvokes bzr through a new Python interpreter, which is a
 
25
bit inefficient but arguably tests in a way more representative of how
 
26
it's normally invoked.
28
27
"""
29
28
 
30
 
 
31
 
# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
32
 
# Note: Please don't add new tests here, it's too big and bulky.  Instead add
33
 
# them into small suites in bzrlib.tests.blackbox.test_FOO for the particular
34
 
# UI command/aspect that is being tested.
35
 
 
36
 
 
37
 
from cStringIO import StringIO
38
 
import os
39
 
import re
40
29
import sys
41
30
 
42
 
import bzrlib
43
 
from bzrlib import (
44
 
    osutils,
45
 
    )
 
31
from bzrlib.selftest import TestCaseInTempDir, BzrTestBase
46
32
from bzrlib.branch import Branch
47
 
from bzrlib.errors import BzrCommandError
48
 
from bzrlib.osutils import (
49
 
    has_symlinks,
50
 
    pathjoin,
51
 
    terminal_width,
52
 
    )
53
 
from bzrlib.tests.HTTPTestUtil import TestCaseWithWebserver
54
 
from bzrlib.tests.test_sftp_transport import TestCaseWithSFTPServer
55
 
from bzrlib.tests.blackbox import ExternalBase
56
 
from bzrlib.workingtree import WorkingTree
 
33
from bzrlib.commands import run_bzr
 
34
 
 
35
 
 
36
class ExternalBase(TestCaseInTempDir):
 
37
    def runbzr(self, args, retcode=0,backtick=False):
 
38
        if isinstance(args, basestring):
 
39
            args = args.split()
 
40
 
 
41
        if backtick:
 
42
            return self.backtick(['python', self.BZRPATH,] + args,
 
43
                           retcode=retcode)
 
44
        else:
 
45
            return self.runcmd(['python', self.BZRPATH,] + args,
 
46
                           retcode=retcode)
57
47
 
58
48
 
59
49
class TestCommands(ExternalBase):
60
50
 
61
 
    def test_nick_command(self):
62
 
        """bzr nick for viewing, setting nicknames"""
63
 
        os.mkdir('me.dev')
64
 
        os.chdir('me.dev')
 
51
    def test_help_commands(self):
 
52
        self.runbzr('--help')
 
53
        self.runbzr('help')
 
54
        self.runbzr('help commands')
 
55
        self.runbzr('help help')
 
56
        self.runbzr('commit -h')
 
57
 
 
58
    def test_init_branch(self):
 
59
        self.runbzr(['init'])
 
60
 
 
61
    def test_whoami(self):
 
62
        # this should always identify something, if only "john@localhost"
 
63
        self.runbzr("whoami")
 
64
        self.runbzr("whoami --email")
 
65
 
 
66
        self.assertEquals(self.runbzr("whoami --email",
 
67
                                      backtick=True).count('@'), 1)
 
68
        
 
69
    def test_whoami_branch(self):
 
70
        """branch specific user identity works."""
65
71
        self.runbzr('init')
66
 
        nick = self.runbzr("nick",backtick=True)
67
 
        self.assertEqual(nick, 'me.dev\n')
68
 
        nick = self.runbzr("nick moo")
69
 
        nick = self.runbzr("nick",backtick=True)
70
 
        self.assertEqual(nick, 'moo\n')
 
72
        f = file('.bzr/email', 'wt')
 
73
        f.write('Branch Identity <branch@identi.ty>')
 
74
        f.close()
 
75
        whoami = self.runbzr("whoami",backtick=True)
 
76
        whoami_email = self.runbzr("whoami --email",backtick=True)
 
77
        self.assertTrue(whoami.startswith('Branch Identity <branch@identi.ty>'))
 
78
        self.assertTrue(whoami_email.startswith('branch@identi.ty'))
71
79
 
72
80
    def test_invalid_commands(self):
73
 
        self.runbzr("pants", retcode=3)
74
 
        self.runbzr("--pants off", retcode=3)
75
 
        self.runbzr("diff --message foo", retcode=3)
 
81
        self.runbzr("pants", retcode=1)
 
82
        self.runbzr("--pants off", retcode=1)
 
83
        self.runbzr("diff --message foo", retcode=1)
 
84
 
 
85
    def test_empty_commit(self):
 
86
        self.runbzr("init")
 
87
        self.build_tree(['hello.txt'])
 
88
        self.runbzr("commit -m empty", retcode=1)
 
89
        self.runbzr("add hello.txt")
 
90
        self.runbzr("commit -m added")
 
91
 
 
92
    def test_ignore_patterns(self):
 
93
        from bzrlib.branch import Branch
 
94
        
 
95
        b = Branch('.', init=True)
 
96
        self.assertEquals(list(b.unknowns()), [])
 
97
 
 
98
        file('foo.tmp', 'wt').write('tmp files are ignored')
 
99
        self.assertEquals(list(b.unknowns()), [])
 
100
        assert self.backtick('bzr unknowns') == ''
 
101
 
 
102
        file('foo.c', 'wt').write('int main() {}')
 
103
        self.assertEquals(list(b.unknowns()), ['foo.c'])
 
104
        assert self.backtick('bzr unknowns') == 'foo.c\n'
 
105
 
 
106
        self.runbzr(['add', 'foo.c'])
 
107
        assert self.backtick('bzr unknowns') == ''
 
108
 
 
109
        # 'ignore' works when creating the .bzignore file
 
110
        file('foo.blah', 'wt').write('blah')
 
111
        self.assertEquals(list(b.unknowns()), ['foo.blah'])
 
112
        self.runbzr('ignore *.blah')
 
113
        self.assertEquals(list(b.unknowns()), [])
 
114
        assert file('.bzrignore', 'rb').read() == '*.blah\n'
 
115
 
 
116
        # 'ignore' works when then .bzrignore file already exists
 
117
        file('garh', 'wt').write('garh')
 
118
        self.assertEquals(list(b.unknowns()), ['garh'])
 
119
        assert self.backtick('bzr unknowns') == 'garh\n'
 
120
        self.runbzr('ignore garh')
 
121
        self.assertEquals(list(b.unknowns()), [])
 
122
        assert file('.bzrignore', 'rb').read() == '*.blah\ngarh\n'
76
123
 
77
124
    def test_revert(self):
 
125
        import os
78
126
        self.runbzr('init')
79
127
 
80
128
        file('hello', 'wt').write('foo')
84
132
        file('goodbye', 'wt').write('baz')
85
133
        self.runbzr('add goodbye')
86
134
        self.runbzr('commit -m setup goodbye')
87
 
 
 
135
        
88
136
        file('hello', 'wt').write('bar')
89
137
        file('goodbye', 'wt').write('qux')
90
138
        self.runbzr('revert hello')
99
147
        os.rmdir('revertdir')
100
148
        self.runbzr('revert')
101
149
 
102
 
        if has_symlinks():
103
 
            os.symlink('/unlikely/to/exist', 'symlink')
104
 
            self.runbzr('add symlink')
105
 
            self.runbzr('commit -m f')
106
 
            os.unlink('symlink')
107
 
            self.runbzr('revert')
108
 
            self.failUnlessExists('symlink')
109
 
            os.unlink('symlink')
110
 
            os.symlink('a-different-path', 'symlink')
111
 
            self.runbzr('revert')
112
 
            self.assertEqual('/unlikely/to/exist',
113
 
                             os.readlink('symlink'))
114
 
        else:
115
 
            self.log("skipping revert symlink tests")
116
 
        
117
 
        file('hello', 'wt').write('xyz')
118
 
        self.runbzr('commit -m xyz hello')
119
 
        self.runbzr('revert -r 1 hello')
120
 
        self.check_file_contents('hello', 'foo')
121
 
        self.runbzr('revert hello')
122
 
        self.check_file_contents('hello', 'xyz')
123
 
        os.chdir('revertdir')
124
 
        self.runbzr('revert')
125
 
        os.chdir('..')
 
150
    def skipped_test_mv_modes(self):
 
151
        """Test two modes of operation for mv"""
 
152
        from bzrlib.branch import Branch
 
153
        b = Branch('.', init=True)
 
154
        self.build_tree(['a', 'c', 'subdir/'])
 
155
        self.run_bzr('mv', 'a', 'b')
 
156
        self.run_bzr('mv', 'b', 'subdir')
 
157
        self.run_bzr('mv', 'subdir/b', 'a')
 
158
        self.run_bzr('mv', 'a', 'b', 'subdir')
 
159
        self.run_bzr('mv', 'subdir/a', 'subdir/newa')
126
160
 
127
161
    def test_main_version(self):
128
162
        """Check output from version command and master option is reasonable"""
131
165
        output = self.runbzr('version', backtick=1)
132
166
        self.log('bzr version output:')
133
167
        self.log(output)
134
 
        self.assert_(output.startswith('Bazaar (bzr) '))
 
168
        self.assert_(output.startswith('bzr (bazaar-ng) '))
135
169
        self.assertNotEqual(output.index('Canonical'), -1)
136
170
        # make sure --version is consistent
137
171
        tmp_output = self.runbzr('--version', backtick=1)
148
182
        test.runbzr('add goodbye')
149
183
        test.runbzr('commit -m setup goodbye')
150
184
 
151
 
    def test_pull_verbose(self):
152
 
        """Pull changes from one branch to another and watch the output."""
 
185
    def test_revert(self):
 
186
        self.example_branch()
 
187
        file('hello', 'wt').write('bar')
 
188
        file('goodbye', 'wt').write('qux')
 
189
        self.runbzr('revert hello')
 
190
        self.check_file_contents('hello', 'foo')
 
191
        self.check_file_contents('goodbye', 'qux')
 
192
        self.runbzr('revert')
 
193
        self.check_file_contents('goodbye', 'baz')
153
194
 
 
195
    def test_merge(self):
 
196
        from bzrlib.branch import Branch
 
197
        import os
 
198
        
154
199
        os.mkdir('a')
155
200
        os.chdir('a')
156
201
 
157
 
        bzr = self.runbzr
158
202
        self.example_branch()
159
 
 
160
203
        os.chdir('..')
161
 
        bzr('branch a b')
 
204
        self.runbzr('branch a b')
162
205
        os.chdir('b')
163
 
        open('b', 'wb').write('else\n')
164
 
        bzr('add b')
165
 
        bzr(['commit', '-m', 'added b'])
166
 
 
167
 
        os.chdir('../a')
168
 
        out = bzr('pull --verbose ../b', backtick=True)
169
 
        self.failIfEqual(out.find('Added Revisions:'), -1)
170
 
        self.failIfEqual(out.find('message:\n  added b'), -1)
171
 
        self.failIfEqual(out.find('added b'), -1)
172
 
 
173
 
        # Check that --overwrite --verbose prints out the removed entries
174
 
        bzr('commit -m foo --unchanged')
175
 
        os.chdir('../b')
176
 
        bzr('commit -m baz --unchanged')
177
 
        bzr('pull ../a', retcode=3)
178
 
        out = bzr('pull --overwrite --verbose ../a', backtick=1)
179
 
 
180
 
        remove_loc = out.find('Removed Revisions:')
181
 
        self.failIfEqual(remove_loc, -1)
182
 
        added_loc = out.find('Added Revisions:')
183
 
        self.failIfEqual(added_loc, -1)
184
 
 
185
 
        removed_message = out.find('message:\n  baz')
186
 
        self.failIfEqual(removed_message, -1)
187
 
        self.failUnless(remove_loc < removed_message < added_loc)
188
 
 
189
 
        added_message = out.find('message:\n  foo')
190
 
        self.failIfEqual(added_message, -1)
191
 
        self.failUnless(added_loc < added_message)
192
 
        
193
 
    def test_locations(self):
194
 
        """Using and remembering different locations"""
195
 
        os.mkdir('a')
196
 
        os.chdir('a')
197
 
        self.runbzr('init')
198
 
        self.runbzr('commit -m unchanged --unchanged')
199
 
        self.runbzr('pull', retcode=3)
200
 
        self.runbzr('merge', retcode=3)
201
 
        self.runbzr('branch . ../b')
202
 
        os.chdir('../b')
203
 
        self.runbzr('pull')
204
 
        self.runbzr('branch . ../c')
205
 
        self.runbzr('pull ../c')
206
 
        self.runbzr('merge')
207
 
        os.chdir('../a')
208
 
        self.runbzr('pull ../b')
209
 
        self.runbzr('pull')
210
 
        self.runbzr('pull ../c')
211
 
        self.runbzr('branch ../c ../d')
212
 
        osutils.rmtree('../c')
213
 
        self.runbzr('pull')
214
 
        os.chdir('../b')
215
 
        self.runbzr('pull')
216
 
        os.chdir('../d')
217
 
        self.runbzr('pull', retcode=3)
218
 
        self.runbzr('pull ../a --remember')
219
 
        self.runbzr('pull')
220
 
        
221
 
    def test_unknown_command(self):
222
 
        """Handling of unknown command."""
223
 
        out, err = self.run_bzr_captured(['fluffy-badger'],
224
 
                                         retcode=3)
225
 
        self.assertEquals(out, '')
226
 
        err.index('unknown command')
227
 
 
228
 
    def create_conflicts(self):
229
 
        """Create a conflicted tree"""
230
 
        os.mkdir('base')
231
 
        os.chdir('base')
232
 
        file('hello', 'wb').write("hi world")
233
 
        file('answer', 'wb').write("42")
234
 
        self.runbzr('init')
235
 
        self.runbzr('add')
236
 
        self.runbzr('commit -m base')
237
 
        self.runbzr('branch . ../other')
238
 
        self.runbzr('branch . ../this')
239
 
        os.chdir('../other')
240
 
        file('hello', 'wb').write("Hello.")
241
 
        file('answer', 'wb').write("Is anyone there?")
242
 
        self.runbzr('commit -m other')
243
 
        os.chdir('../this')
244
 
        file('hello', 'wb').write("Hello, world")
245
 
        self.runbzr('mv answer question')
246
 
        file('question', 'wb').write("What do you get when you multiply six"
247
 
                                   "times nine?")
248
 
        self.runbzr('commit -m this')
249
 
 
250
 
    def test_status(self):
251
 
        os.mkdir('branch1')
252
 
        os.chdir('branch1')
253
 
        self.runbzr('init')
254
 
        self.runbzr('commit --unchanged --message f')
255
 
        self.runbzr('branch . ../branch2')
256
 
        self.runbzr('branch . ../branch3')
257
 
        self.runbzr('commit --unchanged --message peter')
258
 
        os.chdir('../branch2')
259
 
        self.runbzr('merge ../branch1')
260
 
        self.runbzr('commit --unchanged --message pumpkin')
261
 
        os.chdir('../branch3')
262
 
        self.runbzr('merge ../branch2')
263
 
        message = self.capture('status')
264
 
 
265
 
 
266
 
    def test_conflicts(self):
267
 
        """Handling of merge conflicts"""
268
 
        self.create_conflicts()
269
 
        self.runbzr('merge ../other --show-base', retcode=1)
270
 
        conflict_text = file('hello').read()
271
 
        self.assert_('<<<<<<<' in conflict_text)
272
 
        self.assert_('>>>>>>>' in conflict_text)
273
 
        self.assert_('=======' in conflict_text)
274
 
        self.assert_('|||||||' in conflict_text)
275
 
        self.assert_('hi world' in conflict_text)
276
 
        self.runbzr('revert')
277
 
        self.runbzr('resolve --all')
278
 
        self.runbzr('merge ../other', retcode=1)
279
 
        conflict_text = file('hello').read()
280
 
        self.assert_('|||||||' not in conflict_text)
281
 
        self.assert_('hi world' not in conflict_text)
282
 
        result = self.runbzr('conflicts', backtick=1)
283
 
        self.assertEquals(result, "Text conflict in hello\nText conflict in"
284
 
                                  " question\n")
285
 
        result = self.runbzr('status', backtick=1)
286
 
        self.assert_("conflicts:\n  Text conflict in hello\n"
287
 
                     "  Text conflict in question\n" in result, result)
288
 
        self.runbzr('resolve hello')
289
 
        result = self.runbzr('conflicts', backtick=1)
290
 
        self.assertEquals(result, "Text conflict in question\n")
291
 
        self.runbzr('commit -m conflicts', retcode=3)
292
 
        self.runbzr('resolve --all')
293
 
        result = self.runbzr('conflicts', backtick=1)
294
 
        self.runbzr('commit -m conflicts')
295
 
        self.assertEquals(result, "")
296
 
 
297
 
    def test_push(self):
298
 
        # create a source branch
299
 
        os.mkdir('my-branch')
300
 
        os.chdir('my-branch')
301
 
        self.example_branch()
302
 
 
303
 
        # with no push target, fail
304
 
        self.runbzr('push', retcode=3)
305
 
        # with an explicit target work
306
 
        self.runbzr('push ../output-branch')
307
 
        # with an implicit target work
308
 
        self.runbzr('push')
309
 
        # nothing missing
310
 
        self.runbzr('missing ../output-branch')
311
 
        # advance this branch
312
 
        self.runbzr('commit --unchanged -m unchanged')
313
 
 
314
 
        os.chdir('../output-branch')
315
 
        # There is no longer a difference as long as we have
316
 
        # access to the working tree
317
 
        self.runbzr('diff')
318
 
 
319
 
        # But we should be missing a revision
320
 
        self.runbzr('missing ../my-branch', retcode=1)
321
 
 
322
 
        # diverge the branches
323
 
        self.runbzr('commit --unchanged -m unchanged')
324
 
        os.chdir('../my-branch')
325
 
        # cannot push now
326
 
        self.runbzr('push', retcode=3)
327
 
        # and there are difference
328
 
        self.runbzr('missing ../output-branch', retcode=1)
329
 
        self.runbzr('missing --verbose ../output-branch', retcode=1)
330
 
        # but we can force a push
331
 
        self.runbzr('push --overwrite')
332
 
        # nothing missing
333
 
        self.runbzr('missing ../output-branch')
334
 
        
335
 
        # pushing to a new dir with no parent should fail
336
 
        self.runbzr('push ../missing/new-branch', retcode=3)
337
 
        # unless we provide --create-prefix
338
 
        self.runbzr('push --create-prefix ../missing/new-branch')
339
 
        # nothing missing
340
 
        self.runbzr('missing ../missing/new-branch')
341
 
 
342
 
    def test_external_command(self):
343
 
        """Test that external commands can be run by setting the path
344
 
        """
345
 
        # We don't at present run bzr in a subprocess for blackbox tests, and so 
346
 
        # don't really capture stdout, only the internal python stream.
347
 
        # Therefore we don't use a subcommand that produces any output or does
348
 
        # anything -- we just check that it can be run successfully.  
349
 
        cmd_name = 'test-command'
350
 
        if sys.platform == 'win32':
351
 
            cmd_name += '.bat'
352
 
        oldpath = os.environ.get('BZRPATH', None)
353
 
        bzr = self.capture
354
 
        try:
355
 
            if 'BZRPATH' in os.environ:
356
 
                del os.environ['BZRPATH']
357
 
 
358
 
            f = file(cmd_name, 'wb')
359
 
            if sys.platform == 'win32':
360
 
                f.write('@echo off\n')
361
 
            else:
362
 
                f.write('#!/bin/sh\n')
363
 
            # f.write('echo Hello from test-command')
364
 
            f.close()
365
 
            os.chmod(cmd_name, 0755)
366
 
 
367
 
            # It should not find the command in the local 
368
 
            # directory by default, since it is not in my path
369
 
            bzr(cmd_name, retcode=3)
370
 
 
371
 
            # Now put it into my path
372
 
            os.environ['BZRPATH'] = '.'
373
 
 
374
 
            bzr(cmd_name)
375
 
 
376
 
            # Make sure empty path elements are ignored
377
 
            os.environ['BZRPATH'] = os.pathsep
378
 
 
379
 
            bzr(cmd_name, retcode=3)
380
 
 
381
 
        finally:
382
 
            if oldpath:
383
 
                os.environ['BZRPATH'] = oldpath
384
 
 
385
 
 
386
 
def listdir_sorted(dir):
387
 
    L = os.listdir(dir)
388
 
    L.sort()
389
 
    return L
 
206
        file('goodbye', 'wt').write('quux')
 
207
        self.runbzr(['commit',  '-m',  "more u's are always good"])
 
208
 
 
209
        os.chdir('../a')
 
210
        file('hello', 'wt').write('quuux')
 
211
        # We can't merge when there are in-tree changes
 
212
        self.runbzr('merge ../b', retcode=1)
 
213
        self.runbzr(['commit', '-m', "Like an epidemic of u's"])
 
214
        self.runbzr('merge ../b')
 
215
        self.check_file_contents('goodbye', 'quux')
 
216
        # Merging a branch pulls its revision into the tree
 
217
        a = Branch('.')
 
218
        b = Branch('../b')
 
219
        a.get_revision_xml(b.last_patch())
 
220
 
 
221
        self.log('pending merges: %s', a.pending_merges())
 
222
        #        assert a.pending_merges() == [b.last_patch()], "Assertion %s %s" \
 
223
        #        % (a.pending_merges(), b.last_patch())
 
224
 
 
225
 
 
226
    def test_add_reports(self):
 
227
        """add command prints the names of added files."""
 
228
        b = Branch('.', init=True)
 
229
        self.build_tree(['top.txt', 'dir/', 'dir/sub.txt'])
 
230
 
 
231
        from cStringIO import StringIO
 
232
        out = StringIO()
 
233
 
 
234
        ret = self.apply_redirected(None, out, None,
 
235
                                    run_bzr,
 
236
                                    ['add'])
 
237
        self.assertEquals(ret, 0)
 
238
 
 
239
        # the ordering is not defined at the moment
 
240
        results = sorted(out.getvalue().rstrip('\n').split('\n'))
 
241
        self.assertEquals(['added dir',
 
242
                           'added dir/sub.txt',
 
243
                           'added top.txt',],
 
244
                          results)
390
245
 
391
246
 
392
247
class OldTests(ExternalBase):
395
250
    def test_bzr(self):
396
251
        from os import chdir, mkdir
397
252
        from os.path import exists
 
253
        import os
398
254
 
399
255
        runbzr = self.runbzr
400
 
        capture = self.capture
 
256
        backtick = self.backtick
401
257
        progress = self.log
402
258
 
403
259
        progress("basic branch creation")
405
261
        chdir('branch1')
406
262
        runbzr('init')
407
263
 
408
 
        self.assertEquals(capture('root').rstrip(),
409
 
                          pathjoin(self.test_dir, 'branch1'))
 
264
        self.assertEquals(backtick('bzr root').rstrip(),
 
265
                          os.path.join(self.test_dir, 'branch1'))
410
266
 
411
267
        progress("status of new file")
412
268
 
414
270
        f.write('hello world!\n')
415
271
        f.close()
416
272
 
417
 
        self.assertEquals(capture('unknowns'), 'test.txt\n')
418
 
 
419
 
        out = capture("status")
420
 
        self.assertEquals(out, 'unknown:\n  test.txt\n')
 
273
        out = backtick("bzr unknowns")
 
274
        self.assertEquals(out, 'test.txt\n')
 
275
 
 
276
        out = backtick("bzr status")
 
277
        assert out == 'unknown:\n  test.txt\n'
 
278
 
 
279
        out = backtick("bzr status --all")
 
280
        assert out == "unknown:\n  test.txt\n"
 
281
 
 
282
        out = backtick("bzr status test.txt --all")
 
283
        assert out == "unknown:\n  test.txt\n"
421
284
 
422
285
        f = file('test2.txt', 'wt')
423
286
        f.write('goodbye cruel world...\n')
424
287
        f.close()
425
288
 
426
 
        out = capture("status test.txt")
427
 
        self.assertEquals(out, "unknown:\n  test.txt\n")
 
289
        out = backtick("bzr status test.txt")
 
290
        assert out == "unknown:\n  test.txt\n"
428
291
 
429
 
        out = capture("status")
430
 
        self.assertEquals(out, ("unknown:\n" "  test.txt\n" "  test2.txt\n"))
 
292
        out = backtick("bzr status")
 
293
        assert out == ("unknown:\n"
 
294
                       "  test.txt\n"
 
295
                       "  test2.txt\n")
431
296
 
432
297
        os.unlink('test2.txt')
433
298
 
434
299
        progress("command aliases")
435
 
        out = capture("st")
436
 
        self.assertEquals(out, ("unknown:\n" "  test.txt\n"))
 
300
        out = backtick("bzr st --all")
 
301
        assert out == ("unknown:\n"
 
302
                       "  test.txt\n")
437
303
 
438
 
        out = capture("stat")
439
 
        self.assertEquals(out, ("unknown:\n" "  test.txt\n"))
 
304
        out = backtick("bzr stat")
 
305
        assert out == ("unknown:\n"
 
306
                       "  test.txt\n")
440
307
 
441
308
        progress("command help")
442
309
        runbzr("help st")
443
310
        runbzr("help")
444
311
        runbzr("help commands")
445
 
        runbzr("help slartibartfast", 3)
 
312
        runbzr("help slartibartfast", 1)
446
313
 
447
 
        out = capture("help ci")
 
314
        out = backtick("bzr help ci")
448
315
        out.index('aliases: ')
449
316
 
 
317
        progress("can't rename unversioned file")
 
318
        runbzr("rename test.txt new-test.txt", 1)
 
319
 
 
320
        progress("adding a file")
 
321
 
 
322
        runbzr("add test.txt")
 
323
        assert backtick("bzr unknowns") == ''
 
324
        assert backtick("bzr status --all") == ("added:\n"
 
325
                                                "  test.txt\n")
 
326
 
 
327
        progress("rename newly-added file")
 
328
        runbzr("rename test.txt hello.txt")
 
329
        assert os.path.exists("hello.txt")
 
330
        assert not os.path.exists("test.txt")
 
331
 
 
332
        assert backtick("bzr revno") == '0\n'
 
333
 
 
334
        progress("add first revision")
 
335
        runbzr(['commit', '-m', 'add first revision'])
 
336
 
 
337
        progress("more complex renames")
 
338
        os.mkdir("sub1")
 
339
        runbzr("rename hello.txt sub1", 1)
 
340
        runbzr("rename hello.txt sub1/hello.txt", 1)
 
341
        runbzr("move hello.txt sub1", 1)
 
342
 
 
343
        runbzr("add sub1")
 
344
        runbzr("rename sub1 sub2")
 
345
        runbzr("move hello.txt sub2")
 
346
        assert backtick("bzr relpath sub2/hello.txt") == os.path.join("sub2", "hello.txt\n")
 
347
 
 
348
        assert exists("sub2")
 
349
        assert exists("sub2/hello.txt")
 
350
        assert not exists("sub1")
 
351
        assert not exists("hello.txt")
 
352
 
 
353
        runbzr(['commit', '-m', 'commit with some things moved to subdirs'])
 
354
 
 
355
        mkdir("sub1")
 
356
        runbzr('add sub1')
 
357
        runbzr('move sub2/hello.txt sub1')
 
358
        assert not exists('sub2/hello.txt')
 
359
        assert exists('sub1/hello.txt')
 
360
        runbzr('move sub2 sub1')
 
361
        assert not exists('sub2')
 
362
        assert exists('sub1/sub2')
 
363
 
 
364
        runbzr(['commit', '-m', 'rename nested subdirectories'])
 
365
 
 
366
        chdir('sub1/sub2')
 
367
        self.assertEquals(backtick('bzr root')[:-1],
 
368
                          os.path.join(self.test_dir, 'branch1'))
 
369
        runbzr('move ../hello.txt .')
 
370
        assert exists('./hello.txt')
 
371
        assert backtick('bzr relpath hello.txt') == os.path.join('sub1', 'sub2', 'hello.txt\n')
 
372
        assert backtick('bzr relpath ../../sub1/sub2/hello.txt') == os.path.join('sub1', 'sub2', 'hello.txt\n')
 
373
        runbzr(['commit', '-m', 'move to parent directory'])
 
374
        chdir('..')
 
375
        assert backtick('bzr relpath sub2/hello.txt') == os.path.join('sub1', 'sub2', 'hello.txt\n')
 
376
 
 
377
        runbzr('move sub2/hello.txt .')
 
378
        assert exists('hello.txt')
 
379
 
450
380
        f = file('hello.txt', 'wt')
451
381
        f.write('some nice new content\n')
452
382
        f.close()
453
383
 
454
 
        runbzr("add hello.txt")
455
 
        
456
384
        f = file('msg.tmp', 'wt')
457
 
        f.write('this is my new commit\nand it has multiple lines, for fun')
 
385
        f.write('this is my new commit\n')
458
386
        f.close()
459
387
 
460
388
        runbzr('commit -F msg.tmp')
461
389
 
462
 
        self.assertEquals(capture('revno'), '1\n')
463
 
        runbzr('export -r 1 export-1.tmp')
 
390
        assert backtick('bzr revno') == '5\n'
 
391
        runbzr('export -r 5 export-5.tmp')
464
392
        runbzr('export export.tmp')
465
393
 
466
394
        runbzr('log')
467
395
        runbzr('log -v')
468
396
        runbzr('log -v --forward')
469
 
        runbzr('log -m', retcode=3)
470
 
        log_out = capture('log -m commit')
471
 
        self.assert_("this is my new commit\n  and" in log_out)
472
 
        self.assert_("rename nested" not in log_out)
473
 
        self.assert_('revision-id' not in log_out)
474
 
        self.assert_('revision-id' in capture('log --show-ids -m commit'))
 
397
        runbzr('log -m', retcode=1)
 
398
        log_out = backtick('bzr log -m commit')
 
399
        assert "this is my new commit" in log_out
 
400
        assert "rename nested" not in log_out
 
401
        assert 'revision-id' not in log_out
 
402
        assert 'revision-id' in backtick('bzr log --show-ids -m commit')
475
403
 
476
 
        log_out = capture('log --line')
477
 
        # determine the widest line we want
478
 
        max_width = terminal_width() - 1
479
 
        for line in log_out.splitlines():
480
 
            self.assert_(len(line) <= max_width, len(line))
481
 
        self.assert_("this is my new commit and" not in log_out)
482
 
        self.assert_("this is my new commit" in log_out)
483
404
 
484
405
        progress("file with spaces in name")
485
406
        mkdir('sub directory')
486
407
        file('sub directory/file with spaces ', 'wt').write('see how this works\n')
487
408
        runbzr('add .')
488
 
        runbzr('diff', retcode=1)
 
409
        runbzr('diff')
489
410
        runbzr('commit -m add-spaces')
490
411
        runbzr('check')
491
412
 
494
415
 
495
416
        runbzr('info')
496
417
 
497
 
        if has_symlinks():
498
 
            progress("symlinks")
499
 
            mkdir('symlinks')
500
 
            chdir('symlinks')
501
 
            runbzr('init')
502
 
            os.symlink("NOWHERE1", "link1")
503
 
            runbzr('add link1')
504
 
            self.assertEquals(self.capture('unknowns'), '')
505
 
            runbzr(['commit', '-m', '1: added symlink link1'])
506
 
    
507
 
            mkdir('d1')
508
 
            runbzr('add d1')
509
 
            self.assertEquals(self.capture('unknowns'), '')
510
 
            os.symlink("NOWHERE2", "d1/link2")
511
 
            self.assertEquals(self.capture('unknowns'), 'd1/link2\n')
512
 
            # is d1/link2 found when adding d1
513
 
            runbzr('add d1')
514
 
            self.assertEquals(self.capture('unknowns'), '')
515
 
            os.symlink("NOWHERE3", "d1/link3")
516
 
            self.assertEquals(self.capture('unknowns'), 'd1/link3\n')
517
 
            runbzr(['commit', '-m', '2: added dir, symlink'])
518
 
    
519
 
            runbzr('rename d1 d2')
520
 
            runbzr('move d2/link2 .')
521
 
            runbzr('move link1 d2')
522
 
            self.assertEquals(os.readlink("./link2"), "NOWHERE2")
523
 
            self.assertEquals(os.readlink("d2/link1"), "NOWHERE1")
524
 
            runbzr('add d2/link3')
525
 
            runbzr('diff', retcode=1)
526
 
            runbzr(['commit', '-m', '3: rename of dir, move symlinks, add link3'])
527
 
    
528
 
            os.unlink("link2")
529
 
            os.symlink("TARGET 2", "link2")
530
 
            os.unlink("d2/link1")
531
 
            os.symlink("TARGET 1", "d2/link1")
532
 
            runbzr('diff', retcode=1)
533
 
            self.assertEquals(self.capture("relpath d2/link1"), "d2/link1\n")
534
 
            runbzr(['commit', '-m', '4: retarget of two links'])
535
 
    
536
 
            runbzr('remove d2/link1')
537
 
            self.assertEquals(self.capture('unknowns'), 'd2/link1\n')
538
 
            runbzr(['commit', '-m', '5: remove d2/link1'])
539
 
            # try with the rm alias
540
 
            runbzr('add d2/link1')
541
 
            runbzr(['commit', '-m', '6: add d2/link1'])
542
 
            runbzr('rm d2/link1')
543
 
            self.assertEquals(self.capture('unknowns'), 'd2/link1\n')
544
 
            runbzr(['commit', '-m', '7: remove d2/link1'])
545
 
    
546
 
            os.mkdir("d1")
547
 
            runbzr('add d1')
548
 
            runbzr('rename d2/link3 d1/link3new')
549
 
            self.assertEquals(self.capture('unknowns'), 'd2/link1\n')
550
 
            runbzr(['commit', '-m', '8: remove d2/link1, move/rename link3'])
551
 
            
552
 
            runbzr(['check'])
553
 
            
554
 
            runbzr(['export', '-r', '1', 'exp1.tmp'])
555
 
            chdir("exp1.tmp")
556
 
            self.assertEquals(listdir_sorted("."), [ "link1" ])
557
 
            self.assertEquals(os.readlink("link1"), "NOWHERE1")
558
 
            chdir("..")
559
 
            
560
 
            runbzr(['export', '-r', '2', 'exp2.tmp'])
561
 
            chdir("exp2.tmp")
562
 
            self.assertEquals(listdir_sorted("."), [ "d1", "link1" ])
563
 
            chdir("..")
564
 
            
565
 
            runbzr(['export', '-r', '3', 'exp3.tmp'])
566
 
            chdir("exp3.tmp")
567
 
            self.assertEquals(listdir_sorted("."), [ "d2", "link2" ])
568
 
            self.assertEquals(listdir_sorted("d2"), [ "link1", "link3" ])
569
 
            self.assertEquals(os.readlink("d2/link1"), "NOWHERE1")
570
 
            self.assertEquals(os.readlink("link2")   , "NOWHERE2")
571
 
            chdir("..")
572
 
            
573
 
            runbzr(['export', '-r', '4', 'exp4.tmp'])
574
 
            chdir("exp4.tmp")
575
 
            self.assertEquals(listdir_sorted("."), [ "d2", "link2" ])
576
 
            self.assertEquals(os.readlink("d2/link1"), "TARGET 1")
577
 
            self.assertEquals(os.readlink("link2")   , "TARGET 2")
578
 
            self.assertEquals(listdir_sorted("d2"), [ "link1", "link3" ])
579
 
            chdir("..")
580
 
            
581
 
            runbzr(['export', '-r', '5', 'exp5.tmp'])
582
 
            chdir("exp5.tmp")
583
 
            self.assertEquals(listdir_sorted("."), [ "d2", "link2" ])
584
 
            self.assert_(os.path.islink("link2"))
585
 
            self.assert_(listdir_sorted("d2")== [ "link3" ])
586
 
            chdir("..")
587
 
            
588
 
            runbzr(['export', '-r', '8', 'exp6.tmp'])
589
 
            chdir("exp6.tmp")
590
 
            self.assertEqual(listdir_sorted("."), [ "d1", "d2", "link2"])
591
 
            self.assertEquals(listdir_sorted("d1"), [ "link3new" ])
592
 
            self.assertEquals(listdir_sorted("d2"), [])
593
 
            self.assertEquals(os.readlink("d1/link3new"), "NOWHERE3")
594
 
            chdir("..")
595
 
        else:
596
 
            progress("skipping symlink tests")
597
 
 
598
 
 
599
 
class RemoteTests(object):
600
 
    """Test bzr ui commands against remote branches."""
601
 
 
602
 
    def test_branch(self):
603
 
        os.mkdir('from')
604
 
        wt = self.make_branch_and_tree('from')
605
 
        branch = wt.branch
606
 
        wt.commit('empty commit for nonsense', allow_pointless=True)
607
 
        url = self.get_readonly_url('from')
608
 
        self.run_bzr('branch', url, 'to')
609
 
        branch = Branch.open('to')
610
 
        self.assertEqual(1, len(branch.revision_history()))
611
 
        # the branch should be set in to to from
612
 
        self.assertEqual(url + '/', branch.get_parent())
613
 
 
614
 
    def test_log(self):
615
 
        self.build_tree(['branch/', 'branch/file'])
616
 
        self.capture('init branch')
617
 
        self.capture('add branch/file')
618
 
        self.capture('commit -m foo branch')
619
 
        url = self.get_readonly_url('branch/file')
620
 
        output = self.capture('log %s' % url)
621
 
        self.assertEqual(8, len(output.split('\n')))
622
 
        
623
 
    def test_check(self):
624
 
        self.build_tree(['branch/', 'branch/file'])
625
 
        self.capture('init branch')
626
 
        self.capture('add branch/file')
627
 
        self.capture('commit -m foo branch')
628
 
        url = self.get_readonly_url('branch/')
629
 
        self.run_bzr('check', url)
630
 
    
631
 
    def test_push(self):
632
 
        # create a source branch
633
 
        os.mkdir('my-branch')
634
 
        os.chdir('my-branch')
635
 
        self.run_bzr('init')
636
 
        file('hello', 'wt').write('foo')
637
 
        self.run_bzr('add', 'hello')
638
 
        self.run_bzr('commit', '-m', 'setup')
639
 
 
640
 
        # with an explicit target work
641
 
        self.run_bzr('push', self.get_url('output-branch'))
642
 
 
643
 
    
644
 
class HTTPTests(TestCaseWithWebserver, RemoteTests):
645
 
    """Test various commands against a HTTP server."""
646
 
    
647
 
    
648
 
class SFTPTestsAbsolute(TestCaseWithSFTPServer, RemoteTests):
649
 
    """Test various commands against a SFTP server using abs paths."""
650
 
 
651
 
    
652
 
class SFTPTestsAbsoluteSibling(TestCaseWithSFTPServer, RemoteTests):
653
 
    """Test various commands against a SFTP server using abs paths."""
654
 
 
655
 
    def setUp(self):
656
 
        super(SFTPTestsAbsoluteSibling, self).setUp()
657
 
        self._override_home = '/dev/noone/runs/tests/here'
658
 
 
659
 
    
660
 
class SFTPTestsRelative(TestCaseWithSFTPServer, RemoteTests):
661
 
    """Test various commands against a SFTP server using homedir rel paths."""
662
 
 
663
 
    def setUp(self):
664
 
        super(SFTPTestsRelative, self).setUp()
665
 
        self._get_remote_is_absolute = False