~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

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

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2006-07-12 12:36:57 UTC
  • mfrom: (1732.3.4 bzr.revnoX)
  • Revision ID: pqm@pqm.ubuntu.com-20060712123657-365eeb32b69308bf
(matthieu) revno:x:url revision spec

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005-2010 Canonical Ltd
2
 
#
 
1
# Copyright (C) 2005, 2006 by 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
 
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
16
 
17
17
"""Tests of status command.
18
18
 
19
19
Most of these depend on the particular formatting used.
20
 
As such they really are blackbox tests even though some of the
 
20
As such they really are blackbox tests even though some of the 
21
21
tests are not using self.capture. If we add tests for the programmatic
22
22
interface later, they will be non blackbox tests.
23
23
"""
24
24
 
25
25
from cStringIO import StringIO
26
26
import codecs
27
 
from os import mkdir, chdir, rmdir, unlink
 
27
from os import mkdir, chdir
28
28
import sys
29
29
from tempfile import TemporaryFile
30
30
 
31
 
from bzrlib import (
32
 
    bzrdir,
33
 
    conflicts,
34
 
    errors,
35
 
    osutils,
36
 
    status,
37
 
    )
38
31
import bzrlib.branch
 
32
from bzrlib.builtins import merge
 
33
import bzrlib.bzrdir as bzrdir
 
34
import bzrlib.errors as errors
39
35
from bzrlib.osutils import pathjoin
40
36
from bzrlib.revisionspec import RevisionSpec
41
37
from bzrlib.status import show_tree_status
44
40
 
45
41
 
46
42
class BranchStatus(TestCaseWithTransport):
47
 
 
48
 
    def setUp(self):
49
 
        super(BranchStatus, self).setUp()
50
 
        # As TestCase.setUp clears all hooks, we install this default
51
 
        # post_status hook handler for the test.
52
 
        status.hooks.install_named_hook('post_status',
53
 
            status._show_shelve_summary,
54
 
            'bzr status')
55
 
 
56
 
    def assertStatus(self, expected_lines, working_tree,
57
 
        revision=None, short=False, pending=True, verbose=False):
58
 
        """Run status in working_tree and look for output.
59
 
 
60
 
        :param expected_lines: The lines to look for.
61
 
        :param working_tree: The tree to run status in.
62
 
        """
63
 
        output_string = self.status_string(working_tree, revision, short,
64
 
                pending, verbose)
65
 
        self.assertEqual(expected_lines, output_string.splitlines(True))
66
 
 
67
 
    def status_string(self, wt, revision=None, short=False, pending=True,
68
 
        verbose=False):
69
 
        # use a real file rather than StringIO because it doesn't handle
70
 
        # Unicode very well.
71
 
        tof = codecs.getwriter('utf-8')(TemporaryFile())
72
 
        show_tree_status(wt, to_file=tof, revision=revision, short=short,
73
 
                show_pending=pending, verbose=verbose)
74
 
        tof.seek(0)
75
 
        return tof.read().decode('utf-8')
76
 
 
77
 
    def test_branch_status(self):
 
43
    
 
44
    def test_branch_status(self): 
78
45
        """Test basic branch status"""
79
46
        wt = self.make_branch_and_tree('.')
80
 
 
81
 
        # status with no commits or files - it must
82
 
        # work and show no output. We do this with no
83
 
        # commits to be sure that it's not going to fail
84
 
        # as a corner case.
85
 
        self.assertStatus([], wt)
86
 
 
 
47
        b = wt.branch
 
48
 
 
49
        # status with nothing
 
50
        tof = StringIO()
 
51
        show_tree_status(wt, to_file=tof)
 
52
        self.assertEquals(tof.getvalue(), "")
 
53
 
 
54
        tof = StringIO()
87
55
        self.build_tree(['hello.c', 'bye.c'])
88
 
        self.assertStatus([
89
 
                'unknown:\n',
90
 
                '  bye.c\n',
91
 
                '  hello.c\n',
92
 
            ],
93
 
            wt)
94
 
        self.assertStatus([
95
 
                '?   bye.c\n',
96
 
                '?   hello.c\n',
97
 
            ],
98
 
            wt, short=True)
99
 
 
100
 
        # add a commit to allow showing pending merges.
101
 
        wt.commit('create a parent to allow testing merge output')
102
 
 
103
 
        wt.add_parent_tree_id('pending@pending-0-0')
104
 
        self.assertStatus([
105
 
                'unknown:\n',
106
 
                '  bye.c\n',
107
 
                '  hello.c\n',
108
 
                'pending merge tips: (use -v to see all merge revisions)\n',
109
 
                '  (ghost) pending@pending-0-0\n',
110
 
            ],
111
 
            wt)
112
 
        self.assertStatus([
113
 
                'unknown:\n',
114
 
                '  bye.c\n',
115
 
                '  hello.c\n',
116
 
                'pending merges:\n',
117
 
                '  (ghost) pending@pending-0-0\n',
118
 
            ],
119
 
            wt, verbose=True)
120
 
        self.assertStatus([
121
 
                '?   bye.c\n',
122
 
                '?   hello.c\n',
123
 
                'P   (ghost) pending@pending-0-0\n',
124
 
            ],
125
 
            wt, short=True)
126
 
        self.assertStatus([
127
 
                'unknown:\n',
128
 
                '  bye.c\n',
129
 
                '  hello.c\n',
130
 
            ],
131
 
            wt, pending=False)
132
 
        self.assertStatus([
133
 
                '?   bye.c\n',
134
 
                '?   hello.c\n',
135
 
            ],
136
 
            wt, short=True, pending=False)
 
56
        wt.add_pending_merge('pending@pending-0-0')
 
57
        show_tree_status(wt, to_file=tof)
 
58
        tof.seek(0)
 
59
        self.assertEquals(tof.readlines(),
 
60
                          ['unknown:\n',
 
61
                           '  bye.c\n',
 
62
                           '  hello.c\n',
 
63
                           'pending merges:\n',
 
64
                           '  pending@pending-0-0\n'
 
65
                           ])
137
66
 
138
67
    def test_branch_status_revisions(self):
139
68
        """Tests branch status with revisions"""
140
69
        wt = self.make_branch_and_tree('.')
 
70
        b = wt.branch
141
71
 
 
72
        tof = StringIO()
142
73
        self.build_tree(['hello.c', 'bye.c'])
143
74
        wt.add('hello.c')
144
75
        wt.add('bye.c')
145
76
        wt.commit('Test message')
146
77
 
147
 
        revs = [RevisionSpec.from_string('0')]
148
 
        self.assertStatus([
149
 
                'added:\n',
150
 
                '  bye.c\n',
151
 
                '  hello.c\n'
152
 
            ],
153
 
            wt,
154
 
            revision=revs)
 
78
        tof = StringIO()
 
79
        revs =[]
 
80
        revs.append(RevisionSpec(0))
 
81
        
 
82
        show_tree_status(wt, to_file=tof, revision=revs)
 
83
        
 
84
        tof.seek(0)
 
85
        self.assertEquals(tof.readlines(),
 
86
                          ['added:\n',
 
87
                           '  bye.c\n',
 
88
                           '  hello.c\n'])
155
89
 
156
90
        self.build_tree(['more.c'])
157
91
        wt.add('more.c')
158
92
        wt.commit('Another test message')
 
93
        
 
94
        tof = StringIO()
 
95
        revs.append(RevisionSpec(1))
 
96
        
 
97
        show_tree_status(wt, to_file=tof, revision=revs)
 
98
        
 
99
        tof.seek(0)
 
100
        self.assertEquals(tof.readlines(),
 
101
                          ['added:\n',
 
102
                           '  bye.c\n',
 
103
                           '  hello.c\n'])
159
104
 
160
 
        revs.append(RevisionSpec.from_string('1'))
161
 
        self.assertStatus([
162
 
                'added:\n',
163
 
                '  bye.c\n',
164
 
                '  hello.c\n',
165
 
            ],
166
 
            wt,
167
 
            revision=revs)
 
105
    def status_string(self, wt):
 
106
        # use a real file rather than StringIO because it doesn't handle
 
107
        # Unicode very well.
 
108
        tof = codecs.getwriter('utf-8')(TemporaryFile())
 
109
        show_tree_status(wt, to_file=tof)
 
110
        tof.seek(0)
 
111
        return tof.read().decode('utf-8')
168
112
 
169
113
    def test_pending(self):
170
114
        """Pending merges display works, including Unicode"""
176
120
        b_2 = b_2_dir.open_branch()
177
121
        wt2 = b_2_dir.open_workingtree()
178
122
        wt.commit(u"\N{TIBETAN DIGIT TWO} Empty commit 2")
179
 
        wt2.merge_from_branch(wt.branch)
180
 
        message = self.status_string(wt2, verbose=True)
181
 
        self.assertStartsWith(message, "pending merges:\n")
182
 
        self.assertEndsWith(message, "Empty commit 2\n")
 
123
        merge(["./branch", -1], [None, None], this_dir = './copy')
 
124
        message = self.status_string(wt2)
 
125
        self.assert_(message.startswith("pending merges:\n"))
 
126
        self.assert_(message.endswith("Empty commit 2\n")) 
183
127
        wt2.commit("merged")
184
128
        # must be long to make sure we see elipsis at the end
185
 
        wt.commit("Empty commit 3 " +
186
 
                   "blah blah blah blah " * 100)
187
 
        wt2.merge_from_branch(wt.branch)
188
 
        message = self.status_string(wt2, verbose=True)
189
 
        self.assertStartsWith(message, "pending merges:\n")
 
129
        wt.commit("Empty commit 3 " + 
 
130
                   "blah blah blah blah " * 10)
 
131
        merge(["./branch", -1], [None, None], this_dir = './copy')
 
132
        message = self.status_string(wt2)
 
133
        self.assert_(message.startswith("pending merges:\n"))
190
134
        self.assert_("Empty commit 3" in message)
191
 
        self.assertEndsWith(message, "...\n")
192
 
 
193
 
    def test_tree_status_ignores(self):
194
 
        """Tests branch status with ignores"""
195
 
        wt = self.make_branch_and_tree('.')
196
 
        self.run_bzr('ignore *~')
197
 
        wt.commit('commit .bzrignore')
198
 
        self.build_tree(['foo.c', 'foo.c~'])
199
 
        self.assertStatus([
200
 
                'unknown:\n',
201
 
                '  foo.c\n',
202
 
                ],
203
 
                wt)
204
 
        self.assertStatus([
205
 
                '?   foo.c\n',
206
 
                ],
207
 
                wt, short=True)
208
 
 
209
 
    def test_tree_status_specific_files(self):
 
135
        self.assert_(message.endswith("...\n")) 
 
136
 
 
137
    def test_branch_status_specific_files(self): 
210
138
        """Tests branch status with given specific files"""
211
139
        wt = self.make_branch_and_tree('.')
212
140
        b = wt.branch
215
143
        wt.add('directory')
216
144
        wt.add('test.c')
217
145
        wt.commit('testing')
218
 
 
219
 
        self.assertStatus([
220
 
                'unknown:\n',
221
 
                '  bye.c\n',
222
 
                '  dir2/\n',
223
 
                '  directory/hello.c\n'
224
 
                ],
225
 
                wt)
226
 
 
227
 
        self.assertStatus([
228
 
                '?   bye.c\n',
229
 
                '?   dir2/\n',
230
 
                '?   directory/hello.c\n'
231
 
                ],
232
 
                wt, short=True)
233
 
 
 
146
        
234
147
        tof = StringIO()
 
148
        show_tree_status(wt, to_file=tof)
 
149
        tof.seek(0)
 
150
        self.assertEquals(tof.readlines(),
 
151
                          ['unknown:\n',
 
152
                           '  bye.c\n',
 
153
                           '  dir2\n',
 
154
                           '  directory/hello.c\n'
 
155
                           ])
 
156
 
235
157
        self.assertRaises(errors.PathsDoNotExist,
236
158
                          show_tree_status,
237
 
                          wt, specific_files=['bye.c','test.c','absent.c'],
 
159
                          wt, specific_files=['bye.c','test.c','absent.c'], 
238
160
                          to_file=tof)
239
 
 
 
161
        
240
162
        tof = StringIO()
241
163
        show_tree_status(wt, specific_files=['directory'], to_file=tof)
242
164
        tof.seek(0)
245
167
                           '  directory/hello.c\n'
246
168
                           ])
247
169
        tof = StringIO()
248
 
        show_tree_status(wt, specific_files=['directory'], to_file=tof,
249
 
                         short=True)
250
 
        tof.seek(0)
251
 
        self.assertEquals(tof.readlines(), ['?   directory/hello.c\n'])
252
 
 
253
 
        tof = StringIO()
254
170
        show_tree_status(wt, specific_files=['dir2'], to_file=tof)
255
171
        tof.seek(0)
256
172
        self.assertEquals(tof.readlines(),
257
173
                          ['unknown:\n',
258
 
                           '  dir2/\n'
 
174
                           '  dir2\n'
259
175
                           ])
260
 
        tof = StringIO()
261
 
        show_tree_status(wt, specific_files=['dir2'], to_file=tof, short=True)
262
 
        tof.seek(0)
263
 
        self.assertEquals(tof.readlines(), ['?   dir2/\n'])
264
 
 
265
 
        tof = StringIO()
266
 
        revs = [RevisionSpec.from_string('0'), RevisionSpec.from_string('1')]
267
 
        show_tree_status(wt, specific_files=['test.c'], to_file=tof,
268
 
                         short=True, revision=revs)
269
 
        tof.seek(0)
270
 
        self.assertEquals(tof.readlines(), ['+N  test.c\n'])
271
 
 
272
 
    def test_specific_files_conflicts(self):
273
 
        tree = self.make_branch_and_tree('.')
274
 
        self.build_tree(['dir2/'])
275
 
        tree.add('dir2')
276
 
        tree.commit('added dir2')
277
 
        tree.set_conflicts(conflicts.ConflictList(
278
 
            [conflicts.ContentsConflict('foo')]))
279
 
        tof = StringIO()
280
 
        show_tree_status(tree, specific_files=['dir2'], to_file=tof)
281
 
        self.assertEqualDiff('', tof.getvalue())
282
 
        tree.set_conflicts(conflicts.ConflictList(
283
 
            [conflicts.ContentsConflict('dir2')]))
284
 
        tof = StringIO()
285
 
        show_tree_status(tree, specific_files=['dir2'], to_file=tof)
286
 
        self.assertEqualDiff('conflicts:\n  Contents conflict in dir2\n',
287
 
                             tof.getvalue())
288
 
 
289
 
        tree.set_conflicts(conflicts.ConflictList(
290
 
            [conflicts.ContentsConflict('dir2/file1')]))
291
 
        tof = StringIO()
292
 
        show_tree_status(tree, specific_files=['dir2'], to_file=tof)
293
 
        self.assertEqualDiff('conflicts:\n  Contents conflict in dir2/file1\n',
294
 
                             tof.getvalue())
295
 
 
296
 
    def _prepare_nonexistent(self):
297
 
        wt = self.make_branch_and_tree('.')
298
 
        self.assertStatus([], wt)
299
 
        self.build_tree(['FILE_A', 'FILE_B', 'FILE_C', 'FILE_D', 'FILE_E', ])
300
 
        wt.add('FILE_A')
301
 
        wt.add('FILE_B')
302
 
        wt.add('FILE_C')
303
 
        wt.add('FILE_D')
304
 
        wt.add('FILE_E')
305
 
        wt.commit('Create five empty files.')
306
 
        open('FILE_B', 'w').write('Modification to file FILE_B.')
307
 
        open('FILE_C', 'w').write('Modification to file FILE_C.')
308
 
        unlink('FILE_E')  # FILE_E will be versioned but missing
309
 
        open('FILE_Q', 'w').write('FILE_Q is added but not committed.')
310
 
        wt.add('FILE_Q')  # FILE_Q will be added but not committed
311
 
        open('UNVERSIONED_BUT_EXISTING', 'w')
312
 
        return wt
313
176
 
314
177
    def test_status_nonexistent_file(self):
315
178
        # files that don't exist in either the basis tree or working tree
316
179
        # should give an error
317
 
        wt = self._prepare_nonexistent()
318
 
        self.assertStatus([
319
 
            'removed:\n',
320
 
            '  FILE_E\n',
321
 
            'added:\n',
322
 
            '  FILE_Q\n',
323
 
            'modified:\n',
324
 
            '  FILE_B\n',
325
 
            '  FILE_C\n',
326
 
            'unknown:\n',
327
 
            '  UNVERSIONED_BUT_EXISTING\n',
328
 
            ],
329
 
            wt)
330
 
        self.assertStatus([
331
 
            ' M  FILE_B\n',
332
 
            ' M  FILE_C\n',
333
 
            ' D  FILE_E\n',
334
 
            '+N  FILE_Q\n',
335
 
            '?   UNVERSIONED_BUT_EXISTING\n',
336
 
            ],
337
 
            wt, short=True)
338
 
 
339
 
        # Okay, everything's looking good with the existent files.
340
 
        # Let's see what happens when we throw in non-existent files.
341
 
 
342
 
        # bzr st [--short] NONEXISTENT '
343
 
        expected = [
344
 
          'nonexistent:\n',
345
 
          '  NONEXISTENT\n',
346
 
          ]
347
 
        out, err = self.run_bzr('status NONEXISTENT', retcode=3)
348
 
        self.assertEqual(expected, out.splitlines(True))
349
 
        self.assertContainsRe(err,
350
 
                              r'.*ERROR: Path\(s\) do not exist: '
351
 
                              'NONEXISTENT.*')
352
 
        expected = [
353
 
          'X:   NONEXISTENT\n',
354
 
          ]
355
 
        out, err = self.run_bzr('status --short NONEXISTENT', retcode=3)
356
 
        self.assertContainsRe(err,
357
 
                              r'.*ERROR: Path\(s\) do not exist: '
358
 
                              'NONEXISTENT.*')
359
 
 
360
 
    def test_status_nonexistent_file_with_others(self):
361
 
        # bzr st [--short] NONEXISTENT ...others..
362
 
        wt = self._prepare_nonexistent()
363
 
        expected = [
364
 
          'removed:\n',
365
 
          '  FILE_E\n',
366
 
          'modified:\n',
367
 
          '  FILE_B\n',
368
 
          '  FILE_C\n',
369
 
          'nonexistent:\n',
370
 
          '  NONEXISTENT\n',
371
 
          ]
372
 
        out, err = self.run_bzr('status NONEXISTENT '
373
 
                                'FILE_A FILE_B FILE_C FILE_D FILE_E',
374
 
                                retcode=3)
375
 
        self.assertEqual(expected, out.splitlines(True))
376
 
        self.assertContainsRe(err,
377
 
                              r'.*ERROR: Path\(s\) do not exist: '
378
 
                              'NONEXISTENT.*')
379
 
        expected = [
380
 
          ' D  FILE_E\n',
381
 
          ' M  FILE_C\n',
382
 
          ' M  FILE_B\n',
383
 
          'X   NONEXISTENT\n',
384
 
          ]
385
 
        out, err = self.run_bzr('status --short NONEXISTENT '
386
 
                                'FILE_A FILE_B FILE_C FILE_D FILE_E',
387
 
                                retcode=3)
388
 
        self.assertEqual(expected, out.splitlines(True))
389
 
        self.assertContainsRe(err,
390
 
                              r'.*ERROR: Path\(s\) do not exist: '
391
 
                              'NONEXISTENT.*')
392
 
 
393
 
    def test_status_multiple_nonexistent_files(self):
394
 
        # bzr st [--short] NONEXISTENT ... ANOTHER_NONEXISTENT ...
395
 
        wt = self._prepare_nonexistent()
396
 
        expected = [
397
 
          'removed:\n',
398
 
          '  FILE_E\n',
399
 
          'modified:\n',
400
 
          '  FILE_B\n',
401
 
          '  FILE_C\n',
402
 
          'nonexistent:\n',
403
 
          '  ANOTHER_NONEXISTENT\n',
404
 
          '  NONEXISTENT\n',
405
 
          ]
406
 
        out, err = self.run_bzr('status NONEXISTENT '
407
 
                                'FILE_A FILE_B ANOTHER_NONEXISTENT '
408
 
                                'FILE_C FILE_D FILE_E', retcode=3)
409
 
        self.assertEqual(expected, out.splitlines(True))
410
 
        self.assertContainsRe(err,
411
 
                              r'.*ERROR: Path\(s\) do not exist: '
412
 
                              'ANOTHER_NONEXISTENT NONEXISTENT.*')
413
 
        expected = [
414
 
          ' D  FILE_E\n',
415
 
          ' M  FILE_C\n',
416
 
          ' M  FILE_B\n',
417
 
          'X   ANOTHER_NONEXISTENT\n',
418
 
          'X   NONEXISTENT\n',
419
 
          ]
420
 
        out, err = self.run_bzr('status --short NONEXISTENT '
421
 
                                'FILE_A FILE_B ANOTHER_NONEXISTENT '
422
 
                                'FILE_C FILE_D FILE_E', retcode=3)
423
 
        self.assertEqual(expected, out.splitlines(True))
424
 
        self.assertContainsRe(err,
425
 
                              r'.*ERROR: Path\(s\) do not exist: '
426
 
                              'ANOTHER_NONEXISTENT NONEXISTENT.*')
427
 
 
428
 
    def test_status_nonexistent_file_with_unversioned(self):
429
 
        # bzr st [--short] NONEXISTENT A B UNVERSIONED_BUT_EXISTING C D E Q
430
 
        wt = self._prepare_nonexistent()
431
 
        expected = [
432
 
          'removed:\n',
433
 
          '  FILE_E\n',
434
 
          'added:\n',
435
 
          '  FILE_Q\n',
436
 
          'modified:\n',
437
 
          '  FILE_B\n',
438
 
          '  FILE_C\n',
439
 
          'unknown:\n',
440
 
          '  UNVERSIONED_BUT_EXISTING\n',
441
 
          'nonexistent:\n',
442
 
          '  NONEXISTENT\n',
443
 
          ]
444
 
        out, err = self.run_bzr('status NONEXISTENT '
445
 
                                'FILE_A FILE_B UNVERSIONED_BUT_EXISTING '
446
 
                                'FILE_C FILE_D FILE_E FILE_Q', retcode=3)
447
 
        self.assertEqual(expected, out.splitlines(True))
448
 
        self.assertContainsRe(err,
449
 
                              r'.*ERROR: Path\(s\) do not exist: '
450
 
                              'NONEXISTENT.*')
451
 
        expected = [
452
 
          '+N  FILE_Q\n',
453
 
          '?   UNVERSIONED_BUT_EXISTING\n',
454
 
          ' D  FILE_E\n',
455
 
          ' M  FILE_C\n',
456
 
          ' M  FILE_B\n',
457
 
          'X   NONEXISTENT\n',
458
 
          ]
459
 
        out, err = self.run_bzr('status --short NONEXISTENT '
460
 
                                'FILE_A FILE_B UNVERSIONED_BUT_EXISTING '
461
 
                                'FILE_C FILE_D FILE_E FILE_Q', retcode=3)
462
 
        self.assertEqual(expected, out.splitlines(True))
463
 
        self.assertContainsRe(err,
464
 
                              r'.*ERROR: Path\(s\) do not exist: '
465
 
                              'NONEXISTENT.*')
466
 
 
467
 
    def test_status_out_of_date(self):
468
 
        """Simulate status of out-of-date tree after remote push"""
469
 
        tree = self.make_branch_and_tree('.')
470
 
        self.build_tree_contents([('a', 'foo\n')])
471
 
        tree.lock_write()
472
 
        try:
473
 
            tree.add(['a'])
474
 
            tree.commit('add test file')
475
 
            # simulate what happens after a remote push
476
 
            tree.set_last_revision("0")
477
 
        finally:
478
 
            # before run another commands we should unlock tree
479
 
            tree.unlock()
480
 
        out, err = self.run_bzr('status')
481
 
        self.assertEqual("working tree is out of date, run 'bzr update'\n",
482
 
                         err)
483
 
 
484
 
    def test_status_on_ignored(self):
485
 
        """Tests branch status on an unversioned file which is considered ignored.
486
 
 
487
 
        See https://bugs.launchpad.net/bzr/+bug/40103
488
 
        """
489
 
        tree = self.make_branch_and_tree('.')
490
 
 
491
 
        self.build_tree(['test1.c', 'test1.c~', 'test2.c~'])
492
 
        result = self.run_bzr('status')[0]
493
 
        self.assertContainsRe(result, "unknown:\n  test1.c\n")
494
 
        short_result = self.run_bzr('status --short')[0]
495
 
        self.assertContainsRe(short_result, "\?   test1.c\n")
496
 
 
497
 
        result = self.run_bzr('status test1.c')[0]
498
 
        self.assertContainsRe(result, "unknown:\n  test1.c\n")
499
 
        short_result = self.run_bzr('status --short test1.c')[0]
500
 
        self.assertContainsRe(short_result, "\?   test1.c\n")
501
 
 
502
 
        result = self.run_bzr('status test1.c~')[0]
503
 
        self.assertContainsRe(result, "ignored:\n  test1.c~\n")
504
 
        short_result = self.run_bzr('status --short test1.c~')[0]
505
 
        self.assertContainsRe(short_result, "I   test1.c~\n")
506
 
 
507
 
        result = self.run_bzr('status test1.c~ test2.c~')[0]
508
 
        self.assertContainsRe(result, "ignored:\n  test1.c~\n  test2.c~\n")
509
 
        short_result = self.run_bzr('status --short test1.c~ test2.c~')[0]
510
 
        self.assertContainsRe(short_result, "I   test1.c~\nI   test2.c~\n")
511
 
 
512
 
        result = self.run_bzr('status test1.c test1.c~ test2.c~')[0]
513
 
        self.assertContainsRe(result, "unknown:\n  test1.c\nignored:\n  test1.c~\n  test2.c~\n")
514
 
        short_result = self.run_bzr('status --short test1.c test1.c~ test2.c~')[0]
515
 
        self.assertContainsRe(short_result, "\?   test1.c\nI   test1.c~\nI   test2.c~\n")
516
 
 
517
 
    def test_status_write_lock(self):
518
 
        """Test that status works without fetching history and
519
 
        having a write lock.
520
 
 
521
 
        See https://bugs.launchpad.net/bzr/+bug/149270
522
 
        """
523
 
        mkdir('branch1')
524
 
        wt = self.make_branch_and_tree('branch1')
525
 
        b = wt.branch
526
 
        wt.commit('Empty commit 1')
527
 
        wt2 = b.bzrdir.sprout('branch2').open_workingtree()
528
 
        wt2.commit('Empty commit 2')
529
 
        out, err = self.run_bzr('status branch1 -rbranch:branch2')
530
 
        self.assertEqual('', out)
531
 
 
532
 
    def test_status_with_shelves(self):
533
 
        """Ensure that _show_shelve_summary handler works.
534
 
        """
535
180
        wt = self.make_branch_and_tree('.')
536
 
        self.build_tree(['hello.c'])
537
 
        wt.add('hello.c')
538
 
        self.run_bzr(['shelve', '--all', '-m', 'foo'])
539
 
        self.build_tree(['bye.c'])
540
 
        wt.add('bye.c')
541
 
        self.assertStatus([
542
 
                'added:\n',
543
 
                '  bye.c\n',
544
 
                '1 shelves exist. See "bzr shelve --list" for details.\n',
545
 
            ],
546
 
            wt)
 
181
        out, err = self.run_bzr('status', 'does-not-exist', retcode=3)
 
182
        self.assertContainsRe(err, r'do not exist.*does-not-exist')
547
183
 
548
184
 
549
185
class CheckoutStatus(BranchStatus):
552
188
        super(CheckoutStatus, self).setUp()
553
189
        mkdir('codir')
554
190
        chdir('codir')
555
 
 
 
191
        
556
192
    def make_branch_and_tree(self, relpath):
557
193
        source = self.make_branch(pathjoin('..', relpath))
558
194
        checkout = bzrdir.BzrDirMetaFormat1().initialize(relpath)
559
 
        bzrlib.branch.BranchReferenceFormat().initialize(checkout,
560
 
            target_branch=source)
 
195
        bzrlib.branch.BranchReferenceFormat().initialize(checkout, source)
561
196
        return checkout.create_workingtree()
562
197
 
563
198
 
564
199
class TestStatus(TestCaseWithTransport):
565
200
 
566
 
    def test_status_plain(self):
567
 
        tree = self.make_branch_and_tree('.')
568
 
 
569
 
        self.build_tree(['hello.txt'])
570
 
        result = self.run_bzr("status")[0]
571
 
        self.assertContainsRe(result, "unknown:\n  hello.txt\n")
572
 
 
573
 
        tree.add("hello.txt")
574
 
        result = self.run_bzr("status")[0]
575
 
        self.assertContainsRe(result, "added:\n  hello.txt\n")
576
 
 
577
 
        tree.commit(message="added")
578
 
        result = self.run_bzr("status -r 0..1")[0]
579
 
        self.assertContainsRe(result, "added:\n  hello.txt\n")
580
 
 
581
 
        result = self.run_bzr("status -c 1")[0]
582
 
        self.assertContainsRe(result, "added:\n  hello.txt\n")
583
 
 
584
 
        self.build_tree(['world.txt'])
585
 
        result = self.run_bzr("status -r 0")[0]
586
 
        self.assertContainsRe(result, "added:\n  hello.txt\n" \
587
 
                                      "unknown:\n  world.txt\n")
588
 
        result2 = self.run_bzr("status -r 0..")[0]
589
 
        self.assertEquals(result2, result)
590
 
 
591
 
    def test_status_short(self):
592
 
        tree = self.make_branch_and_tree('.')
593
 
 
594
 
        self.build_tree(['hello.txt'])
595
 
        result = self.run_bzr("status --short")[0]
596
 
        self.assertContainsRe(result, "[?]   hello.txt\n")
597
 
 
598
 
        tree.add("hello.txt")
599
 
        result = self.run_bzr("status --short")[0]
600
 
        self.assertContainsRe(result, "[+]N  hello.txt\n")
601
 
 
602
 
        tree.commit(message="added")
603
 
        result = self.run_bzr("status --short -r 0..1")[0]
604
 
        self.assertContainsRe(result, "[+]N  hello.txt\n")
605
 
 
606
 
        self.build_tree(['world.txt'])
607
 
        result = self.run_bzr("status --short -r 0")[0]
608
 
        self.assertContainsRe(result, "[+]N  hello.txt\n" \
609
 
                                      "[?]   world.txt\n")
610
 
        result2 = self.run_bzr("status --short -r 0..")[0]
611
 
        self.assertEquals(result2, result)
612
 
 
613
 
    def test_status_versioned(self):
614
 
        tree = self.make_branch_and_tree('.')
615
 
 
616
 
        self.build_tree(['hello.txt'])
617
 
        result = self.run_bzr("status --versioned")[0]
618
 
        self.assertNotContainsRe(result, "unknown:\n  hello.txt\n")
619
 
 
620
 
        tree.add("hello.txt")
621
 
        result = self.run_bzr("status --versioned")[0]
622
 
        self.assertContainsRe(result, "added:\n  hello.txt\n")
623
 
 
624
 
        tree.commit("added")
625
 
        result = self.run_bzr("status --versioned -r 0..1")[0]
626
 
        self.assertContainsRe(result, "added:\n  hello.txt\n")
627
 
 
628
 
        self.build_tree(['world.txt'])
629
 
        result = self.run_bzr("status --versioned -r 0")[0]
630
 
        self.assertContainsRe(result, "added:\n  hello.txt\n")
631
 
        self.assertNotContainsRe(result, "unknown:\n  world.txt\n")
632
 
        result2 = self.run_bzr("status --versioned -r 0..")[0]
633
 
        self.assertEquals(result2, result)
634
 
 
635
 
    def test_status_SV(self):
636
 
        tree = self.make_branch_and_tree('.')
637
 
 
638
 
        self.build_tree(['hello.txt'])
639
 
        result = self.run_bzr("status -SV")[0]
640
 
        self.assertNotContainsRe(result, "hello.txt")
641
 
 
642
 
        tree.add("hello.txt")
643
 
        result = self.run_bzr("status -SV")[0]
644
 
        self.assertContainsRe(result, "[+]N  hello.txt\n")
645
 
 
646
 
        tree.commit(message="added")
647
 
        result = self.run_bzr("status -SV -r 0..1")[0]
648
 
        self.assertContainsRe(result, "[+]N  hello.txt\n")
649
 
 
650
 
        self.build_tree(['world.txt'])
651
 
        result = self.run_bzr("status -SV -r 0")[0]
652
 
        self.assertContainsRe(result, "[+]N  hello.txt\n")
653
 
 
654
 
        result2 = self.run_bzr("status -SV -r 0..")[0]
655
 
        self.assertEquals(result2, result)
656
 
 
657
 
    def assertStatusContains(self, pattern, short=False):
658
 
        """Run status, and assert it contains the given pattern"""
659
 
        if short:
660
 
            result = self.run_bzr("status --short")[0]
661
 
        else:
662
 
            result = self.run_bzr("status")[0]
663
 
        self.assertContainsRe(result, pattern)
664
 
 
665
 
    def test_kind_change_plain(self):
666
 
        tree = self.make_branch_and_tree('.')
667
 
        self.build_tree(['file'])
668
 
        tree.add('file')
669
 
        tree.commit('added file')
670
 
        unlink('file')
671
 
        self.build_tree(['file/'])
672
 
        self.assertStatusContains('kind changed:\n  file \(file => directory\)')
673
 
        tree.rename_one('file', 'directory')
674
 
        self.assertStatusContains('renamed:\n  file/ => directory/\n' \
675
 
                                  'modified:\n  directory/\n')
676
 
        rmdir('directory')
677
 
        self.assertStatusContains('removed:\n  file\n')
678
 
 
679
 
    def test_kind_change_short(self):
680
 
        tree = self.make_branch_and_tree('.')
681
 
        self.build_tree(['file'])
682
 
        tree.add('file')
683
 
        tree.commit('added file')
684
 
        unlink('file')
685
 
        self.build_tree(['file/'])
686
 
        self.assertStatusContains('K  file => file/',
687
 
                                   short=True)
688
 
        tree.rename_one('file', 'directory')
689
 
        self.assertStatusContains('RK  file => directory/',
690
 
                                   short=True)
691
 
        rmdir('directory')
692
 
        self.assertStatusContains('RD  file => directory',
693
 
                                   short=True)
694
 
 
695
 
    def test_status_illegal_revision_specifiers(self):
696
 
        out, err = self.run_bzr('status -r 1..23..123', retcode=3)
697
 
        self.assertContainsRe(err, 'one or two revision specifiers')
698
 
 
699
 
    def test_status_no_pending(self):
700
 
        a_tree = self.make_branch_and_tree('a')
701
 
        self.build_tree(['a/a'])
702
 
        a_tree.add('a')
703
 
        a_tree.commit('a')
704
 
        b_tree = a_tree.bzrdir.sprout('b').open_workingtree()
705
 
        self.build_tree(['b/b'])
706
 
        b_tree.add('b')
707
 
        b_tree.commit('b')
708
 
 
709
 
        self.run_bzr('merge ../b', working_dir='a')
710
 
        out, err = self.run_bzr('status --no-pending', working_dir='a')
711
 
        self.assertEquals(out, "added:\n  b\n")
712
 
 
713
 
    def test_pending_specific_files(self):
714
 
        """With a specific file list, pending merges are not shown."""
715
 
        tree = self.make_branch_and_tree('tree')
716
 
        self.build_tree_contents([('tree/a', 'content of a\n')])
717
 
        tree.add('a')
718
 
        r1_id = tree.commit('one')
719
 
        alt = tree.bzrdir.sprout('alt').open_workingtree()
720
 
        self.build_tree_contents([('alt/a', 'content of a\nfrom alt\n')])
721
 
        alt_id = alt.commit('alt')
722
 
        tree.merge_from_branch(alt.branch)
723
 
        output = self.make_utf8_encoded_stringio()
724
 
        show_tree_status(tree, to_file=output)
725
 
        self.assertContainsRe(output.getvalue(), 'pending merge')
726
 
        out, err = self.run_bzr('status tree/a')
727
 
        self.assertNotContainsRe(out, 'pending merge')
 
201
    def test_status(self):
 
202
        self.run_bzr("init")
 
203
        self.build_tree(['hello.txt'])
 
204
        result = self.run_bzr("status")[0]
 
205
        self.assert_("unknown:\n  hello.txt\n" in result, result)
 
206
        self.run_bzr("add", "hello.txt")
 
207
        result = self.run_bzr("status")[0]
 
208
        self.assert_("added:\n  hello.txt\n" in result, result)
 
209
        self.run_bzr("commit", "-m", "added")
 
210
        result = self.run_bzr("status", "-r", "0..1")[0]
 
211
        self.assert_("added:\n  hello.txt\n" in result, result)
 
212
        self.build_tree(['world.txt'])
 
213
        result = self.run_bzr("status", "-r", "0")[0]
 
214
        self.assert_("added:\n  hello.txt\n" \
 
215
                     "unknown:\n  world.txt\n" in result, result)
 
216
 
 
217
        result2 = self.run_bzr("status", "-r", "0..")[0]
 
218
        self.assertEquals(result2, result)
728
219
 
729
220
 
730
221
class TestStatusEncodings(TestCaseWithTransport):
 
222
    
 
223
    def setUp(self):
 
224
        TestCaseWithTransport.setUp(self)
 
225
        self.user_encoding = bzrlib.user_encoding
 
226
        self.stdout = sys.stdout
 
227
 
 
228
    def tearDown(self):
 
229
        bzrlib.user_encoding = self.user_encoding
 
230
        sys.stdout = self.stdout
 
231
        TestCaseWithTransport.tearDown(self)
731
232
 
732
233
    def make_uncommitted_tree(self):
733
234
        """Build a branch with uncommitted unicode named changes in the cwd."""
742
243
        return working_tree
743
244
 
744
245
    def test_stdout_ascii(self):
745
 
        self.overrideAttr(osutils, '_cached_user_encoding', 'ascii')
 
246
        sys.stdout = StringIO()
 
247
        bzrlib.user_encoding = 'ascii'
746
248
        working_tree = self.make_uncommitted_tree()
747
249
        stdout, stderr = self.run_bzr("status")
748
250
 
752
254
""")
753
255
 
754
256
    def test_stdout_latin1(self):
755
 
        self.overrideAttr(osutils, '_cached_user_encoding', 'latin-1')
 
257
        sys.stdout = StringIO()
 
258
        bzrlib.user_encoding = 'latin-1'
756
259
        working_tree = self.make_uncommitted_tree()
757
260
        stdout, stderr = self.run_bzr('status')
758
261