~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

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

Review comments.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005 by Canonical Ltd
2
 
 
 
1
# Copyright (C) 2005, 2006 Canonical Ltd
 
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
5
5
# the Free Software Foundation; either version 2 of the License, or
6
6
# (at your option) any later version.
7
 
 
 
7
#
8
8
# This program is distributed in the hope that it will be useful,
9
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
11
# GNU General Public License for more details.
12
 
 
 
12
#
13
13
# You should have received a copy of the GNU General Public License
14
14
# along with this program; if not, write to the Free Software
15
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
16
 
17
 
 
18
17
"""Tests of status command.
19
18
 
20
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.
21
23
"""
22
24
 
23
 
 
24
 
from bzrlib.selftest import InTempDir
25
 
 
26
 
class BranchStatus(InTempDir):
27
 
    def runTest(self): 
28
 
        """Basic 'bzr mkdir' operation"""
29
 
        from cStringIO import StringIO
30
 
        from bzrlib.status import show_status
31
 
        from bzrlib.branch import Branch
32
 
        
33
 
        b = Branch('.', init=True)
34
 
 
35
 
        # status with nothing
36
 
        tof = StringIO()
37
 
        show_status(b, to_file=tof)
38
 
        self.assertEquals(tof.getvalue(), "")
39
 
 
40
 
        tof = StringIO()
41
 
        self.build_tree(['hello.c', 'bye.c'])
42
 
        show_status(b, to_file=tof)
43
 
        tof.seek(0)
44
 
        self.assertEquals(tof.readlines(),
45
 
                          ['unknown:\n',
46
 
                           '  bye.c\n',
47
 
                           '  hello.c\n',
48
 
                           ])
 
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
    )
 
36
import bzrlib.branch
 
37
from bzrlib.builtins import merge
 
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
        merge(["./branch", -1], [None, None], this_dir = './copy')
 
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
        merge(["./branch", -1], [None, None], this_dir = './copy')
 
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
    def test_specific_files_conflicts(self):
 
235
        tree = self.make_branch_and_tree('.')
 
236
        self.build_tree(['dir2/'])
 
237
        tree.add('dir2')
 
238
        tree.commit('added dir2')
 
239
        tree.set_conflicts(conflicts.ConflictList(
 
240
            [conflicts.ContentsConflict('foo')]))
 
241
        tof = StringIO()
 
242
        show_tree_status(tree, specific_files=['dir2'], to_file=tof)
 
243
        self.assertEqualDiff('', tof.getvalue())
 
244
        tree.set_conflicts(conflicts.ConflictList(
 
245
            [conflicts.ContentsConflict('dir2')]))
 
246
        tof = StringIO()
 
247
        show_tree_status(tree, specific_files=['dir2'], to_file=tof)
 
248
        self.assertEqualDiff('conflicts:\n  Contents conflict in dir2\n',
 
249
                             tof.getvalue())
 
250
 
 
251
        tree.set_conflicts(conflicts.ConflictList(
 
252
            [conflicts.ContentsConflict('dir2/file1')]))
 
253
        tof = StringIO()
 
254
        show_tree_status(tree, specific_files=['dir2'], to_file=tof)
 
255
        self.assertEqualDiff('conflicts:\n  Contents conflict in dir2/file1\n',
 
256
                             tof.getvalue())
 
257
 
 
258
    def test_status_nonexistent_file(self):
 
259
        # files that don't exist in either the basis tree or working tree
 
260
        # should give an error
 
261
        wt = self.make_branch_and_tree('.')
 
262
        out, err = self.run_bzr('status does-not-exist', retcode=3)
 
263
        self.assertContainsRe(err, r'do not exist.*does-not-exist')
 
264
 
 
265
    def test_status_out_of_date(self):
 
266
        """Simulate status of out-of-date tree after remote push"""
 
267
        tree = self.make_branch_and_tree('.')
 
268
        self.build_tree_contents([('a', 'foo\n')])
 
269
        tree.lock_write()
 
270
        try:
 
271
            tree.add(['a'])
 
272
            tree.commit('add test file')
 
273
            # simulate what happens after a remote push
 
274
            tree.set_last_revision("0")
 
275
        finally:
 
276
            # before run another commands we should unlock tree
 
277
            tree.unlock()
 
278
        out, err = self.run_bzr('status')
 
279
        self.assertEqual("working tree is out of date, run 'bzr update'\n",
 
280
                         err)
 
281
 
 
282
 
 
283
class CheckoutStatus(BranchStatus):
 
284
 
 
285
    def setUp(self):
 
286
        super(CheckoutStatus, self).setUp()
 
287
        mkdir('codir')
 
288
        chdir('codir')
 
289
        
 
290
    def make_branch_and_tree(self, relpath):
 
291
        source = self.make_branch(pathjoin('..', relpath))
 
292
        checkout = bzrdir.BzrDirMetaFormat1().initialize(relpath)
 
293
        bzrlib.branch.BranchReferenceFormat().initialize(checkout, source)
 
294
        return checkout.create_workingtree()
 
295
 
 
296
 
 
297
class TestStatus(TestCaseWithTransport):
 
298
 
 
299
    def test_status_plain(self):
 
300
        self.run_bzr("init")
 
301
 
 
302
        self.build_tree(['hello.txt'])
 
303
        result = self.run_bzr("status")[0]
 
304
        self.assertContainsRe(result, "unknown:\n  hello.txt\n")
 
305
 
 
306
        self.run_bzr("add hello.txt")
 
307
        result = self.run_bzr("status")[0]
 
308
        self.assertContainsRe(result, "added:\n  hello.txt\n")
 
309
 
 
310
        self.run_bzr("commit -m added")
 
311
        result = self.run_bzr("status -r 0..1")[0]
 
312
        self.assertContainsRe(result, "added:\n  hello.txt\n")
 
313
 
 
314
        self.build_tree(['world.txt'])
 
315
        result = self.run_bzr("status -r 0")[0]
 
316
        self.assertContainsRe(result, "added:\n  hello.txt\n" \
 
317
                                      "unknown:\n  world.txt\n")
 
318
        result2 = self.run_bzr("status -r 0..")[0]
 
319
        self.assertEquals(result2, result)
 
320
 
 
321
    def test_status_short(self):
 
322
        self.run_bzr("init")
 
323
 
 
324
        self.build_tree(['hello.txt'])
 
325
        result = self.run_bzr("status --short")[0]
 
326
        self.assertContainsRe(result, "[?]   hello.txt\n")
 
327
 
 
328
        self.run_bzr("add hello.txt")
 
329
        result = self.run_bzr("status --short")[0]
 
330
        self.assertContainsRe(result, "[+]N  hello.txt\n")
 
331
 
 
332
        self.run_bzr("commit -m added")
 
333
        result = self.run_bzr("status --short -r 0..1")[0]
 
334
        self.assertContainsRe(result, "[+]N  hello.txt\n")
 
335
 
 
336
        self.build_tree(['world.txt'])
 
337
        result = self.run_bzr("status --short -r 0")[0]
 
338
        self.assertContainsRe(result, "[+]N  hello.txt\n" \
 
339
                                      "[?]   world.txt\n")
 
340
        result2 = self.run_bzr("status --short -r 0..")[0]
 
341
        self.assertEquals(result2, result)
 
342
 
 
343
    def test_status_versioned(self):
 
344
        self.run_bzr("init")
 
345
 
 
346
        self.build_tree(['hello.txt'])
 
347
        result = self.run_bzr("status --versioned")[0]
 
348
        self.assertNotContainsRe(result, "unknown:\n  hello.txt\n")
 
349
 
 
350
        self.run_bzr("add hello.txt")
 
351
        result = self.run_bzr("status --versioned")[0]
 
352
        self.assertContainsRe(result, "added:\n  hello.txt\n")
 
353
 
 
354
        self.run_bzr("commit -m added")
 
355
        result = self.run_bzr("status --versioned -r 0..1")[0]
 
356
        self.assertContainsRe(result, "added:\n  hello.txt\n")
 
357
 
 
358
        self.build_tree(['world.txt'])
 
359
        result = self.run_bzr("status --versioned -r 0")[0]
 
360
        self.assertContainsRe(result, "added:\n  hello.txt\n")
 
361
        self.assertNotContainsRe(result, "unknown:\n  world.txt\n")
 
362
        result2 = self.run_bzr("status --versioned -r 0..")[0]
 
363
        self.assertEquals(result2, result)
 
364
 
 
365
    def assertStatusContains(self, pattern):
 
366
        """Run status, and assert it contains the given pattern"""
 
367
        result = self.run_bzr("status --short")[0]
 
368
        self.assertContainsRe(result, pattern)
 
369
 
 
370
    def test_kind_change_short(self):
 
371
        tree = self.make_branch_and_tree('.')
 
372
        self.build_tree(['file'])
 
373
        tree.add('file')
 
374
        tree.commit('added file')
 
375
        unlink('file')
 
376
        self.build_tree(['file/'])
 
377
        self.assertStatusContains('K  file => file/')
 
378
        tree.rename_one('file', 'directory')
 
379
        self.assertStatusContains('RK  file => directory/')
 
380
        rmdir('directory')
 
381
        self.assertStatusContains('RD  file => directory')
 
382
 
 
383
 
 
384
class TestStatusEncodings(TestCaseWithTransport):
 
385
    
 
386
    def setUp(self):
 
387
        TestCaseWithTransport.setUp(self)
 
388
        self.user_encoding = bzrlib.user_encoding
 
389
        self.stdout = sys.stdout
 
390
 
 
391
    def tearDown(self):
 
392
        bzrlib.user_encoding = self.user_encoding
 
393
        sys.stdout = self.stdout
 
394
        TestCaseWithTransport.tearDown(self)
 
395
 
 
396
    def make_uncommitted_tree(self):
 
397
        """Build a branch with uncommitted unicode named changes in the cwd."""
 
398
        working_tree = self.make_branch_and_tree(u'.')
 
399
        filename = u'hell\u00d8'
 
400
        try:
 
401
            self.build_tree_contents([(filename, 'contents of hello')])
 
402
        except UnicodeEncodeError:
 
403
            raise TestSkipped("can't build unicode working tree in "
 
404
                "filesystem encoding %s" % sys.getfilesystemencoding())
 
405
        working_tree.add(filename)
 
406
        return working_tree
 
407
 
 
408
    def test_stdout_ascii(self):
 
409
        sys.stdout = StringIO()
 
410
        bzrlib.user_encoding = 'ascii'
 
411
        working_tree = self.make_uncommitted_tree()
 
412
        stdout, stderr = self.run_bzr("status")
 
413
 
 
414
        self.assertEquals(stdout, """\
 
415
added:
 
416
  hell?
 
417
""")
 
418
 
 
419
    def test_stdout_latin1(self):
 
420
        sys.stdout = StringIO()
 
421
        bzrlib.user_encoding = 'latin-1'
 
422
        working_tree = self.make_uncommitted_tree()
 
423
        stdout, stderr = self.run_bzr('status')
 
424
 
 
425
        self.assertEquals(stdout, u"""\
 
426
added:
 
427
  hell\u00d8
 
428
""".encode('latin-1'))
49
429