45
44
class BranchStatus(TestCaseWithTransport):
 
47
46
    def assertStatus(self, expected_lines, working_tree,
 
48
 
        revision=None, short=False, pending=True, verbose=False):
 
 
47
        revision=None, short=False, pending=True):
 
49
48
        """Run status in working_tree and look for output.
 
51
50
        :param expected_lines: The lines to look for.
 
52
51
        :param working_tree: The tree to run status in.
 
54
53
        output_string = self.status_string(working_tree, revision, short,
 
56
55
        self.assertEqual(expected_lines, output_string.splitlines(True))
 
58
 
    def status_string(self, wt, revision=None, short=False, pending=True,
 
 
57
    def status_string(self, wt, revision=None, short=False, pending=True):
 
60
58
        # use a real file rather than StringIO because it doesn't handle
 
61
59
        # Unicode very well.
 
62
60
        tof = codecs.getwriter('utf-8')(TemporaryFile())
 
63
61
        show_tree_status(wt, to_file=tof, revision=revision, short=short,
 
64
 
                show_pending=pending, verbose=verbose)
 
66
64
        return tof.read().decode('utf-8')
 
 
284
274
        self.assertEqualDiff('conflicts:\n  Contents conflict in dir2/file1\n',
 
287
 
    def _prepare_nonexistent(self):
 
288
 
        wt = self.make_branch_and_tree('.')
 
289
 
        self.assertStatus([], wt)
 
290
 
        self.build_tree(['FILE_A', 'FILE_B', 'FILE_C', 'FILE_D', 'FILE_E', ])
 
296
 
        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.')
 
299
 
        unlink('FILE_E')  # FILE_E will be versioned but missing
 
300
 
        open('FILE_Q', 'w').write('FILE_Q is added but not committed.')
 
301
 
        wt.add('FILE_Q')  # FILE_Q will be added but not committed
 
302
 
        open('UNVERSIONED_BUT_EXISTING', 'w')
 
305
277
    def test_status_nonexistent_file(self):
 
306
278
        # files that don't exist in either the basis tree or working tree
 
307
279
        # should give an error
 
308
 
        wt = self._prepare_nonexistent()
 
318
 
            '  UNVERSIONED_BUT_EXISTING\n',
 
326
 
            '?   UNVERSIONED_BUT_EXISTING\n',
 
330
 
        # Okay, everything's looking good with the existent files.
 
331
 
        # Let's see what happens when we throw in non-existent files.
 
333
 
        # bzr st [--short] NONEXISTENT '
 
338
 
        out, err = self.run_bzr('status NONEXISTENT', retcode=3)
 
339
 
        self.assertEqual(expected, out.splitlines(True))
 
340
 
        self.assertContainsRe(err,
 
341
 
                              r'.*ERROR: Path\(s\) do not exist: '
 
346
 
        out, err = self.run_bzr('status --short NONEXISTENT', retcode=3)
 
347
 
        self.assertContainsRe(err,
 
348
 
                              r'.*ERROR: Path\(s\) do not exist: '
 
351
 
    def test_status_nonexistent_file_with_others(self):
 
352
 
        # bzr st [--short] NONEXISTENT ...others..
 
353
 
        wt = self._prepare_nonexistent()
 
363
 
        out, err = self.run_bzr('status NONEXISTENT '
 
364
 
                                'FILE_A FILE_B FILE_C FILE_D FILE_E',
 
366
 
        self.assertEqual(expected, out.splitlines(True))
 
367
 
        self.assertContainsRe(err,
 
368
 
                              r'.*ERROR: Path\(s\) do not exist: '
 
376
 
        out, err = self.run_bzr('status --short NONEXISTENT '
 
377
 
                                'FILE_A FILE_B FILE_C FILE_D FILE_E',
 
379
 
        self.assertEqual(expected, out.splitlines(True))
 
380
 
        self.assertContainsRe(err,
 
381
 
                              r'.*ERROR: Path\(s\) do not exist: '
 
384
 
    def test_status_multiple_nonexistent_files(self):
 
385
 
        # bzr st [--short] NONEXISTENT ... ANOTHER_NONEXISTENT ...
 
386
 
        wt = self._prepare_nonexistent()
 
394
 
          '  ANOTHER_NONEXISTENT\n',
 
397
 
        out, err = self.run_bzr('status NONEXISTENT '
 
398
 
                                'FILE_A FILE_B ANOTHER_NONEXISTENT '
 
399
 
                                'FILE_C FILE_D FILE_E', retcode=3)
 
400
 
        self.assertEqual(expected, out.splitlines(True))
 
401
 
        self.assertContainsRe(err,
 
402
 
                              r'.*ERROR: Path\(s\) do not exist: '
 
403
 
                              'ANOTHER_NONEXISTENT NONEXISTENT.*')
 
408
 
          'X   ANOTHER_NONEXISTENT\n',
 
411
 
        out, err = self.run_bzr('status --short NONEXISTENT '
 
412
 
                                'FILE_A FILE_B ANOTHER_NONEXISTENT '
 
413
 
                                'FILE_C FILE_D FILE_E', retcode=3)
 
414
 
        self.assertEqual(expected, out.splitlines(True))
 
415
 
        self.assertContainsRe(err,
 
416
 
                              r'.*ERROR: Path\(s\) do not exist: '
 
417
 
                              'ANOTHER_NONEXISTENT NONEXISTENT.*')
 
419
 
    def test_status_nonexistent_file_with_unversioned(self):
 
420
 
        # bzr st [--short] NONEXISTENT A B UNVERSIONED_BUT_EXISTING C D E Q
 
421
 
        wt = self._prepare_nonexistent()
 
431
 
          '  UNVERSIONED_BUT_EXISTING\n',
 
435
 
        out, err = self.run_bzr('status NONEXISTENT '
 
436
 
                                'FILE_A FILE_B UNVERSIONED_BUT_EXISTING '
 
437
 
                                'FILE_C FILE_D FILE_E FILE_Q', retcode=3)
 
438
 
        self.assertEqual(expected, out.splitlines(True))
 
439
 
        self.assertContainsRe(err,
 
440
 
                              r'.*ERROR: Path\(s\) do not exist: '
 
444
 
          '?   UNVERSIONED_BUT_EXISTING\n',
 
450
 
        out, err = self.run_bzr('status --short NONEXISTENT '
 
451
 
                                'FILE_A FILE_B UNVERSIONED_BUT_EXISTING '
 
452
 
                                'FILE_C FILE_D FILE_E FILE_Q', retcode=3)
 
453
 
        self.assertEqual(expected, out.splitlines(True))
 
454
 
        self.assertContainsRe(err,
 
455
 
                              r'.*ERROR: Path\(s\) do not exist: '
 
 
280
        wt = self.make_branch_and_tree('.')
 
 
281
        out, err = self.run_bzr('status does-not-exist', retcode=3)
 
 
282
        self.assertContainsRe(err, r'do not exist.*does-not-exist')
 
458
284
    def test_status_out_of_date(self):
 
459
285
        """Simulate status of out-of-date tree after remote push"""
 
 
472
298
        self.assertEqual("working tree is out of date, run 'bzr update'\n",
 
475
 
    def test_status_on_ignored(self):
 
476
 
        """Tests branch status on an unversioned file which is considered ignored.
 
478
 
        See https://bugs.launchpad.net/bzr/+bug/40103
 
480
 
        tree = self.make_branch_and_tree('.')
 
482
 
        self.build_tree(['test1.c', 'test1.c~', 'test2.c~'])
 
483
 
        result = self.run_bzr('status')[0]
 
484
 
        self.assertContainsRe(result, "unknown:\n  test1.c\n")
 
485
 
        short_result = self.run_bzr('status --short')[0]
 
486
 
        self.assertContainsRe(short_result, "\?   test1.c\n")
 
488
 
        result = self.run_bzr('status test1.c')[0]
 
489
 
        self.assertContainsRe(result, "unknown:\n  test1.c\n")
 
490
 
        short_result = self.run_bzr('status --short test1.c')[0]
 
491
 
        self.assertContainsRe(short_result, "\?   test1.c\n")
 
493
 
        result = self.run_bzr('status test1.c~')[0]
 
494
 
        self.assertContainsRe(result, "ignored:\n  test1.c~\n")
 
495
 
        short_result = self.run_bzr('status --short test1.c~')[0]
 
496
 
        self.assertContainsRe(short_result, "I   test1.c~\n")
 
498
 
        result = self.run_bzr('status test1.c~ test2.c~')[0]
 
499
 
        self.assertContainsRe(result, "ignored:\n  test1.c~\n  test2.c~\n")
 
500
 
        short_result = self.run_bzr('status --short test1.c~ test2.c~')[0]
 
501
 
        self.assertContainsRe(short_result, "I   test1.c~\nI   test2.c~\n")
 
503
 
        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")
 
508
 
    def test_status_write_lock(self):
 
509
 
        """Test that status works without fetching history and
 
512
 
        See https://bugs.launchpad.net/bzr/+bug/149270
 
515
 
        wt = self.make_branch_and_tree('branch1')
 
517
 
        wt.commit('Empty commit 1')
 
518
 
        wt2 = b.bzrdir.sprout('branch2').open_workingtree()
 
519
 
        wt2.commit('Empty commit 2')
 
520
 
        out, err = self.run_bzr('status branch1 -rbranch:branch2')
 
521
 
        self.assertEqual('', out)
 
524
302
class CheckoutStatus(BranchStatus):
 
 
629
406
        result2 = self.run_bzr("status -SV -r 0..")[0]
 
630
407
        self.assertEquals(result2, result)
 
632
 
    def assertStatusContains(self, pattern, short=False):
 
 
409
    def assertStatusContains(self, pattern):
 
633
410
        """Run status, and assert it contains the given pattern"""
 
635
 
            result = self.run_bzr("status --short")[0]
 
637
 
            result = self.run_bzr("status")[0]
 
 
411
        result = self.run_bzr("status --short")[0]
 
638
412
        self.assertContainsRe(result, pattern)
 
640
 
    def test_kind_change_plain(self):
 
641
 
        tree = self.make_branch_and_tree('.')
 
642
 
        self.build_tree(['file'])
 
644
 
        tree.commit('added file')
 
646
 
        self.build_tree(['file/'])
 
647
 
        self.assertStatusContains('kind changed:\n  file \(file => directory\)')
 
648
 
        tree.rename_one('file', 'directory')
 
649
 
        self.assertStatusContains('renamed:\n  file/ => directory/\n' \
 
650
 
                                  'modified:\n  directory/\n')
 
652
 
        self.assertStatusContains('removed:\n  file\n')
 
654
414
    def test_kind_change_short(self):
 
655
415
        tree = self.make_branch_and_tree('.')
 
656
416
        self.build_tree(['file'])
 
 
682
439
        b_tree.commit('b')
 
684
 
        self.run_bzr('merge ../b', working_dir='a')
 
685
 
        out, err = self.run_bzr('status --no-pending', working_dir='a')
 
 
442
        self.run_bzr('merge ../b')
 
 
443
        out, err = self.run_bzr('status --no-pending')
 
686
444
        self.assertEquals(out, "added:\n  b\n")
 
688
 
    def test_pending_specific_files(self):
 
689
 
        """With a specific file list, pending merges are not shown."""
 
690
 
        tree = self.make_branch_and_tree('tree')
 
691
 
        self.build_tree_contents([('tree/a', 'content of a\n')])
 
693
 
        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')])
 
696
 
        alt_id = alt.commit('alt')
 
697
 
        tree.merge_from_branch(alt.branch)
 
698
 
        output = self.make_utf8_encoded_stringio()
 
699
 
        show_tree_status(tree, to_file=output)
 
700
 
        self.assertContainsRe(output.getvalue(), 'pending merge')
 
701
 
        out, err = self.run_bzr('status tree/a')
 
702
 
        self.assertNotContainsRe(out, 'pending merge')
 
705
448
class TestStatusEncodings(TestCaseWithTransport):
 
708
451
        TestCaseWithTransport.setUp(self)
 
709
 
        self.user_encoding = osutils._cached_user_encoding
 
 
452
        self.user_encoding = bzrlib.user_encoding
 
710
453
        self.stdout = sys.stdout
 
712
455
    def tearDown(self):
 
713
 
        osutils._cached_user_encoding = self.user_encoding
 
 
456
        bzrlib.user_encoding = self.user_encoding
 
714
457
        sys.stdout = self.stdout
 
715
458
        TestCaseWithTransport.tearDown(self)