55
53
# As TestCase.setUp clears all hooks, we install this default
56
54
# post_status hook handler for the test.
57
55
status.hooks.install_named_hook('post_status',
58
status._show_shelve_summary,
56
status._show_shelve_summary,
61
59
def assertStatus(self, expected_lines, working_tree, specific_files=None,
62
revision=None, short=False, pending=True, verbose=False):
60
revision=None, short=False, pending=True, verbose=False):
63
61
"""Run status in working_tree and look for output.
65
63
:param expected_lines: The lines to look for.
66
64
:param working_tree: The tree to run status in.
68
66
output_string = self.status_string(working_tree, specific_files, revision, short,
70
68
self.assertEqual(expected_lines, output_string.splitlines(True))
72
70
def status_string(self, wt, specific_files=None, revision=None,
73
short=False, pending=True, verbose=False):
71
short=False, pending=True, verbose=False):
74
72
uio = self.make_utf8_encoded_stringio()
75
73
show_tree_status(wt, specific_files=specific_files, to_file=uio,
76
revision=revision, short=short, show_pending=pending,
74
revision=revision, short=short, show_pending=pending,
78
76
return uio.getvalue().decode('utf-8')
80
78
def test_branch_status(self):
90
88
self.build_tree(['hello.c', 'bye.c'])
91
89
self.assertStatus([
97
95
self.assertStatus([
103
101
# add a commit to allow showing pending merges.
104
102
wt.commit('create a parent to allow testing merge output')
106
wt.add_parent_tree_id(b'pending@pending-0-0')
104
wt.add_parent_tree_id('pending@pending-0-0')
107
105
self.assertStatus([
111
'pending merge tips: (use -v to see all merge revisions)\n',
112
' (ghost) pending@pending-0-0\n',
109
'pending merge tips: (use -v to see all merge revisions)\n',
110
' (ghost) pending@pending-0-0\n',
115
113
self.assertStatus([
120
' (ghost) pending@pending-0-0\n',
118
' (ghost) pending@pending-0-0\n',
122
120
wt, verbose=True)
123
121
self.assertStatus([
126
'P (ghost) pending@pending-0-0\n',
124
'P (ghost) pending@pending-0-0\n',
129
127
self.assertStatus([
134
132
wt, pending=False)
135
133
self.assertStatus([
139
137
wt, short=True, pending=False)
185
183
self.assertEndsWith(message, "Empty commit 2\n")
186
184
wt2.commit("merged")
187
185
# must be long to make sure we see elipsis at the end
188
wt.commit("Empty commit 3 "
189
+ "blah blah blah blah " * 100)
186
wt.commit("Empty commit 3 " +
187
"blah blah blah blah " * 100)
190
188
wt2.merge_from_branch(wt.branch)
191
189
message = self.status_string(wt2, verbose=True)
192
190
self.assertStartsWith(message, "pending merges:\n")
200
198
wt.commit('commit .bzrignore')
201
199
self.build_tree(['foo.c', 'foo.c~'])
202
200
self.assertStatus([
207
205
self.assertStatus([
212
210
def test_tree_status_specific_files(self):
213
211
"""Tests branch status with given specific files"""
224
222
unlink('missing.c')
226
224
self.assertStatus([
232
' directory/hello.c\n'
230
' directory/hello.c\n'
236
234
self.assertStatus([
239
'? directory/hello.c\n',
238
'? directory/hello.c\n'
245
243
self.assertRaises(errors.PathsDoNotExist,
246
244
show_tree_status,
247
245
wt, specific_files=['bye.c', 'test.c', 'absent.c'],
251
249
show_tree_status(wt, specific_files=['directory'], to_file=tof)
253
251
self.assertEqual(tof.readlines(),
255
' directory/hello.c\n'
253
' directory/hello.c\n'
258
256
show_tree_status(wt, specific_files=['directory'], to_file=tof,
261
259
self.assertEqual(tof.readlines(), ['? directory/hello.c\n'])
264
262
show_tree_status(wt, specific_files=['dir2'], to_file=tof)
266
264
self.assertEqual(tof.readlines(),
271
269
show_tree_status(wt, specific_files=['dir2'], to_file=tof, short=True)
273
271
self.assertEqual(tof.readlines(), ['? dir2/\n'])
276
274
revs = [RevisionSpec.from_string('0'), RevisionSpec.from_string('1')]
277
275
show_tree_status(wt, specific_files=['test.c'], to_file=tof,
278
276
short=True, revision=revs)
280
278
self.assertEqual(tof.readlines(), ['+N test.c\n'])
283
281
show_tree_status(wt, specific_files=['missing.c'], to_file=tof)
285
283
self.assertEqual(tof.readlines(),
290
288
show_tree_status(wt, specific_files=['missing.c'], to_file=tof,
293
291
self.assertEqual(tof.readlines(),
296
294
def test_specific_files_conflicts(self):
297
295
tree = self.make_branch_and_tree('.')
302
300
[conflicts.ContentsConflict('foo')]))
304
302
show_tree_status(tree, specific_files=['dir2'], to_file=tof)
305
self.assertEqualDiff(b'', tof.getvalue())
303
self.assertEqualDiff('', tof.getvalue())
306
304
tree.set_conflicts(conflicts.ConflictList(
307
305
[conflicts.ContentsConflict('dir2')]))
309
307
show_tree_status(tree, specific_files=['dir2'], to_file=tof)
310
308
self.assertEqualDiff('conflicts:\n Contents conflict in dir2\n',
313
311
tree.set_conflicts(conflicts.ConflictList(
314
312
[conflicts.ContentsConflict('dir2/file1')]))
316
314
show_tree_status(tree, specific_files=['dir2'], to_file=tof)
317
315
self.assertEqualDiff('conflicts:\n Contents conflict in dir2/file1\n',
329
327
wt.commit('Create five empty files.')
330
with open('FILE_B', 'w') as f:
331
f.write('Modification to file FILE_B.')
332
with open('FILE_C', 'w') as f:
333
f.write('Modification to file FILE_C.')
328
with open('FILE_B', 'w') as f: f.write('Modification to file FILE_B.')
329
with open('FILE_C', 'w') as f: f.write('Modification to file FILE_C.')
334
330
unlink('FILE_E') # FILE_E will be versioned but missing
335
with open('FILE_Q', 'w') as f:
336
f.write('FILE_Q is added but not committed.')
331
with open('FILE_Q', 'w') as f: f.write('FILE_Q is added but not committed.')
337
332
wt.add('FILE_Q') # FILE_Q will be added but not committed
338
333
open('UNVERSIONED_BUT_EXISTING', 'w')
369
364
# brz st [--short] NONEXISTENT '
374
369
out, err = self.run_bzr('status NONEXISTENT', retcode=3)
375
370
self.assertEqual(expected, out.splitlines(True))
376
371
self.assertContainsRe(err,
377
372
r'.*ERROR: Path\(s\) do not exist: '
382
377
out, err = self.run_bzr('status --short NONEXISTENT', retcode=3)
383
378
self.assertContainsRe(err,
384
379
r'.*ERROR: Path\(s\) do not exist: '
388
383
# brz st [--short] NONEXISTENT ...others..
389
384
wt = self._prepare_nonexistent()
399
394
out, err = self.run_bzr('status NONEXISTENT '
400
395
'FILE_A FILE_B FILE_C FILE_D FILE_E',
421
416
# brz st [--short] NONEXISTENT ... ANOTHER_NONEXISTENT ...
422
417
wt = self._prepare_nonexistent()
430
' ANOTHER_NONEXISTENT\n',
425
' ANOTHER_NONEXISTENT\n',
433
428
out, err = self.run_bzr('status NONEXISTENT '
434
429
'FILE_A FILE_B ANOTHER_NONEXISTENT '
435
430
'FILE_C FILE_D FILE_E', retcode=3)
438
433
r'.*ERROR: Path\(s\) do not exist: '
439
434
'ANOTHER_NONEXISTENT NONEXISTENT.*')
444
'X ANOTHER_NONEXISTENT\n',
439
'X ANOTHER_NONEXISTENT\n',
447
442
out, err = self.run_bzr('status --short NONEXISTENT '
448
443
'FILE_A FILE_B ANOTHER_NONEXISTENT '
449
444
'FILE_C FILE_D FILE_E', retcode=3)
456
451
# brz st [--short] NONEXISTENT A B UNVERSIONED_BUT_EXISTING C D E Q
457
452
wt = self._prepare_nonexistent()
467
' UNVERSIONED_BUT_EXISTING\n',
462
' UNVERSIONED_BUT_EXISTING\n',
471
466
out, err = self.run_bzr('status NONEXISTENT '
472
467
'FILE_A FILE_B UNVERSIONED_BUT_EXISTING '
473
468
'FILE_C FILE_D FILE_E FILE_Q', retcode=3)
476
471
r'.*ERROR: Path\(s\) do not exist: '
478
473
expected = sorted([
480
'? UNVERSIONED_BUT_EXISTING\n',
475
'? UNVERSIONED_BUT_EXISTING\n',
486
481
out, err = self.run_bzr('status --short NONEXISTENT '
487
482
'FILE_A FILE_B UNVERSIONED_BUT_EXISTING '
488
483
'FILE_C FILE_D FILE_E FILE_Q', retcode=3)
497
492
"""Simulate status of out-of-date tree after remote push"""
498
493
tree = self.make_branch_and_tree('.')
499
494
self.build_tree_contents([('a', b'foo\n')])
500
with tree.lock_write():
502
498
tree.commit('add test file')
503
499
# simulate what happens after a remote push
504
tree.set_last_revision(b"0")
500
tree.set_last_revision("0")
502
# before run another commands we should unlock tree
505
504
out, err = self.run_bzr('status')
506
505
self.assertEqual("working tree is out of date, run 'brz update'\n",
517
516
result = self.run_bzr('status')[0]
518
517
self.assertContainsRe(result, "unknown:\n test1.c\n")
519
518
short_result = self.run_bzr('status --short')[0]
520
self.assertContainsRe(short_result, "\\? test1.c\n")
519
self.assertContainsRe(short_result, "\? test1.c\n")
522
521
result = self.run_bzr('status test1.c')[0]
523
522
self.assertContainsRe(result, "unknown:\n test1.c\n")
524
523
short_result = self.run_bzr('status --short test1.c')[0]
525
self.assertContainsRe(short_result, "\\? test1.c\n")
524
self.assertContainsRe(short_result, "\? test1.c\n")
527
526
result = self.run_bzr('status test1.c~')[0]
528
527
self.assertContainsRe(result, "ignored:\n test1.c~\n")
535
534
self.assertContainsRe(short_result, "I test1.c~\nI test2.c~\n")
537
536
result = self.run_bzr('status test1.c test1.c~ test2.c~')[0]
538
self.assertContainsRe(
539
result, "unknown:\n test1.c\nignored:\n test1.c~\n test2.c~\n")
540
short_result = self.run_bzr(
541
'status --short test1.c test1.c~ test2.c~')[0]
542
self.assertContainsRe(
543
short_result, "\\? test1.c\nI test1.c~\nI test2.c~\n")
537
self.assertContainsRe(result, "unknown:\n test1.c\nignored:\n test1.c~\n test2.c~\n")
538
short_result = self.run_bzr('status --short test1.c test1.c~ test2.c~')[0]
539
self.assertContainsRe(short_result, "\? test1.c\nI test1.c~\nI test2.c~\n")
545
541
def test_status_write_lock(self):
546
542
"""Test that status works without fetching history and
567
563
self.build_tree(['bye.c'])
569
565
self.assertStatus([
572
'1 shelf exists. See "brz shelve --list" for details.\n',
568
'1 shelf exists. See "brz shelve --list" for details.\n',
575
571
self.run_bzr(['shelve', '--all', '-m', 'bar'])
628
624
self.build_tree(['world.txt'])
629
625
result = self.run_bzr("status -r 0")[0]
630
self.assertContainsRe(result, "added:\n hello.txt\n"
626
self.assertContainsRe(result, "added:\n hello.txt\n" \
631
627
"unknown:\n world.txt\n")
632
628
result2 = self.run_bzr("status -r 0..")[0]
633
629
self.assertEqual(result2, result)
650
646
self.build_tree(['world.txt'])
651
647
result = self.run_bzr("status -S -r 0")[0]
652
self.assertContainsRe(result, "[+]N hello.txt\n"
648
self.assertContainsRe(result, "[+]N hello.txt\n" \
653
649
"[?] world.txt\n")
654
650
result2 = self.run_bzr("status -S -r 0..")[0]
655
651
self.assertEqual(result2, result)
713
709
tree.commit('added file')
715
711
self.build_tree(['file/'])
716
self.assertStatusContains(
717
'kind changed:\n file \\(file => directory\\)')
712
self.assertStatusContains('kind changed:\n file \(file => directory\)')
718
713
tree.rename_one('file', 'directory')
719
self.assertStatusContains('renamed:\n file => directory/\n'
714
self.assertStatusContains('renamed:\n file/ => directory/\n' \
720
715
'modified:\n directory/\n')
721
716
rmdir('directory')
722
717
self.assertStatusContains('removed:\n file\n')
730
725
self.build_tree(['file/'])
731
726
self.assertStatusContains('K file => file/',
733
728
tree.rename_one('file', 'directory')
734
729
self.assertStatusContains('RK file => directory/',
736
731
rmdir('directory')
737
732
self.assertStatusContains('RD file => directory',
740
735
def test_status_illegal_revision_specifiers(self):
741
736
out, err = self.run_bzr('status -r 1..23..123', retcode=3)
767
762
tree.merge_from_branch(alt.branch)
768
763
output = self.make_utf8_encoded_stringio()
769
764
show_tree_status(tree, to_file=output)
770
self.assertContainsRe(output.getvalue(), b'pending merge')
765
self.assertContainsRe(output.getvalue(), 'pending merge')
771
766
out, err = self.run_bzr('status tree/a')
772
767
self.assertNotContainsRe(out, 'pending merge')
782
777
self.build_tree_contents([(filename, b'contents of hello')])
783
778
except UnicodeEncodeError:
784
779
raise TestSkipped("can't build unicode working tree in "
785
"filesystem encoding %s" % sys.getfilesystemencoding())
780
"filesystem encoding %s" % sys.getfilesystemencoding())
786
781
working_tree.add(filename)
787
782
return working_tree
801
796
working_tree = self.make_uncommitted_tree()
802
797
stdout, stderr = self.run_bzr('status')
799
self.assertEqual(stdout, u"""\
809
expected = expected.encode('latin-1')
810
self.assertEqual(stdout, expected)
802
""".encode('latin-1'))