214
builder.build_snapshot(None, [
215
('add', ('', b'root-id', 'directory', ''))],
217
builder.build_snapshot([b'1'], [], revision_id=b'2')
213
builder.build_snapshot('1', None, [
214
('add', ('', 'root-id', 'directory', ''))])
215
builder.build_snapshot('2', ['1'], [])
219
builder.build_snapshot([b'1'], [], revision_id=b'1.1.1')
217
builder.build_snapshot('1.1.1', ['1'], [])
220
218
# merge branch into mainline
221
builder.build_snapshot([b'2', b'1.1.1'], [], revision_id=b'3')
219
builder.build_snapshot('3', ['2', '1.1.1'], [])
222
220
# new commits in branch
223
builder.build_snapshot([b'1.1.1'], [], revision_id=b'1.1.2')
224
builder.build_snapshot([b'1.1.2'], [], revision_id=b'1.1.3')
221
builder.build_snapshot('1.1.2', ['1.1.1'], [])
222
builder.build_snapshot('1.1.3', ['1.1.2'], [])
225
223
# merge branch into mainline
226
builder.build_snapshot([b'3', b'1.1.3'], [], revision_id=b'4')
224
builder.build_snapshot('4', ['3', '1.1.3'], [])
227
225
# merge mainline into branch
228
builder.build_snapshot([b'1.1.3', b'4'], [], revision_id=b'1.1.4')
226
builder.build_snapshot('1.1.4', ['1.1.3', '4'], [])
229
227
# merge branch into mainline
230
builder.build_snapshot([b'4', b'1.1.4'], [], revision_id=b'5')
231
builder.build_snapshot([b'5'], [], revision_id=b'5.1.1')
232
builder.build_snapshot([b'5', b'5.1.1'], [], revision_id=b'6')
228
builder.build_snapshot('5', ['4', '1.1.4'], [])
229
builder.build_snapshot('5.1.1', ['5'], [])
230
builder.build_snapshot('6', ['5', '5.1.1'], [])
233
231
builder.finish_series()
235
233
def test_n0(self):
236
234
self.assertLogRevnos(['-n0', '-r1.1.1..1.1.4'],
237
235
['1.1.4', '4', '1.1.3', '1.1.2', '3', '1.1.1'])
239
236
def test_n0_forward(self):
240
237
self.assertLogRevnos(['-n0', '-r1.1.1..1.1.4', '--forward'],
241
238
['3', '1.1.1', '4', '1.1.2', '1.1.3', '1.1.4'])
287
builder.build_snapshot(None, [
288
('add', ('', b'root-id', 'directory', ''))], revision_id=b'1')
289
builder.build_snapshot([b'1'], [], revision_id=b'2')
290
builder.build_snapshot([b'1'], [], revision_id=b'1.1.1')
291
builder.build_snapshot([b'2'], [], revision_id=b'2.1.1')
292
builder.build_snapshot([b'2', b'1.1.1'], [], revision_id=b'3')
293
builder.build_snapshot([b'2.1.1'], [], revision_id=b'2.1.2')
294
builder.build_snapshot([b'2.1.1'], [], revision_id=b'2.2.1')
295
builder.build_snapshot([b'2.1.2', b'2.2.1'], [], revision_id=b'2.1.3')
296
builder.build_snapshot([b'3', b'2.1.3'], [], revision_id=b'4')
297
builder.build_snapshot([b'4', b'2.1.2'], [], revision_id=b'5')
284
builder.build_snapshot('1', None, [
285
('add', ('', 'root-id', 'directory', ''))])
286
builder.build_snapshot('2', ['1'], [])
287
builder.build_snapshot('1.1.1', ['1'], [])
288
builder.build_snapshot('2.1.1', ['2'], [])
289
builder.build_snapshot('3', ['2', '1.1.1'], [])
290
builder.build_snapshot('2.1.2', ['2.1.1'], [])
291
builder.build_snapshot('2.2.1', ['2.1.1'], [])
292
builder.build_snapshot('2.1.3', ['2.1.2', '2.2.1'], [])
293
builder.build_snapshot('4', ['3', '2.1.3'], [])
294
builder.build_snapshot('5', ['4', '2.1.2'], [])
298
295
builder.finish_series()
301
298
def test_not_an_ancestor(self):
302
self.assertRaises(errors.CommandError,
299
self.assertRaises(errors.BzrCommandError,
303
300
log._generate_all_revisions,
304
301
self.branch, '1.1.1', '2.1.3', 'reverse',
305
302
delayed_graph_generation=True)
307
304
def test_wrong_order(self):
308
self.assertRaises(errors.CommandError,
305
self.assertRaises(errors.BzrCommandError,
309
306
log._generate_all_revisions,
310
307
self.branch, '5', '2.1.3', 'reverse',
311
308
delayed_graph_generation=True)
382
379
def test_log_change_single_revno_only(self):
383
380
self.make_minimal_branch()
384
381
self.run_bzr_error(['brz: ERROR: Option --change does not'
385
' accept revision ranges'],
382
' accept revision ranges'],
386
383
['log', '--change', '2..3'])
388
385
def test_log_change_incompatible_with_revision(self):
389
386
self.run_bzr_error(['brz: ERROR: --revision and --change'
390
' are mutually exclusive'],
387
' are mutually exclusive'],
391
388
['log', '--change', '2', '--revision', '3'])
393
390
def test_log_nonexistent_file(self):
504
499
def assertUseShortDeltaFormat(self, cmd):
505
500
log = self.run_bzr(cmd)[0]
506
501
# Check that we use the short status format
507
self.assertContainsRe(log, '(?m)^\\s*A hello.txt$')
508
self.assertNotContainsRe(log, '(?m)^\\s*added:$')
502
self.assertContainsRe(log, '(?m)^\s*A hello.txt$')
503
self.assertNotContainsRe(log, '(?m)^\s*added:$')
510
505
def assertUseLongDeltaFormat(self, cmd):
511
506
log = self.run_bzr(cmd)[0]
512
507
# Check that we use the long status format
513
self.assertNotContainsRe(log, '(?m)^\\s*A hello.txt$')
514
self.assertContainsRe(log, '(?m)^\\s*added:$')
508
self.assertNotContainsRe(log, '(?m)^\s*A hello.txt$')
509
self.assertContainsRe(log, '(?m)^\s*added:$')
516
511
def test_log_short_verbose(self):
517
512
self.assertUseShortDeltaFormat(['log', '--short', '-v'])
542
537
def make_branches_with_merges(self):
543
538
level0 = self.make_branch_and_tree('level0')
544
539
self.wt_commit(level0, 'in branch level0')
545
level1 = level0.controldir.sprout('level1').open_workingtree()
540
level1 = level0.bzrdir.sprout('level1').open_workingtree()
546
541
self.wt_commit(level1, 'in branch level1')
547
level2 = level1.controldir.sprout('level2').open_workingtree()
542
level2 = level1.bzrdir.sprout('level2').open_workingtree()
548
543
self.wt_commit(level2, 'in branch level2')
549
544
level1.merge_from_branch(level2.branch)
550
545
self.wt_commit(level1, 'merge branch level2')
588
583
def test_merges_partial_range(self):
589
584
self.assertLogRevnosAndDepths(
590
['-n0', '-r1.1.1..1.1.2'],
591
[('1.1.2', 0), ('1.2.1', 1), ('1.1.1', 0)],
592
working_dir='level0')
585
['-n0', '-r1.1.1..1.1.2'],
586
[('1.1.2', 0), ('1.2.1', 1), ('1.1.1', 0)],
587
working_dir='level0')
594
589
def test_merges_partial_range_ignore_before_lower_bound(self):
595
590
"""Dont show revisions before the lower bound's merged revs"""
596
591
self.assertLogRevnosAndDepths(
597
['-n0', '-r1.1.2..2'],
598
[('2', 0), ('1.1.2', 1), ('1.2.1', 2)],
599
working_dir='level0')
592
['-n0', '-r1.1.2..2'],
593
[('2', 0), ('1.1.2', 1), ('1.2.1', 2)],
594
working_dir='level0')
601
596
def test_omit_merges_with_sidelines(self):
602
597
self.assertLogRevnos(['--omit-merges', '-n0'], ['1.2.1', '1.1.1', '1'],
624
619
level0.add('file2')
625
620
self.wt_commit(level0, 'in branch level0')
627
level1 = level0.controldir.sprout('level1').open_workingtree()
628
self.build_tree_contents([('level1/file2', b'hello\n')])
622
level1 = level0.bzrdir.sprout('level1').open_workingtree()
623
self.build_tree_contents([('level1/file2', 'hello\n')])
629
624
self.wt_commit(level1, 'in branch level1')
630
625
level0.merge_from_branch(level1.branch)
631
626
self.wt_commit(level0, 'merge branch level1')
633
628
def _diff_file1_revno1(self):
634
return b"""=== added file 'file1'
629
return """=== added file 'file1'
635
630
--- file1\t1970-01-01 00:00:00 +0000
636
631
+++ file1\t2005-11-22 00:00:00 +0000
671
666
def assertLogRevnosAndDiff(self, args, expected,
673
668
self.run_bzr(['log', '-p'] + args, working_dir=working_dir)
674
669
expected_revnos_and_depths = [
675
670
(revno, depth) for revno, depth, diff in expected]
676
671
# Check the revnos and depths first to make debugging easier
677
672
self.assertEqual(expected_revnos_and_depths,
678
673
[(r.revno, r.merge_depth)
679
for r in self.get_captured_revisions()])
674
for r in self.get_captured_revisions()])
680
675
# Now check the diffs, adding the revno in case of failure
681
676
fmt = 'In revno %s\n%s'
682
677
for expected_rev, actual_rev in zip(expected,
692
687
[('2', 0, self._diff_file2_revno2()),
693
688
('1.1.1', 1, self._diff_file2_revno1_1_1()),
694
('1', 0, self._diff_file1_revno1() +
695
self._diff_file2_revno1())],
689
('1', 0, self._diff_file1_revno1()
690
+ self._diff_file2_revno1())],
696
691
working_dir='level0')
698
694
def test_log_diff_file1(self):
699
695
self.assertLogRevnosAndDiff(['-n0', 'file1'],
700
696
[('1', 0, self._diff_file1_revno1())],
712
708
def test_log_show_diff_non_ascii(self):
713
709
# Smoke test for bug #328007 UnicodeDecodeError on 'log -p'
714
710
message = u'Message with \xb5'
715
body = b'Body with \xb5\n'
711
body = 'Body with \xb5\n'
716
712
wt = self.make_branch_and_tree('.')
717
713
self.build_tree_contents([('foo', body)])
719
715
wt.commit(message=message)
720
716
# check that command won't fail with unicode error
721
717
# don't care about exact output because we have other tests for this
722
out, err = self.run_bzr('log -p --long')
723
self.assertNotEqual('', out)
724
self.assertEqual('', err)
725
out, err = self.run_bzr('log -p --short')
726
self.assertNotEqual('', out)
727
self.assertEqual('', err)
728
out, err = self.run_bzr('log -p --line')
718
out,err = self.run_bzr('log -p --long')
719
self.assertNotEqual('', out)
720
self.assertEqual('', err)
721
out,err = self.run_bzr('log -p --short')
722
self.assertNotEqual('', out)
723
self.assertEqual('', err)
724
out,err = self.run_bzr('log -p --line')
729
725
self.assertNotEqual('', out)
730
726
self.assertEqual('', err)
986
984
super(MainlineGhostTests, self).setUp()
987
985
tree = self.make_branch_and_tree('')
988
tree.set_parent_ids([b"spooky"], allow_leftmost_as_ghost=True)
986
tree.set_parent_ids(["spooky"], allow_leftmost_as_ghost=True)
990
tree.commit('msg1', rev_id=b'rev1')
991
tree.commit('msg2', rev_id=b'rev2')
988
tree.commit('msg1', rev_id='rev1')
989
tree.commit('msg2', rev_id='rev2')
993
991
def test_log_range(self):
994
992
self.assertLogRevnos(["-r1..2"], ["2", "1"])
997
995
self.assertLogRevnos([], ["2", "1"])
999
997
def test_log_range_open_begin(self):
998
self.knownFailure("log with ghosts fails. bug #726466")
1000
999
(stdout, stderr) = self.run_bzr(['log', '-r..2'], retcode=3)
1001
1000
self.assertEqual(["2", "1"],
1002
1001
[r.revno for r in self.get_captured_revisions()])
1003
self.assertEqual("brz: ERROR: Further revision history missing.\n",
1002
self.assertEqual("brz: ERROR: Further revision history missing.", stderr)
1006
1004
def test_log_range_open_end(self):
1007
1005
self.assertLogRevnos(["-r1.."], ["2", "1"])
1010
1007
class TestLogMatch(TestLogWithLogCatcher):
1012
1008
def prepare_tree(self):
1013
1009
tree = self.make_branch_and_tree('')
1014
1010
self.build_tree(
1015
1011
['/hello.txt', '/goodbye.txt'])
1016
1012
tree.add('hello.txt')
1017
tree.commit(message='message1', committer='committer1',
1018
authors=['author1'])
1013
tree.commit(message='message1', committer='committer1', authors=['author1'])
1019
1014
tree.add('goodbye.txt')
1020
tree.commit(message='message2', committer='committer2',
1021
authors=['author2'])
1015
tree.commit(message='message2', committer='committer2', authors=['author2'])
1023
1017
def test_message(self):
1024
1018
self.prepare_tree()
1025
1019
self.assertLogRevnos(["-m", "message1"], ["1"])
1029
1023
self.assertLogRevnos(["--match-message", "message1"], ["1"])
1030
1024
self.assertLogRevnos(["--match-message", "message2"], ["2"])
1031
1025
self.assertLogRevnos(["--match-message", "message"], ["2", "1"])
1032
self.assertLogRevnos(["--match-message", "message1",
1026
self.assertLogRevnos(["--match-message", "message1",
1033
1027
"--match-message", "message2"], ["2", "1"])
1034
1028
self.assertLogRevnos(["--message", "message1"], ["1"])
1035
1029
self.assertLogRevnos(["--message", "message2"], ["2"])
1036
1030
self.assertLogRevnos(["--message", "message"], ["2", "1"])
1037
self.assertLogRevnos(["--match-message", "message1",
1031
self.assertLogRevnos(["--match-message", "message1",
1038
1032
"--message", "message2"], ["2", "1"])
1039
self.assertLogRevnos(["--message", "message1",
1033
self.assertLogRevnos(["--message", "message1",
1040
1034
"--match-message", "message2"], ["2", "1"])
1042
1036
def test_committer(self):
1044
1038
self.assertLogRevnos(["-m", "committer1"], ["1"])
1045
1039
self.assertLogRevnos(["-m", "committer2"], ["2"])
1046
1040
self.assertLogRevnos(["-m", "committer"], ["2", "1"])
1047
self.assertLogRevnos(["-m", "committer1", "-m", "committer2"],
1041
self.assertLogRevnos(["-m", "committer1", "-m", "committer2"],
1049
1043
self.assertLogRevnos(["--match-committer", "committer1"], ["1"])
1050
1044
self.assertLogRevnos(["--match-committer", "committer2"], ["2"])
1051
1045
self.assertLogRevnos(["--match-committer", "committer"], ["2", "1"])
1052
self.assertLogRevnos(["--match-committer", "committer1",
1046
self.assertLogRevnos(["--match-committer", "committer1",
1053
1047
"--match-committer", "committer2"], ["2", "1"])
1055
1049
def test_author(self):
1057
1051
self.assertLogRevnos(["-m", "author1"], ["1"])
1058
1052
self.assertLogRevnos(["-m", "author2"], ["2"])
1059
1053
self.assertLogRevnos(["-m", "author"], ["2", "1"])
1060
self.assertLogRevnos(["-m", "author1", "-m", "author2"],
1054
self.assertLogRevnos(["-m", "author1", "-m", "author2"],
1062
1056
self.assertLogRevnos(["--match-author", "author1"], ["1"])
1063
1057
self.assertLogRevnos(["--match-author", "author2"], ["2"])
1064
1058
self.assertLogRevnos(["--match-author", "author"], ["2", "1"])
1065
self.assertLogRevnos(["--match-author", "author1",
1059
self.assertLogRevnos(["--match-author", "author1",
1066
1060
"--match-author", "author2"], ["2", "1"])
1063
class TestSmartServerLog(tests.TestCaseWithTransport):
1065
def test_standard_log(self):
1066
self.setup_smart_server_with_call_log()
1067
t = self.make_branch_and_tree('branch')
1068
self.build_tree_contents([('branch/foo', 'thecontents')])
1071
self.reset_smart_call_log()
1072
out, err = self.run_bzr(['log', self.get_url('branch')])
1073
# This figure represent the amount of work to perform this use case. It
1074
# is entirely ok to reduce this number if a test fails due to rpc_count
1075
# being too low. If rpc_count increases, more network roundtrips have
1076
# become necessary for this use case. Please do not adjust this number
1077
# upwards without agreement from bzr's network support maintainers.
1078
self.assertThat(self.hpss_calls, ContainsNoVfsCalls)
1079
self.assertLength(1, self.hpss_connections)
1080
self.assertLength(9, self.hpss_calls)
1082
def test_verbose_log(self):
1083
self.setup_smart_server_with_call_log()
1084
t = self.make_branch_and_tree('branch')
1085
self.build_tree_contents([('branch/foo', 'thecontents')])
1088
self.reset_smart_call_log()
1089
out, err = self.run_bzr(['log', '-v', self.get_url('branch')])
1090
# This figure represent the amount of work to perform this use case. It
1091
# is entirely ok to reduce this number if a test fails due to rpc_count
1092
# being too low. If rpc_count increases, more network roundtrips have
1093
# become necessary for this use case. Please do not adjust this number
1094
# upwards without agreement from bzr's network support maintainers.
1095
self.assertLength(10, self.hpss_calls)
1096
self.assertLength(1, self.hpss_connections)
1097
self.assertThat(self.hpss_calls, ContainsNoVfsCalls)
1099
def test_per_file(self):
1100
self.setup_smart_server_with_call_log()
1101
t = self.make_branch_and_tree('branch')
1102
self.build_tree_contents([('branch/foo', 'thecontents')])
1105
self.reset_smart_call_log()
1106
out, err = self.run_bzr(['log', '-v', self.get_url('branch') + "/foo"])
1107
# This figure represent the amount of work to perform this use case. It
1108
# is entirely ok to reduce this number if a test fails due to rpc_count
1109
# being too low. If rpc_count increases, more network roundtrips have
1110
# become necessary for this use case. Please do not adjust this number
1111
# upwards without agreement from bzr's network support maintainers.
1112
self.assertLength(14, self.hpss_calls)
1113
self.assertLength(1, self.hpss_connections)
1114
self.assertThat(self.hpss_calls, ContainsNoVfsCalls)