/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 breezy/tests/blackbox/test_status.py

  • Committer: Jelmer Vernooij
  • Date: 2020-09-02 15:11:17 UTC
  • mto: (7490.40.109 work)
  • mto: This revision was merged to the branch mainline in revision 7526.
  • Revision ID: jelmer@jelmer.uk-20200902151117-jeu7tarbz3dkuju0
Move more transform code.

Show diffs side-by-side

added added

removed removed

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