30
class TestCaseWithoutPropsHandler(tests.TestCaseWithTransport):
30
class TestCaseForLogFormatter(tests.TestCaseWithTransport):
33
super(TestCaseWithoutPropsHandler, self).setUp()
33
super(TestCaseForLogFormatter, self).setUp()
34
34
# keep a reference to the "current" custom prop. handler registry
35
35
self.properties_handler_registry = log.properties_handler_registry
36
# clean up the registry in log
36
# Use a clean registry for log
37
37
log.properties_handler_registry = registry.Registry()
40
super(TestCaseWithoutPropsHandler, self)._cleanup()
41
# restore the custom properties handler registry
42
log.properties_handler_registry = self.properties_handler_registry
40
log.properties_handler_registry = self.properties_handler_registry
41
self.addCleanup(restore)
43
def assertFormatterResult(self, result, branch, formatter_class,
44
formatter_kwargs=None, show_log_kwargs=None,
46
logfile = self.make_utf8_encoded_stringio()
47
if formatter_kwargs is None:
49
formatter = formatter_class(to_file=logfile, **formatter_kwargs)
50
if show_log_kwargs is None:
52
log.show_log(branch, formatter, **show_log_kwargs)
53
log_content = logfile.getvalue()
55
log_content = normalize_log(log_content)
56
self.assertEqualDiff(result, log_content)
58
def make_standard_commit(self, branch_nick, **kwargs):
59
wt = self.make_branch_and_tree('.')
61
self.addCleanup(wt.unlock)
62
self.build_tree(['a'])
64
wt.branch.nick = branch_nick
66
kwargs.setdefault('message', 'add a')
67
kwargs.setdefault('timestamp', 1132711707)
68
kwargs.setdefault('timezone', 36000)
69
kwargs.setdefault('committer', 'Lorem Ipsum <test@example.com>')
70
kwargs.setdefault('authors', ['John Doe <jdoe@example.com>'])
74
def _prepare_tree_with_merges(self, with_tags=False):
75
wt = self.make_branch_and_memory_tree('.')
77
self.addCleanup(wt.unlock)
79
wt.commit('rev-1', rev_id='rev-1',
80
timestamp=1132586655, timezone=36000,
81
committer='Joe Foo <joe@foo.com>')
82
wt.commit('rev-merged', rev_id='rev-2a',
83
timestamp=1132586700, timezone=36000,
84
committer='Joe Foo <joe@foo.com>')
85
wt.set_parent_ids(['rev-1', 'rev-2a'])
86
wt.branch.set_last_revision_info(1, 'rev-1')
87
wt.commit('rev-2', rev_id='rev-2b',
88
timestamp=1132586800, timezone=36000,
89
committer='Joe Foo <joe@foo.com>')
92
branch.tags.set_tag('v0.2', 'rev-2b')
93
wt.commit('rev-3', rev_id='rev-3',
94
timestamp=1132586900, timezone=36000,
95
committer='Jane Foo <jane@foo.com>')
96
branch.tags.set_tag('v1.0rc1', 'rev-3')
97
branch.tags.set_tag('v1.0', 'rev-3')
45
103
class LogCatcher(log.LogFormatter):
46
"""Pull log messages into list rather than displaying them.
48
For ease of testing we save log messages here rather than actually
49
formatting them, so that we can precisely check the result without
50
being too dependent on the exact formatting.
52
We should also test the LogFormatter.
104
"""Pull log messages into a list rather than displaying them.
106
To simplify testing we save logged revisions here rather than actually
107
formatting anything, so that we can precisely check the result without
108
being dependent on the formatting.
55
111
supports_delta = True
57
113
def __init__(self):
58
114
super(LogCatcher, self).__init__(to_file=None)
61
117
def log_revision(self, revision):
62
self.logs.append(revision)
118
self.revisions.append(revision)
65
121
class TestShowLog(tests.TestCaseWithTransport):
181
241
lf.supports_merge_revisions = True
182
242
log.show_log(b, lf, verbose=True)
184
self.assertEqual(3, len(lf.logs))
245
self.assertEqual(3, len(revs))
186
logentry = lf.logs[0]
187
248
self.assertEqual('2', logentry.revno)
188
249
self.assertEqual('merge child branch', logentry.rev.message)
189
250
self.checkDelta(logentry.delta, removed=['file1'], modified=['file2'])
191
logentry = lf.logs[1]
192
253
self.assertEqual('1.1.1', logentry.revno)
193
254
self.assertEqual('remove file1 and modify file2', logentry.rev.message)
194
255
self.checkDelta(logentry.delta, removed=['file1'], modified=['file2'])
196
logentry = lf.logs[2]
197
258
self.assertEqual('1', logentry.revno)
198
259
self.assertEqual('add file1 and file2', logentry.rev.message)
199
260
self.checkDelta(logentry.delta, added=['file1', 'file2'])
201
def test_merges_nonsupporting_formatter(self):
202
"""Tests that show_log will raise if the formatter doesn't
203
support merge revisions."""
204
wt = self.make_branch_and_memory_tree('.')
206
self.addCleanup(wt.unlock)
208
wt.commit('rev-1', rev_id='rev-1',
209
timestamp=1132586655, timezone=36000,
210
committer='Joe Foo <joe@foo.com>')
211
wt.commit('rev-merged', rev_id='rev-2a',
212
timestamp=1132586700, timezone=36000,
213
committer='Joe Foo <joe@foo.com>')
214
wt.set_parent_ids(['rev-1', 'rev-2a'])
215
wt.branch.set_last_revision_info(1, 'rev-1')
216
wt.commit('rev-2', rev_id='rev-2b',
217
timestamp=1132586800, timezone=36000,
218
committer='Joe Foo <joe@foo.com>')
219
logfile = self.make_utf8_encoded_stringio()
220
formatter = log.ShortLogFormatter(to_file=logfile)
223
revspec = revisionspec.RevisionSpec.from_string('1.1.1')
224
rev = revspec.in_history(wtb)
225
self.assertRaises(errors.BzrCommandError, log.show_log, wtb, lf,
226
start_revision=rev, end_revision=rev)
229
263
def make_commits_with_trailing_newlines(wt):
230
264
"""Helper method for LogFormatter tests"""
288
319
simple log message
293
def _prepare_tree_with_merges(self, with_tags=False):
294
wt = self.make_branch_and_memory_tree('.')
296
self.addCleanup(wt.unlock)
298
wt.commit('rev-1', rev_id='rev-1',
299
timestamp=1132586655, timezone=36000,
300
committer='Joe Foo <joe@foo.com>')
301
wt.commit('rev-merged', rev_id='rev-2a',
302
timestamp=1132586700, timezone=36000,
303
committer='Joe Foo <joe@foo.com>')
304
wt.set_parent_ids(['rev-1', 'rev-2a'])
305
wt.branch.set_last_revision_info(1, 'rev-1')
306
wt.commit('rev-2', rev_id='rev-2b',
307
timestamp=1132586800, timezone=36000,
308
committer='Joe Foo <joe@foo.com>')
311
branch.tags.set_tag('v0.2', 'rev-2b')
312
wt.commit('rev-3', rev_id='rev-3',
313
timestamp=1132586900, timezone=36000,
314
committer='Jane Foo <jane@foo.com>')
315
branch.tags.set_tag('v1.0rc1', 'rev-3')
316
branch.tags.set_tag('v1.0', 'rev-3')
322
b, log.ShortLogFormatter)
319
324
def test_short_log_with_merges(self):
320
325
wt = self._prepare_tree_with_merges()
321
logfile = self.make_utf8_encoded_stringio()
322
formatter = log.ShortLogFormatter(to_file=logfile)
323
log.show_log(wt.branch, formatter)
324
self.assertEqualDiff("""\
325
2 Joe Foo\t2005-11-22 [merge]
328
1 Joe Foo\t2005-11-22
326
self.assertFormatterResult("""\
327
2 Joe Foo\t2005-11-22 [merge]
330
1 Joe Foo\t2005-11-22
334
wt.branch, log.ShortLogFormatter)
336
def test_short_log_with_merges_and_advice(self):
337
wt = self._prepare_tree_with_merges()
338
self.assertFormatterResult("""\
339
2 Joe Foo\t2005-11-22 [merge]
342
1 Joe Foo\t2005-11-22
345
Use --include-merges or -n0 to see merged revisions.
347
wt.branch, log.ShortLogFormatter,
348
formatter_kwargs=dict(show_advice=True))
334
350
def test_short_log_with_merges_and_range(self):
335
351
wt = self.make_branch_and_memory_tree('.')
470
475
wt.commit('rev-2', rev_id='rev-2b',
471
476
timestamp=1132586800, timezone=36000,
472
477
committer='Joe Foo <joe@foo.com>')
473
logfile = self.make_utf8_encoded_stringio()
474
formatter = log.ShortLogFormatter(to_file=logfile, levels=0)
475
478
revspec = revisionspec.RevisionSpec.from_string('1.1.1')
477
rev = revspec.in_history(wtb)
478
log.show_log(wtb, formatter, start_revision=rev, end_revision=rev)
479
self.assertEqualDiff("""\
479
rev = revspec.in_history(wt.branch)
480
self.assertFormatterResult("""\
480
481
1.1.1 Joe Foo\t2005-11-22
487
class TestLongLogFormatter(TestCaseWithoutPropsHandler):
485
wt.branch, log.ShortLogFormatter,
486
formatter_kwargs=dict(levels=0),
487
show_log_kwargs=dict(start_revision=rev, end_revision=rev))
490
class TestLongLogFormatter(TestCaseForLogFormatter):
489
492
def test_verbose_log(self):
490
493
"""Verbose log includes changed files
494
wt = self.make_branch_and_tree('.')
496
self.build_tree(['a'])
498
# XXX: why does a longer nick show up?
499
b.nick = 'test_verbose_log'
500
wt.commit(message='add a',
501
timestamp=1132711707,
503
committer='Lorem Ipsum <test@example.com>')
504
logfile = file('out.tmp', 'w+')
505
formatter = log.LongLogFormatter(to_file=logfile)
506
log.show_log(b, formatter, verbose=True)
509
log_contents = logfile.read()
510
self.assertEqualDiff('''\
497
wt = self.make_standard_commit('test_verbose_log', authors=[])
498
self.assertFormatterResult('''\
511
499
------------------------------------------------------------
513
501
committer: Lorem Ipsum <test@example.com>
665
647
simple log message
649
b, log.LongLogFormatter)
669
651
def test_author_in_log(self):
670
652
"""Log includes the author name if it's set in
671
653
the revision properties
673
wt = self.make_branch_and_tree('.')
675
self.build_tree(['a'])
677
b.nick = 'test_author_log'
678
wt.commit(message='add a',
679
timestamp=1132711707,
681
committer='Lorem Ipsum <test@example.com>',
682
author='John Doe <jdoe@example.com>')
684
formatter = log.LongLogFormatter(to_file=sio)
685
log.show_log(b, formatter)
686
self.assertEqualDiff('''\
655
wt = self.make_standard_commit('test_author_log',
656
authors=['John Doe <jdoe@example.com>',
657
'Jane Rey <jrey@example.com>'])
658
self.assertFormatterResult("""\
687
659
------------------------------------------------------------
689
author: John Doe <jdoe@example.com>
661
author: John Doe <jdoe@example.com>, Jane Rey <jrey@example.com>
690
662
committer: Lorem Ipsum <test@example.com>
691
663
branch nick: test_author_log
692
664
timestamp: Wed 2005-11-23 12:08:27 +1000
668
wt.branch, log.LongLogFormatter)
698
670
def test_properties_in_log(self):
699
"""Log includes the custom properties returned by the registered
671
"""Log includes the custom properties returned by the registered
702
wt = self.make_branch_and_tree('.')
704
self.build_tree(['a'])
706
b.nick = 'test_properties_in_log'
707
wt.commit(message='add a',
708
timestamp=1132711707,
710
committer='Lorem Ipsum <test@example.com>',
711
author='John Doe <jdoe@example.com>')
713
formatter = log.LongLogFormatter(to_file=sio)
715
def trivial_custom_prop_handler(revision):
716
return {'test_prop':'test_value'}
674
wt = self.make_standard_commit('test_properties_in_log')
675
def trivial_custom_prop_handler(revision):
676
return {'test_prop':'test_value'}
718
log.properties_handler_registry.register(
719
'trivial_custom_prop_handler',
720
trivial_custom_prop_handler)
721
log.show_log(b, formatter)
723
log.properties_handler_registry.remove(
724
'trivial_custom_prop_handler')
725
self.assertEqualDiff('''\
678
# Cleaned up in setUp()
679
log.properties_handler_registry.register(
680
'trivial_custom_prop_handler',
681
trivial_custom_prop_handler)
682
self.assertFormatterResult("""\
726
683
------------------------------------------------------------
728
685
test_prop: test_value
732
689
timestamp: Wed 2005-11-23 12:08:27 +1000
693
wt.branch, log.LongLogFormatter)
738
695
def test_properties_in_short_log(self):
739
"""Log includes the custom properties returned by the registered
696
"""Log includes the custom properties returned by the registered
742
wt = self.make_branch_and_tree('.')
744
self.build_tree(['a'])
746
b.nick = 'test_properties_in_short_log'
747
wt.commit(message='add a',
748
timestamp=1132711707,
750
committer='Lorem Ipsum <test@example.com>',
751
author='John Doe <jdoe@example.com>')
753
formatter = log.ShortLogFormatter(to_file=sio)
755
def trivial_custom_prop_handler(revision):
756
return {'test_prop':'test_value'}
699
wt = self.make_standard_commit('test_properties_in_short_log')
700
def trivial_custom_prop_handler(revision):
701
return {'test_prop':'test_value'}
758
log.properties_handler_registry.register(
759
'trivial_custom_prop_handler',
760
trivial_custom_prop_handler)
761
log.show_log(b, formatter)
763
log.properties_handler_registry.remove(
764
'trivial_custom_prop_handler')
765
self.assertEqualDiff('''\
703
log.properties_handler_registry.register(
704
'trivial_custom_prop_handler',
705
trivial_custom_prop_handler)
706
self.assertFormatterResult("""\
766
707
1 John Doe\t2005-11-23
767
708
test_prop: test_value
712
wt.branch, log.ShortLogFormatter)
773
714
def test_error_in_properties_handler(self):
774
"""Log includes the custom properties returned by the registered
715
"""Log includes the custom properties returned by the registered
777
wt = self.make_branch_and_tree('.')
779
self.build_tree(['a'])
781
b.nick = 'test_author_log'
782
wt.commit(message='add a',
783
timestamp=1132711707,
785
committer='Lorem Ipsum <test@example.com>',
786
author='John Doe <jdoe@example.com>',
787
revprops={'first_prop':'first_value'})
718
wt = self.make_standard_commit('error_in_properties_handler',
719
revprops={'first_prop':'first_value'})
720
sio = self.make_utf8_encoded_stringio()
789
721
formatter = log.LongLogFormatter(to_file=sio)
791
def trivial_custom_prop_handler(revision):
792
raise StandardError("a test error")
722
def trivial_custom_prop_handler(revision):
723
raise StandardError("a test error")
794
log.properties_handler_registry.register(
795
'trivial_custom_prop_handler',
796
trivial_custom_prop_handler)
797
self.assertRaises(StandardError, log.show_log, b, formatter,)
799
log.properties_handler_registry.remove(
800
'trivial_custom_prop_handler')
725
log.properties_handler_registry.register(
726
'trivial_custom_prop_handler',
727
trivial_custom_prop_handler)
728
self.assertRaises(StandardError, log.show_log, wt.branch, formatter,)
802
730
def test_properties_handler_bad_argument(self):
803
wt = self.make_branch_and_tree('.')
805
self.build_tree(['a'])
807
b.nick = 'test_author_log'
808
wt.commit(message='add a',
809
timestamp=1132711707,
811
committer='Lorem Ipsum <test@example.com>',
812
author='John Doe <jdoe@example.com>',
813
revprops={'a_prop':'test_value'})
731
wt = self.make_standard_commit('bad_argument',
732
revprops={'a_prop':'test_value'})
733
sio = self.make_utf8_encoded_stringio()
815
734
formatter = log.LongLogFormatter(to_file=sio)
817
def bad_argument_prop_handler(revision):
818
return {'custom_prop_name':revision.properties['a_prop']}
820
log.properties_handler_registry.register(
821
'bad_argument_prop_handler',
822
bad_argument_prop_handler)
824
self.assertRaises(AttributeError, formatter.show_properties,
827
revision = b.repository.get_revision(b.last_revision())
828
formatter.show_properties(revision, '')
829
self.assertEqualDiff('''custom_prop_name: test_value\n''',
832
log.properties_handler_registry.remove(
833
'bad_argument_prop_handler')
836
class TestLongLogFormatterWithoutMergeRevisions(TestCaseWithoutPropsHandler):
735
def bad_argument_prop_handler(revision):
736
return {'custom_prop_name':revision.properties['a_prop']}
738
log.properties_handler_registry.register(
739
'bad_argument_prop_handler',
740
bad_argument_prop_handler)
742
self.assertRaises(AttributeError, formatter.show_properties,
745
revision = wt.branch.repository.get_revision(wt.branch.last_revision())
746
formatter.show_properties(revision, '')
747
self.assertEqualDiff('''custom_prop_name: test_value\n''',
751
class TestLongLogFormatterWithoutMergeRevisions(TestCaseForLogFormatter):
838
753
def test_long_verbose_log(self):
839
754
"""Verbose log includes changed files
843
wt = self.make_branch_and_tree('.')
845
self.build_tree(['a'])
847
# XXX: why does a longer nick show up?
848
b.nick = 'test_verbose_log'
849
wt.commit(message='add a',
850
timestamp=1132711707,
852
committer='Lorem Ipsum <test@example.com>')
853
logfile = file('out.tmp', 'w+')
854
formatter = log.LongLogFormatter(to_file=logfile, levels=1)
855
log.show_log(b, formatter, verbose=True)
858
log_contents = logfile.read()
859
self.assertEqualDiff('''\
758
wt = self.make_standard_commit('test_long_verbose_log', authors=[])
759
self.assertFormatterResult("""\
860
760
------------------------------------------------------------
862
762
committer: Lorem Ipsum <test@example.com>
863
branch nick: test_verbose_log
763
branch nick: test_long_verbose_log
864
764
timestamp: Wed 2005-11-23 12:08:27 +1000
770
wt.branch, log.LongLogFormatter,
771
formatter_kwargs=dict(levels=1),
772
show_log_kwargs=dict(verbose=True))
872
774
def test_long_verbose_contain_deltas(self):
873
775
wt = self.make_branch_and_tree('parent')
874
776
self.build_tree(['parent/f1', 'parent/f2'])
875
777
wt.add(['f1','f2'])
876
778
wt.commit('first post')
877
self.run_bzr('branch parent child')
779
child_wt = wt.bzrdir.sprout('child').open_workingtree()
878
780
os.unlink('child/f1')
879
file('child/f2', 'wb').write('hello\n')
880
self.run_bzr(['commit', '-m', 'removed f1 and modified f2',
883
self.run_bzr('merge ../child')
781
self.build_tree_contents([('child/f2', 'hello\n')])
782
child_wt.commit('removed f1 and modified f2')
783
wt.merge_from_branch(child_wt.branch)
884
784
wt.commit('merge branch 1')
886
sio = self.make_utf8_encoded_stringio()
887
lf = log.LongLogFormatter(to_file=sio, levels=1)
888
log.show_log(b, lf, verbose=True)
889
the_log = normalize_log(sio.getvalue())
890
self.assertEqualDiff("""\
785
self.assertFormatterResult("""\
891
786
------------------------------------------------------------
893
788
committer: Lorem Ipsum <test@example.com>
894
789
branch nick: parent
895
790
timestamp: Just now
972
856
timestamp: Wed 2005-11-23 12:08:27 +1000
860
wt.branch, log.LongLogFormatter,
861
formatter_kwargs=dict(levels=1))
978
863
def test_long_properties_in_log(self):
979
"""Log includes the custom properties returned by the registered
864
"""Log includes the custom properties returned by the registered
982
wt = self.make_branch_and_tree('.')
984
self.build_tree(['a'])
986
b.nick = 'test_properties_in_log'
987
wt.commit(message='add a',
988
timestamp=1132711707,
990
committer='Lorem Ipsum <test@example.com>',
991
author='John Doe <jdoe@example.com>')
993
formatter = log.LongLogFormatter(to_file=sio, levels=1)
995
def trivial_custom_prop_handler(revision):
996
return {'test_prop':'test_value'}
867
wt = self.make_standard_commit('test_properties_in_log')
868
def trivial_custom_prop_handler(revision):
869
return {'test_prop':'test_value'}
998
log.properties_handler_registry.register(
999
'trivial_custom_prop_handler',
1000
trivial_custom_prop_handler)
1001
log.show_log(b, formatter)
1003
log.properties_handler_registry.remove(
1004
'trivial_custom_prop_handler')
1005
self.assertEqualDiff('''\
871
log.properties_handler_registry.register(
872
'trivial_custom_prop_handler',
873
trivial_custom_prop_handler)
874
self.assertFormatterResult("""\
1006
875
------------------------------------------------------------
1008
877
test_prop: test_value
1012
881
timestamp: Wed 2005-11-23 12:08:27 +1000
1019
class TestLineLogFormatter(tests.TestCaseWithTransport):
885
wt.branch, log.LongLogFormatter,
886
formatter_kwargs=dict(levels=1))
889
class TestLineLogFormatter(TestCaseForLogFormatter):
1021
891
def test_line_log(self):
1022
892
"""Line log should show revno
1026
wt = self.make_branch_and_tree('.')
1028
self.build_tree(['a'])
1030
b.nick = 'test-line-log'
1031
wt.commit(message='add a',
1032
timestamp=1132711707,
1034
committer='Line-Log-Formatter Tester <test@line.log>')
1035
logfile = file('out.tmp', 'w+')
1036
formatter = log.LineLogFormatter(to_file=logfile)
1037
log.show_log(b, formatter)
1040
log_contents = logfile.read()
1041
self.assertEqualDiff('1: Line-Log-Formatte... 2005-11-23 add a\n',
896
wt = self.make_standard_commit('test-line-log',
897
committer='Line-Log-Formatter Tester <test@line.log>',
899
self.assertFormatterResult("""\
900
1: Line-Log-Formatte... 2005-11-23 add a
902
wt.branch, log.LineLogFormatter)
1044
904
def test_trailing_newlines(self):
1045
905
wt = self.make_branch_and_tree('.')
1046
906
b = make_commits_with_trailing_newlines(wt)
1047
sio = self.make_utf8_encoded_stringio()
1048
lf = log.LineLogFormatter(to_file=sio)
1050
self.assertEqualDiff("""\
907
self.assertFormatterResult("""\
1051
908
3: Joe Foo 2005-11-21 single line with trailing newline
1052
909
2: Joe Bar 2005-11-21 multiline
1053
910
1: Joe Foo 2005-11-21 simple log message
1057
def _prepare_tree_with_merges(self, with_tags=False):
1058
wt = self.make_branch_and_memory_tree('.')
1060
self.addCleanup(wt.unlock)
1062
wt.commit('rev-1', rev_id='rev-1',
1063
timestamp=1132586655, timezone=36000,
1064
committer='Joe Foo <joe@foo.com>')
1065
wt.commit('rev-merged', rev_id='rev-2a',
1066
timestamp=1132586700, timezone=36000,
1067
committer='Joe Foo <joe@foo.com>')
1068
wt.set_parent_ids(['rev-1', 'rev-2a'])
1069
wt.branch.set_last_revision_info(1, 'rev-1')
1070
wt.commit('rev-2', rev_id='rev-2b',
1071
timestamp=1132586800, timezone=36000,
1072
committer='Joe Foo <joe@foo.com>')
1075
branch.tags.set_tag('v0.2', 'rev-2b')
1076
wt.commit('rev-3', rev_id='rev-3',
1077
timestamp=1132586900, timezone=36000,
1078
committer='Jane Foo <jane@foo.com>')
1079
branch.tags.set_tag('v1.0rc1', 'rev-3')
1080
branch.tags.set_tag('v1.0', 'rev-3')
912
b, log.LineLogFormatter)
1083
914
def test_line_log_single_merge_revision(self):
1084
915
wt = self._prepare_tree_with_merges()
1085
logfile = self.make_utf8_encoded_stringio()
1086
formatter = log.LineLogFormatter(to_file=logfile)
1087
916
revspec = revisionspec.RevisionSpec.from_string('1.1.1')
1089
rev = revspec.in_history(wtb)
1090
log.show_log(wtb, formatter, start_revision=rev, end_revision=rev)
1091
self.assertEqualDiff("""\
917
rev = revspec.in_history(wt.branch)
918
self.assertFormatterResult("""\
1092
919
1.1.1: Joe Foo 2005-11-22 rev-merged
921
wt.branch, log.LineLogFormatter,
922
show_log_kwargs=dict(start_revision=rev, end_revision=rev))
1096
924
def test_line_log_with_tags(self):
1097
925
wt = self._prepare_tree_with_merges(with_tags=True)
1098
logfile = self.make_utf8_encoded_stringio()
1099
formatter = log.LineLogFormatter(to_file=logfile)
1100
log.show_log(wt.branch, formatter)
1101
self.assertEqualDiff("""\
926
self.assertFormatterResult("""\
1102
927
3: Jane Foo 2005-11-22 {v1.0, v1.0rc1} rev-3
1103
928
2: Joe Foo 2005-11-22 [merge] {v0.2} rev-2
1104
929
1: Joe Foo 2005-11-22 rev-1
1108
class TestLineLogFormatterWithMergeRevisions(tests.TestCaseWithTransport):
931
wt.branch, log.LineLogFormatter)
934
class TestLineLogFormatterWithMergeRevisions(TestCaseForLogFormatter):
1110
936
def test_line_merge_revs_log(self):
1111
937
"""Line log should show revno
1115
wt = self.make_branch_and_tree('.')
1117
self.build_tree(['a'])
1119
b.nick = 'test-line-log'
1120
wt.commit(message='add a',
1121
timestamp=1132711707,
1123
committer='Line-Log-Formatter Tester <test@line.log>')
1124
logfile = file('out.tmp', 'w+')
1125
formatter = log.LineLogFormatter(to_file=logfile, levels=0)
1126
log.show_log(b, formatter)
1129
log_contents = logfile.read()
1130
self.assertEqualDiff('1: Line-Log-Formatte... 2005-11-23 add a\n',
941
wt = self.make_standard_commit('test-line-log',
942
committer='Line-Log-Formatter Tester <test@line.log>',
944
self.assertFormatterResult("""\
945
1: Line-Log-Formatte... 2005-11-23 add a
947
wt.branch, log.LineLogFormatter)
1133
949
def test_line_merge_revs_log_single_merge_revision(self):
1134
950
wt = self.make_branch_and_memory_tree('.')
1208
1021
return mainline_revs, rev_nos, wt
1210
def make_tree_with_many_merges(self):
1023
def make_branch_with_many_merges(self):
1211
1024
"""Create a tree with well-known revision ids"""
1212
wt = self.make_branch_and_tree('tree1')
1213
self.build_tree_contents([('tree1/f', '1\n')])
1214
wt.add(['f'], ['f-id'])
1215
wt.commit('commit one', rev_id='1')
1216
wt.commit('commit two', rev_id='2')
1218
tree3 = wt.bzrdir.sprout('tree3').open_workingtree()
1219
self.build_tree_contents([('tree3/f', '1\n2\n3a\n')])
1220
tree3.commit('commit three a', rev_id='3a')
1222
tree2 = wt.bzrdir.sprout('tree2').open_workingtree()
1223
tree2.merge_from_branch(tree3.branch)
1224
tree2.commit('commit three b', rev_id='3b')
1226
wt.merge_from_branch(tree2.branch)
1227
wt.commit('commit three c', rev_id='3c')
1228
tree2.commit('four-a', rev_id='4a')
1230
wt.merge_from_branch(tree2.branch)
1231
wt.commit('four-b', rev_id='4b')
1025
builder = self.make_branch_builder('tree1')
1026
builder.start_series()
1027
builder.build_snapshot('1', None, [
1028
('add', ('', 'TREE_ROOT', 'directory', '')),
1029
('add', ('f', 'f-id', 'file', '1\n'))])
1030
builder.build_snapshot('2', ['1'], [])
1031
builder.build_snapshot('3a', ['2'], [
1032
('modify', ('f-id', '1\n2\n3a\n'))])
1033
builder.build_snapshot('3b', ['2', '3a'], [
1034
('modify', ('f-id', '1\n2\n3a\n'))])
1035
builder.build_snapshot('3c', ['2', '3b'], [
1036
('modify', ('f-id', '1\n2\n3a\n'))])
1037
builder.build_snapshot('4a', ['3b'], [])
1038
builder.build_snapshot('4b', ['3c', '4a'], [])
1039
builder.finish_series()
1233
1053
mainline_revs = [None, '1', '2', '3c', '4b']
1234
1054
rev_nos = {'1':1, '2':2, '3c': 3, '4b':4}
1308
1128
def test_get_view_revisions_merge2(self):
1309
1129
"""Test get_view_revisions when there are merges"""
1310
mainline_revs, rev_nos, wt = self.make_tree_with_many_merges()
1312
self.addCleanup(wt.unlock)
1130
mainline_revs, rev_nos, b = self.make_branch_with_many_merges()
1132
self.addCleanup(b.unlock)
1313
1133
revisions = list(log.get_view_revisions(
1314
mainline_revs, rev_nos, wt.branch, 'forward'))
1134
mainline_revs, rev_nos, b, 'forward'))
1315
1135
expected = [('1', '1', 0), ('2', '2', 0), ('3c', '3', 0),
1316
('3a', '2.1.1', 1), ('3b', '2.2.1', 1), ('4b', '4', 0),
1136
('3b', '2.2.1', 1), ('3a', '2.1.1', 2), ('4b', '4', 0),
1317
1137
('4a', '2.2.2', 1)]
1318
1138
self.assertEqual(expected, revisions)
1319
1139
revisions = list(log.get_view_revisions(
1320
mainline_revs, rev_nos, wt.branch, 'forward',
1140
mainline_revs, rev_nos, b, 'forward',
1321
1141
include_merges=False))
1322
1142
self.assertEqual([('1', '1', 0), ('2', '2', 0), ('3c', '3', 0),
1323
1143
('4b', '4', 0)],
1336
1156
def view_revs(start_rev, end_rev, file_id, direction):
1337
1157
revs = log.calculate_view_revisions(
1339
1159
start_rev, # start_revision
1340
1160
end_rev, # end_revision
1341
1161
direction, # direction
1342
1162
file_id, # specific_fileid
1343
1163
True, # generate_merge_revisions
1344
True, # allow_single_merge_revision
1348
rev_3a = rev_from_rev_id('3a', wt.branch)
1349
rev_4b = rev_from_rev_id('4b', wt.branch)
1350
self.assertEqual([('3c', '3', 0), ('3a', '2.1.1', 1)],
1167
rev_3a = rev_from_rev_id('3a', b)
1168
rev_4b = rev_from_rev_id('4b', b)
1169
self.assertEqual([('3c', '3', 0), ('3b', '2.2.1', 1), ('3a', '2.1.1', 2)],
1351
1170
view_revs(rev_3a, rev_4b, 'f-id', 'reverse'))
1352
1171
# Note: 3c still appears before 3a here because of depth-based sorting
1353
self.assertEqual([('3c', '3', 0), ('3a', '2.1.1', 1)],
1172
self.assertEqual([('3c', '3', 0), ('3b', '2.2.1', 1), ('3a', '2.1.1', 2)],
1354
1173
view_revs(rev_3a, rev_4b, 'f-id', 'forward'))
1696
1527
log.show_branch_change(tree.branch, s, 3, '3b')
1697
1528
self.assertContainsRe(s.getvalue(), 'Removed Revisions:')
1698
1529
self.assertNotContainsRe(s.getvalue(), 'Added Revisions:')
1533
class TestLogWithBugs(TestCaseForLogFormatter):
1536
TestCaseForLogFormatter.setUp(self)
1537
log.properties_handler_registry.register(
1538
'bugs_properties_handler',
1539
log._bugs_properties_handler)
1541
def make_commits_with_bugs(self):
1542
"""Helper method for LogFormatter tests"""
1543
tree = self.make_branch_and_tree(u'.')
1544
self.build_tree(['a', 'b'])
1546
tree.commit('simple log message', rev_id='a1',
1547
timestamp=1132586655.459960938, timezone=-6*3600,
1548
committer='Joe Foo <joe@foo.com>',
1549
revprops={'bugs': 'test://bug/id fixed'})
1551
tree.commit('multiline\nlog\nmessage\n', rev_id='a2',
1552
timestamp=1132586842.411175966, timezone=-6*3600,
1553
committer='Joe Foo <joe@foo.com>',
1554
authors=['Joe Bar <joe@bar.com>'],
1555
revprops={'bugs': 'test://bug/id fixed\n'
1556
'test://bug/2 fixed'})
1560
def test_long_bugs(self):
1561
tree = self.make_commits_with_bugs()
1562
self.assertFormatterResult("""\
1563
------------------------------------------------------------
1565
fixes bug(s): test://bug/id test://bug/2
1566
author: Joe Bar <joe@bar.com>
1567
committer: Joe Foo <joe@foo.com>
1569
timestamp: Mon 2005-11-21 09:27:22 -0600
1574
------------------------------------------------------------
1576
fixes bug(s): test://bug/id
1577
committer: Joe Foo <joe@foo.com>
1579
timestamp: Mon 2005-11-21 09:24:15 -0600
1583
tree.branch, log.LongLogFormatter)
1585
def test_short_bugs(self):
1586
tree = self.make_commits_with_bugs()
1587
self.assertFormatterResult("""\
1588
2 Joe Bar\t2005-11-21
1589
fixes bug(s): test://bug/id test://bug/2
1594
1 Joe Foo\t2005-11-21
1595
fixes bug(s): test://bug/id
1599
tree.branch, log.ShortLogFormatter)
1601
def test_wrong_bugs_property(self):
1602
tree = self.make_branch_and_tree(u'.')
1603
self.build_tree(['foo'])
1604
tree.commit('simple log message', rev_id='a1',
1605
timestamp=1132586655.459960938, timezone=-6*3600,
1606
committer='Joe Foo <joe@foo.com>',
1607
revprops={'bugs': 'test://bug/id invalid_value'})
1608
self.assertFormatterResult("""\
1609
1 Joe Foo\t2005-11-21
1613
tree.branch, log.ShortLogFormatter)
1615
def test_bugs_handler_present(self):
1616
self.properties_handler_registry.get('bugs_properties_handler')