/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/tests/blackbox/test_status.py

  • Committer: Andrew Bennetts
  • Date: 2008-03-14 17:07:55 UTC
  • mto: This revision was merged to the branch mainline in revision 3756.
  • Revision ID: andrew.bennetts@canonical.com-20080314170755-th4th2bapqdzowxa
More initial import hackery.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Copyright (C) 2005, 2006 Canonical Ltd
 
2
#
 
3
# This program is free software; you can redistribute it and/or modify
 
4
# it under the terms of the GNU General Public License as published by
 
5
# the Free Software Foundation; either version 2 of the License, or
 
6
# (at your option) any later version.
 
7
#
 
8
# This program is distributed in the hope that it will be useful,
 
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
11
# GNU General Public License for more details.
 
12
#
 
13
# You should have received a copy of the GNU General Public License
 
14
# along with this program; if not, write to the Free Software
 
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
16
 
 
17
"""Tests of status command.
 
18
 
 
19
Most of these depend on the particular formatting used.
 
20
As such they really are blackbox tests even though some of the 
 
21
tests are not using self.capture. If we add tests for the programmatic
 
22
interface later, they will be non blackbox tests.
 
23
"""
 
24
 
 
25
from cStringIO import StringIO
 
26
import codecs
 
27
from os import mkdir, chdir, rmdir, unlink
 
28
import sys
 
29
from tempfile import TemporaryFile
 
30
 
 
31
from bzrlib import (
 
32
    bzrdir,
 
33
    conflicts,
 
34
    errors,
 
35
    osutils,
 
36
    )
 
37
import bzrlib.branch
 
38
from bzrlib.osutils import pathjoin
 
39
from bzrlib.revisionspec import RevisionSpec
 
40
from bzrlib.status import show_tree_status
 
41
from bzrlib.tests import TestCaseWithTransport, TestSkipped
 
42
from bzrlib.workingtree import WorkingTree
 
43
 
 
44
 
 
45
class BranchStatus(TestCaseWithTransport):
 
46
    
 
47
    def assertStatus(self, expected_lines, working_tree,
 
48
        revision=None, short=False):
 
49
        """Run status in working_tree and look for output.
 
50
        
 
51
        :param expected_lines: The lines to look for.
 
52
        :param working_tree: The tree to run status in.
 
53
        """
 
54
        output_string = self.status_string(working_tree, revision, short)
 
55
        self.assertEqual(expected_lines, output_string.splitlines(True))
 
56
    
 
57
    def status_string(self, wt, revision=None, short=False):
 
58
        # use a real file rather than StringIO because it doesn't handle
 
59
        # Unicode very well.
 
60
        tof = codecs.getwriter('utf-8')(TemporaryFile())
 
61
        show_tree_status(wt, to_file=tof, revision=revision, short=short)
 
62
        tof.seek(0)
 
63
        return tof.read().decode('utf-8')
 
64
 
 
65
    def test_branch_status(self):
 
66
        """Test basic branch status"""
 
67
        wt = self.make_branch_and_tree('.')
 
68
 
 
69
        # status with no commits or files - it must
 
70
        # work and show no output. We do this with no
 
71
        # commits to be sure that it's not going to fail
 
72
        # as a corner case.
 
73
        self.assertStatus([], wt)
 
74
 
 
75
        self.build_tree(['hello.c', 'bye.c'])
 
76
        self.assertStatus([
 
77
                'unknown:\n',
 
78
                '  bye.c\n',
 
79
                '  hello.c\n',
 
80
            ],
 
81
            wt)
 
82
        self.assertStatus([
 
83
                '?   bye.c\n',
 
84
                '?   hello.c\n',
 
85
            ],
 
86
            wt, short=True)
 
87
 
 
88
        # add a commit to allow showing pending merges.
 
89
        wt.commit('create a parent to allow testing merge output')
 
90
 
 
91
        wt.add_parent_tree_id('pending@pending-0-0')
 
92
        self.assertStatus([
 
93
                'unknown:\n',
 
94
                '  bye.c\n',
 
95
                '  hello.c\n',
 
96
                'pending merges:\n',
 
97
                '  pending@pending-0-0\n',
 
98
            ],
 
99
            wt)
 
100
        self.assertStatus([
 
101
                '?   bye.c\n',
 
102
                '?   hello.c\n',
 
103
                'P   pending@pending-0-0\n',
 
104
            ],
 
105
            wt, short=True)
 
106
 
 
107
    def test_branch_status_revisions(self):
 
108
        """Tests branch status with revisions"""
 
109
        wt = self.make_branch_and_tree('.')
 
110
 
 
111
        self.build_tree(['hello.c', 'bye.c'])
 
112
        wt.add('hello.c')
 
113
        wt.add('bye.c')
 
114
        wt.commit('Test message')
 
115
 
 
116
        revs = [RevisionSpec.from_string('0')]
 
117
        self.assertStatus([
 
118
                'added:\n',
 
119
                '  bye.c\n',
 
120
                '  hello.c\n'
 
121
            ],
 
122
            wt,
 
123
            revision=revs)
 
124
 
 
125
        self.build_tree(['more.c'])
 
126
        wt.add('more.c')
 
127
        wt.commit('Another test message')
 
128
        
 
129
        revs.append(RevisionSpec.from_string('1'))
 
130
        self.assertStatus([
 
131
                'added:\n',
 
132
                '  bye.c\n',
 
133
                '  hello.c\n',
 
134
            ],
 
135
            wt,
 
136
            revision=revs)
 
137
 
 
138
    def test_pending(self):
 
139
        """Pending merges display works, including Unicode"""
 
140
        mkdir("./branch")
 
141
        wt = self.make_branch_and_tree('branch')
 
142
        b = wt.branch
 
143
        wt.commit("Empty commit 1")
 
144
        b_2_dir = b.bzrdir.sprout('./copy')
 
145
        b_2 = b_2_dir.open_branch()
 
146
        wt2 = b_2_dir.open_workingtree()
 
147
        wt.commit(u"\N{TIBETAN DIGIT TWO} Empty commit 2")
 
148
        wt2.merge_from_branch(wt.branch)
 
149
        message = self.status_string(wt2)
 
150
        self.assertStartsWith(message, "pending merges:\n")
 
151
        self.assertEndsWith(message, "Empty commit 2\n")
 
152
        wt2.commit("merged")
 
153
        # must be long to make sure we see elipsis at the end
 
154
        wt.commit("Empty commit 3 " +
 
155
                   "blah blah blah blah " * 100)
 
156
        wt2.merge_from_branch(wt.branch)
 
157
        message = self.status_string(wt2)
 
158
        self.assertStartsWith(message, "pending merges:\n")
 
159
        self.assert_("Empty commit 3" in message)
 
160
        self.assertEndsWith(message, "...\n")
 
161
 
 
162
    def test_tree_status_ignores(self):
 
163
        """Tests branch status with ignores"""
 
164
        wt = self.make_branch_and_tree('.')
 
165
        self.run_bzr('ignore *~')
 
166
        wt.commit('commit .bzrignore')
 
167
        self.build_tree(['foo.c', 'foo.c~'])
 
168
        self.assertStatus([
 
169
                'unknown:\n',
 
170
                '  foo.c\n',
 
171
                ],
 
172
                wt)
 
173
        self.assertStatus([
 
174
                '?   foo.c\n',
 
175
                ],
 
176
                wt, short=True)
 
177
 
 
178
    def test_tree_status_specific_files(self):
 
179
        """Tests branch status with given specific files"""
 
180
        wt = self.make_branch_and_tree('.')
 
181
        b = wt.branch
 
182
 
 
183
        self.build_tree(['directory/','directory/hello.c', 'bye.c','test.c','dir2/'])
 
184
        wt.add('directory')
 
185
        wt.add('test.c')
 
186
        wt.commit('testing')
 
187
        
 
188
        self.assertStatus([
 
189
                'unknown:\n',
 
190
                '  bye.c\n',
 
191
                '  dir2/\n',
 
192
                '  directory/hello.c\n'
 
193
                ],
 
194
                wt)
 
195
 
 
196
        self.assertStatus([
 
197
                '?   bye.c\n',
 
198
                '?   dir2/\n',
 
199
                '?   directory/hello.c\n'
 
200
                ],
 
201
                wt, short=True)
 
202
 
 
203
        tof = StringIO()
 
204
        self.assertRaises(errors.PathsDoNotExist,
 
205
                          show_tree_status,
 
206
                          wt, specific_files=['bye.c','test.c','absent.c'], 
 
207
                          to_file=tof)
 
208
        
 
209
        tof = StringIO()
 
210
        show_tree_status(wt, specific_files=['directory'], to_file=tof)
 
211
        tof.seek(0)
 
212
        self.assertEquals(tof.readlines(),
 
213
                          ['unknown:\n',
 
214
                           '  directory/hello.c\n'
 
215
                           ])
 
216
        tof = StringIO()
 
217
        show_tree_status(wt, specific_files=['directory'], to_file=tof,
 
218
                         short=True)
 
219
        tof.seek(0)
 
220
        self.assertEquals(tof.readlines(), ['?   directory/hello.c\n'])
 
221
 
 
222
        tof = StringIO()
 
223
        show_tree_status(wt, specific_files=['dir2'], to_file=tof)
 
224
        tof.seek(0)
 
225
        self.assertEquals(tof.readlines(),
 
226
                          ['unknown:\n',
 
227
                           '  dir2/\n'
 
228
                           ])
 
229
        tof = StringIO()
 
230
        show_tree_status(wt, specific_files=['dir2'], to_file=tof, short=True)
 
231
        tof.seek(0)
 
232
        self.assertEquals(tof.readlines(), ['?   dir2/\n'])
 
233
 
 
234
        tof = StringIO()
 
235
        revs = [RevisionSpec.from_string('0'), RevisionSpec.from_string('1')]
 
236
        show_tree_status(wt, specific_files=['test.c'], to_file=tof,
 
237
                         short=True, revision=revs)
 
238
        tof.seek(0)
 
239
        self.assertEquals(tof.readlines(), ['+N  test.c\n'])
 
240
 
 
241
    def test_specific_files_conflicts(self):
 
242
        tree = self.make_branch_and_tree('.')
 
243
        self.build_tree(['dir2/'])
 
244
        tree.add('dir2')
 
245
        tree.commit('added dir2')
 
246
        tree.set_conflicts(conflicts.ConflictList(
 
247
            [conflicts.ContentsConflict('foo')]))
 
248
        tof = StringIO()
 
249
        show_tree_status(tree, specific_files=['dir2'], to_file=tof)
 
250
        self.assertEqualDiff('', tof.getvalue())
 
251
        tree.set_conflicts(conflicts.ConflictList(
 
252
            [conflicts.ContentsConflict('dir2')]))
 
253
        tof = StringIO()
 
254
        show_tree_status(tree, specific_files=['dir2'], to_file=tof)
 
255
        self.assertEqualDiff('conflicts:\n  Contents conflict in dir2\n',
 
256
                             tof.getvalue())
 
257
 
 
258
        tree.set_conflicts(conflicts.ConflictList(
 
259
            [conflicts.ContentsConflict('dir2/file1')]))
 
260
        tof = StringIO()
 
261
        show_tree_status(tree, specific_files=['dir2'], to_file=tof)
 
262
        self.assertEqualDiff('conflicts:\n  Contents conflict in dir2/file1\n',
 
263
                             tof.getvalue())
 
264
 
 
265
    def test_status_nonexistent_file(self):
 
266
        # files that don't exist in either the basis tree or working tree
 
267
        # should give an error
 
268
        wt = self.make_branch_and_tree('.')
 
269
        out, err = self.run_bzr('status does-not-exist', retcode=3)
 
270
        self.assertContainsRe(err, r'do not exist.*does-not-exist')
 
271
 
 
272
    def test_status_out_of_date(self):
 
273
        """Simulate status of out-of-date tree after remote push"""
 
274
        tree = self.make_branch_and_tree('.')
 
275
        self.build_tree_contents([('a', 'foo\n')])
 
276
        tree.lock_write()
 
277
        try:
 
278
            tree.add(['a'])
 
279
            tree.commit('add test file')
 
280
            # simulate what happens after a remote push
 
281
            tree.set_last_revision("0")
 
282
        finally:
 
283
            # before run another commands we should unlock tree
 
284
            tree.unlock()
 
285
        out, err = self.run_bzr('status')
 
286
        self.assertEqual("working tree is out of date, run 'bzr update'\n",
 
287
                         err)
 
288
 
 
289
 
 
290
class CheckoutStatus(BranchStatus):
 
291
 
 
292
    def setUp(self):
 
293
        super(CheckoutStatus, self).setUp()
 
294
        mkdir('codir')
 
295
        chdir('codir')
 
296
        
 
297
    def make_branch_and_tree(self, relpath):
 
298
        source = self.make_branch(pathjoin('..', relpath))
 
299
        checkout = bzrdir.BzrDirMetaFormat1().initialize(relpath)
 
300
        bzrlib.branch.BranchReferenceFormat().initialize(checkout, source)
 
301
        return checkout.create_workingtree()
 
302
 
 
303
 
 
304
class TestStatus(TestCaseWithTransport):
 
305
 
 
306
    def test_status_plain(self):
 
307
        tree = self.make_branch_and_tree('.')
 
308
 
 
309
        self.build_tree(['hello.txt'])
 
310
        result = self.run_bzr("status")[0]
 
311
        self.assertContainsRe(result, "unknown:\n  hello.txt\n")
 
312
 
 
313
        tree.add("hello.txt")
 
314
        result = self.run_bzr("status")[0]
 
315
        self.assertContainsRe(result, "added:\n  hello.txt\n")
 
316
 
 
317
        tree.commit(message="added")
 
318
        result = self.run_bzr("status -r 0..1")[0]
 
319
        self.assertContainsRe(result, "added:\n  hello.txt\n")
 
320
 
 
321
        result = self.run_bzr("status -c 1")[0]
 
322
        self.assertContainsRe(result, "added:\n  hello.txt\n")
 
323
 
 
324
        self.build_tree(['world.txt'])
 
325
        result = self.run_bzr("status -r 0")[0]
 
326
        self.assertContainsRe(result, "added:\n  hello.txt\n" \
 
327
                                      "unknown:\n  world.txt\n")
 
328
        result2 = self.run_bzr("status -r 0..")[0]
 
329
        self.assertEquals(result2, result)
 
330
 
 
331
    def test_status_short(self):
 
332
        tree = self.make_branch_and_tree('.')
 
333
 
 
334
        self.build_tree(['hello.txt'])
 
335
        result = self.run_bzr("status --short")[0]
 
336
        self.assertContainsRe(result, "[?]   hello.txt\n")
 
337
 
 
338
        tree.add("hello.txt")
 
339
        result = self.run_bzr("status --short")[0]
 
340
        self.assertContainsRe(result, "[+]N  hello.txt\n")
 
341
 
 
342
        tree.commit(message="added")
 
343
        result = self.run_bzr("status --short -r 0..1")[0]
 
344
        self.assertContainsRe(result, "[+]N  hello.txt\n")
 
345
 
 
346
        self.build_tree(['world.txt'])
 
347
        result = self.run_bzr("status --short -r 0")[0]
 
348
        self.assertContainsRe(result, "[+]N  hello.txt\n" \
 
349
                                      "[?]   world.txt\n")
 
350
        result2 = self.run_bzr("status --short -r 0..")[0]
 
351
        self.assertEquals(result2, result)
 
352
 
 
353
    def test_status_versioned(self):
 
354
        tree = self.make_branch_and_tree('.')
 
355
 
 
356
        self.build_tree(['hello.txt'])
 
357
        result = self.run_bzr("status --versioned")[0]
 
358
        self.assertNotContainsRe(result, "unknown:\n  hello.txt\n")
 
359
 
 
360
        tree.add("hello.txt")
 
361
        result = self.run_bzr("status --versioned")[0]
 
362
        self.assertContainsRe(result, "added:\n  hello.txt\n")
 
363
 
 
364
        tree.commit("added")
 
365
        result = self.run_bzr("status --versioned -r 0..1")[0]
 
366
        self.assertContainsRe(result, "added:\n  hello.txt\n")
 
367
 
 
368
        self.build_tree(['world.txt'])
 
369
        result = self.run_bzr("status --versioned -r 0")[0]
 
370
        self.assertContainsRe(result, "added:\n  hello.txt\n")
 
371
        self.assertNotContainsRe(result, "unknown:\n  world.txt\n")
 
372
        result2 = self.run_bzr("status --versioned -r 0..")[0]
 
373
        self.assertEquals(result2, result)
 
374
 
 
375
    def test_status_SV(self):
 
376
        tree = self.make_branch_and_tree('.')
 
377
 
 
378
        self.build_tree(['hello.txt'])
 
379
        result = self.run_bzr("status -SV")[0]
 
380
        self.assertNotContainsRe(result, "hello.txt")
 
381
 
 
382
        tree.add("hello.txt")
 
383
        result = self.run_bzr("status -SV")[0]
 
384
        self.assertContainsRe(result, "[+]N  hello.txt\n")
 
385
 
 
386
        tree.commit(message="added")
 
387
        result = self.run_bzr("status -SV -r 0..1")[0]
 
388
        self.assertContainsRe(result, "[+]N  hello.txt\n")
 
389
 
 
390
        self.build_tree(['world.txt'])
 
391
        result = self.run_bzr("status -SV -r 0")[0]
 
392
        self.assertContainsRe(result, "[+]N  hello.txt\n")
 
393
 
 
394
        result2 = self.run_bzr("status -SV -r 0..")[0]
 
395
        self.assertEquals(result2, result)
 
396
 
 
397
    def assertStatusContains(self, pattern):
 
398
        """Run status, and assert it contains the given pattern"""
 
399
        result = self.run_bzr("status --short")[0]
 
400
        self.assertContainsRe(result, pattern)
 
401
 
 
402
    def test_kind_change_short(self):
 
403
        tree = self.make_branch_and_tree('.')
 
404
        self.build_tree(['file'])
 
405
        tree.add('file')
 
406
        tree.commit('added file')
 
407
        unlink('file')
 
408
        self.build_tree(['file/'])
 
409
        self.assertStatusContains('K  file => file/')
 
410
        tree.rename_one('file', 'directory')
 
411
        self.assertStatusContains('RK  file => directory/')
 
412
        rmdir('directory')
 
413
        self.assertStatusContains('RD  file => directory')
 
414
 
 
415
    def test_status_illegal_revision_specifiers(self):
 
416
        out, err = self.run_bzr('status -r 1..23..123', retcode=3)
 
417
        self.assertContainsRe(err, 'one or two revision specifiers')
 
418
 
 
419
 
 
420
class TestStatusEncodings(TestCaseWithTransport):
 
421
    
 
422
    def setUp(self):
 
423
        TestCaseWithTransport.setUp(self)
 
424
        self.user_encoding = osutils._cached_user_encoding
 
425
        self.stdout = sys.stdout
 
426
 
 
427
    def tearDown(self):
 
428
        bzrlib.user_encoding = self.user_encoding
 
429
        sys.stdout = self.stdout
 
430
        TestCaseWithTransport.tearDown(self)
 
431
 
 
432
    def make_uncommitted_tree(self):
 
433
        """Build a branch with uncommitted unicode named changes in the cwd."""
 
434
        working_tree = self.make_branch_and_tree(u'.')
 
435
        filename = u'hell\u00d8'
 
436
        try:
 
437
            self.build_tree_contents([(filename, 'contents of hello')])
 
438
        except UnicodeEncodeError:
 
439
            raise TestSkipped("can't build unicode working tree in "
 
440
                "filesystem encoding %s" % sys.getfilesystemencoding())
 
441
        working_tree.add(filename)
 
442
        return working_tree
 
443
 
 
444
    def test_stdout_ascii(self):
 
445
        sys.stdout = StringIO()
 
446
        osutils._cached_user_encoding = 'ascii'
 
447
        working_tree = self.make_uncommitted_tree()
 
448
        stdout, stderr = self.run_bzr("status")
 
449
 
 
450
        self.assertEquals(stdout, """\
 
451
added:
 
452
  hell?
 
453
""")
 
454
 
 
455
    def test_stdout_latin1(self):
 
456
        sys.stdout = StringIO()
 
457
        osutils._cached_user_encoding = 'latin-1'
 
458
        working_tree = self.make_uncommitted_tree()
 
459
        stdout, stderr = self.run_bzr('status')
 
460
 
 
461
        self.assertEquals(stdout, u"""\
 
462
added:
 
463
  hell\u00d8
 
464
""".encode('latin-1'))
 
465