40
40
log.properties_handler_registry = self.properties_handler_registry
41
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')
103
44
class LogCatcher(log.LogFormatter):
104
45
"""Pull log messages into a list rather than displaying them.
319
263
simple log message
322
b, log.ShortLogFormatter)
268
def _prepare_tree_with_merges(self, with_tags=False):
269
wt = self.make_branch_and_memory_tree('.')
271
self.addCleanup(wt.unlock)
273
wt.commit('rev-1', rev_id='rev-1',
274
timestamp=1132586655, timezone=36000,
275
committer='Joe Foo <joe@foo.com>')
276
wt.commit('rev-merged', rev_id='rev-2a',
277
timestamp=1132586700, timezone=36000,
278
committer='Joe Foo <joe@foo.com>')
279
wt.set_parent_ids(['rev-1', 'rev-2a'])
280
wt.branch.set_last_revision_info(1, 'rev-1')
281
wt.commit('rev-2', rev_id='rev-2b',
282
timestamp=1132586800, timezone=36000,
283
committer='Joe Foo <joe@foo.com>')
286
branch.tags.set_tag('v0.2', 'rev-2b')
287
wt.commit('rev-3', rev_id='rev-3',
288
timestamp=1132586900, timezone=36000,
289
committer='Jane Foo <jane@foo.com>')
290
branch.tags.set_tag('v1.0rc1', 'rev-3')
291
branch.tags.set_tag('v1.0', 'rev-3')
324
294
def test_short_log_with_merges(self):
325
295
wt = self._prepare_tree_with_merges()
326
self.assertFormatterResult("""\
296
logfile = self.make_utf8_encoded_stringio()
297
formatter = log.ShortLogFormatter(to_file=logfile)
298
log.show_log(wt.branch, formatter)
299
self.assertEqualDiff("""\
327
300
2 Joe Foo\t2005-11-22 [merge]
475
462
wt.commit('rev-2', rev_id='rev-2b',
476
463
timestamp=1132586800, timezone=36000,
477
464
committer='Joe Foo <joe@foo.com>')
465
logfile = self.make_utf8_encoded_stringio()
466
formatter = log.ShortLogFormatter(to_file=logfile, levels=0)
478
467
revspec = revisionspec.RevisionSpec.from_string('1.1.1')
479
rev = revspec.in_history(wt.branch)
480
self.assertFormatterResult("""\
469
rev = revspec.in_history(wtb)
470
log.show_log(wtb, formatter, start_revision=rev, end_revision=rev)
471
self.assertEqualDiff("""\
481
472
1.1.1 Joe Foo\t2005-11-22
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):
479
class TestLongLogFormatter(TestCaseWithoutPropsHandler):
492
481
def test_verbose_log(self):
493
482
"""Verbose log includes changed files
497
wt = self.make_standard_commit('test_verbose_log', authors=[])
498
self.assertFormatterResult('''\
486
wt = self.make_branch_and_tree('.')
488
self.build_tree(['a'])
490
# XXX: why does a longer nick show up?
491
b.nick = 'test_verbose_log'
492
wt.commit(message='add a',
493
timestamp=1132711707,
495
committer='Lorem Ipsum <test@example.com>')
496
logfile = file('out.tmp', 'w+')
497
formatter = log.LongLogFormatter(to_file=logfile)
498
log.show_log(b, formatter, verbose=True)
501
log_contents = logfile.read()
502
self.assertEqualDiff('''\
499
503
------------------------------------------------------------
501
505
committer: Lorem Ipsum <test@example.com>
664
685
timestamp: Wed 2005-11-23 12:08:27 +1000
668
wt.branch, log.LongLogFormatter)
670
691
def test_properties_in_log(self):
671
692
"""Log includes the custom properties returned by the registered
674
wt = self.make_standard_commit('test_properties_in_log')
675
def trivial_custom_prop_handler(revision):
676
return {'test_prop':'test_value'}
695
wt = self.make_branch_and_tree('.')
697
self.build_tree(['a'])
699
b.nick = 'test_properties_in_log'
700
wt.commit(message='add a',
701
timestamp=1132711707,
703
committer='Lorem Ipsum <test@example.com>',
704
authors=['John Doe <jdoe@example.com>'])
706
formatter = log.LongLogFormatter(to_file=sio)
708
def trivial_custom_prop_handler(revision):
709
return {'test_prop':'test_value'}
678
# Cleaned up in setUp()
679
log.properties_handler_registry.register(
680
'trivial_custom_prop_handler',
681
trivial_custom_prop_handler)
682
self.assertFormatterResult("""\
711
log.properties_handler_registry.register(
712
'trivial_custom_prop_handler',
713
trivial_custom_prop_handler)
714
log.show_log(b, formatter)
716
log.properties_handler_registry.remove(
717
'trivial_custom_prop_handler')
718
self.assertEqualDiff('''\
683
719
------------------------------------------------------------
685
721
test_prop: test_value
689
725
timestamp: Wed 2005-11-23 12:08:27 +1000
693
wt.branch, log.LongLogFormatter)
695
731
def test_properties_in_short_log(self):
696
732
"""Log includes the custom properties returned by the registered
699
wt = self.make_standard_commit('test_properties_in_short_log')
700
def trivial_custom_prop_handler(revision):
701
return {'test_prop':'test_value'}
735
wt = self.make_branch_and_tree('.')
737
self.build_tree(['a'])
739
b.nick = 'test_properties_in_short_log'
740
wt.commit(message='add a',
741
timestamp=1132711707,
743
committer='Lorem Ipsum <test@example.com>',
744
authors=['John Doe <jdoe@example.com>'])
746
formatter = log.ShortLogFormatter(to_file=sio)
748
def trivial_custom_prop_handler(revision):
749
return {'test_prop':'test_value'}
703
log.properties_handler_registry.register(
704
'trivial_custom_prop_handler',
705
trivial_custom_prop_handler)
706
self.assertFormatterResult("""\
751
log.properties_handler_registry.register(
752
'trivial_custom_prop_handler',
753
trivial_custom_prop_handler)
754
log.show_log(b, formatter)
756
log.properties_handler_registry.remove(
757
'trivial_custom_prop_handler')
758
self.assertEqualDiff('''\
707
759
1 John Doe\t2005-11-23
708
760
test_prop: test_value
712
wt.branch, log.ShortLogFormatter)
714
766
def test_error_in_properties_handler(self):
715
767
"""Log includes the custom properties returned by the registered
718
wt = self.make_standard_commit('error_in_properties_handler',
719
revprops={'first_prop':'first_value'})
720
sio = self.make_utf8_encoded_stringio()
770
wt = self.make_branch_and_tree('.')
772
self.build_tree(['a'])
774
b.nick = 'test_author_log'
775
wt.commit(message='add a',
776
timestamp=1132711707,
778
committer='Lorem Ipsum <test@example.com>',
779
authors=['John Doe <jdoe@example.com>'],
780
revprops={'first_prop':'first_value'})
721
782
formatter = log.LongLogFormatter(to_file=sio)
722
def trivial_custom_prop_handler(revision):
723
raise StandardError("a test error")
784
def trivial_custom_prop_handler(revision):
785
raise StandardError("a test error")
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,)
787
log.properties_handler_registry.register(
788
'trivial_custom_prop_handler',
789
trivial_custom_prop_handler)
790
self.assertRaises(StandardError, log.show_log, b, formatter,)
792
log.properties_handler_registry.remove(
793
'trivial_custom_prop_handler')
730
795
def test_properties_handler_bad_argument(self):
731
wt = self.make_standard_commit('bad_argument',
732
revprops={'a_prop':'test_value'})
733
sio = self.make_utf8_encoded_stringio()
796
wt = self.make_branch_and_tree('.')
798
self.build_tree(['a'])
800
b.nick = 'test_author_log'
801
wt.commit(message='add a',
802
timestamp=1132711707,
804
committer='Lorem Ipsum <test@example.com>',
805
authors=['John Doe <jdoe@example.com>'],
806
revprops={'a_prop':'test_value'})
734
808
formatter = log.LongLogFormatter(to_file=sio)
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):
810
def bad_argument_prop_handler(revision):
811
return {'custom_prop_name':revision.properties['a_prop']}
813
log.properties_handler_registry.register(
814
'bad_argument_prop_handler',
815
bad_argument_prop_handler)
817
self.assertRaises(AttributeError, formatter.show_properties,
820
revision = b.repository.get_revision(b.last_revision())
821
formatter.show_properties(revision, '')
822
self.assertEqualDiff('''custom_prop_name: test_value\n''',
825
log.properties_handler_registry.remove(
826
'bad_argument_prop_handler')
829
class TestLongLogFormatterWithoutMergeRevisions(TestCaseWithoutPropsHandler):
753
831
def test_long_verbose_log(self):
754
832
"""Verbose log includes changed files
758
wt = self.make_standard_commit('test_long_verbose_log', authors=[])
759
self.assertFormatterResult("""\
836
wt = self.make_branch_and_tree('.')
838
self.build_tree(['a'])
840
# XXX: why does a longer nick show up?
841
b.nick = 'test_verbose_log'
842
wt.commit(message='add a',
843
timestamp=1132711707,
845
committer='Lorem Ipsum <test@example.com>')
846
logfile = file('out.tmp', 'w+')
847
formatter = log.LongLogFormatter(to_file=logfile, levels=1)
848
log.show_log(b, formatter, verbose=True)
851
log_contents = logfile.read()
852
self.assertEqualDiff('''\
760
853
------------------------------------------------------------
762
855
committer: Lorem Ipsum <test@example.com>
763
branch nick: test_long_verbose_log
856
branch nick: test_verbose_log
764
857
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))
774
865
def test_long_verbose_contain_deltas(self):
775
866
wt = self.make_branch_and_tree('parent')
776
867
self.build_tree(['parent/f1', 'parent/f2'])
777
868
wt.add(['f1','f2'])
778
869
wt.commit('first post')
779
child_wt = wt.bzrdir.sprout('child').open_workingtree()
870
self.run_bzr('branch parent child')
780
871
os.unlink('child/f1')
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)
872
file('child/f2', 'wb').write('hello\n')
873
self.run_bzr(['commit', '-m', 'removed f1 and modified f2',
876
self.run_bzr('merge ../child')
784
877
wt.commit('merge branch 1')
785
self.assertFormatterResult("""\
879
sio = self.make_utf8_encoded_stringio()
880
lf = log.LongLogFormatter(to_file=sio, levels=1)
881
log.show_log(b, lf, verbose=True)
882
the_log = normalize_log(sio.getvalue())
883
self.assertEqualDiff("""\
786
884
------------------------------------------------------------
788
886
committer: Lorem Ipsum <test@example.com>
856
965
timestamp: Wed 2005-11-23 12:08:27 +1000
860
wt.branch, log.LongLogFormatter,
861
formatter_kwargs=dict(levels=1))
863
971
def test_long_properties_in_log(self):
864
972
"""Log includes the custom properties returned by the registered
867
wt = self.make_standard_commit('test_properties_in_log')
868
def trivial_custom_prop_handler(revision):
869
return {'test_prop':'test_value'}
975
wt = self.make_branch_and_tree('.')
977
self.build_tree(['a'])
979
b.nick = 'test_properties_in_log'
980
wt.commit(message='add a',
981
timestamp=1132711707,
983
committer='Lorem Ipsum <test@example.com>',
984
authors=['John Doe <jdoe@example.com>'])
986
formatter = log.LongLogFormatter(to_file=sio, levels=1)
988
def trivial_custom_prop_handler(revision):
989
return {'test_prop':'test_value'}
871
log.properties_handler_registry.register(
872
'trivial_custom_prop_handler',
873
trivial_custom_prop_handler)
874
self.assertFormatterResult("""\
991
log.properties_handler_registry.register(
992
'trivial_custom_prop_handler',
993
trivial_custom_prop_handler)
994
log.show_log(b, formatter)
996
log.properties_handler_registry.remove(
997
'trivial_custom_prop_handler')
998
self.assertEqualDiff('''\
875
999
------------------------------------------------------------
877
1001
test_prop: test_value
881
1005
timestamp: Wed 2005-11-23 12:08:27 +1000
885
wt.branch, log.LongLogFormatter,
886
formatter_kwargs=dict(levels=1))
889
class TestLineLogFormatter(TestCaseForLogFormatter):
1012
class TestLineLogFormatter(tests.TestCaseWithTransport):
891
1014
def test_line_log(self):
892
1015
"""Line log should show revno
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)
1019
wt = self.make_branch_and_tree('.')
1021
self.build_tree(['a'])
1023
b.nick = 'test-line-log'
1024
wt.commit(message='add a',
1025
timestamp=1132711707,
1027
committer='Line-Log-Formatter Tester <test@line.log>')
1028
logfile = file('out.tmp', 'w+')
1029
formatter = log.LineLogFormatter(to_file=logfile)
1030
log.show_log(b, formatter)
1033
log_contents = logfile.read()
1034
self.assertEqualDiff('1: Line-Log-Formatte... 2005-11-23 add a\n',
904
1037
def test_trailing_newlines(self):
905
1038
wt = self.make_branch_and_tree('.')
906
1039
b = make_commits_with_trailing_newlines(wt)
907
self.assertFormatterResult("""\
1040
sio = self.make_utf8_encoded_stringio()
1041
lf = log.LineLogFormatter(to_file=sio)
1043
self.assertEqualDiff("""\
908
1044
3: Joe Foo 2005-11-21 single line with trailing newline
909
1045
2: Joe Bar 2005-11-21 multiline
910
1046
1: Joe Foo 2005-11-21 simple log message
912
b, log.LineLogFormatter)
1050
def _prepare_tree_with_merges(self, with_tags=False):
1051
wt = self.make_branch_and_memory_tree('.')
1053
self.addCleanup(wt.unlock)
1055
wt.commit('rev-1', rev_id='rev-1',
1056
timestamp=1132586655, timezone=36000,
1057
committer='Joe Foo <joe@foo.com>')
1058
wt.commit('rev-merged', rev_id='rev-2a',
1059
timestamp=1132586700, timezone=36000,
1060
committer='Joe Foo <joe@foo.com>')
1061
wt.set_parent_ids(['rev-1', 'rev-2a'])
1062
wt.branch.set_last_revision_info(1, 'rev-1')
1063
wt.commit('rev-2', rev_id='rev-2b',
1064
timestamp=1132586800, timezone=36000,
1065
committer='Joe Foo <joe@foo.com>')
1068
branch.tags.set_tag('v0.2', 'rev-2b')
1069
wt.commit('rev-3', rev_id='rev-3',
1070
timestamp=1132586900, timezone=36000,
1071
committer='Jane Foo <jane@foo.com>')
1072
branch.tags.set_tag('v1.0rc1', 'rev-3')
1073
branch.tags.set_tag('v1.0', 'rev-3')
914
1076
def test_line_log_single_merge_revision(self):
915
1077
wt = self._prepare_tree_with_merges()
1078
logfile = self.make_utf8_encoded_stringio()
1079
formatter = log.LineLogFormatter(to_file=logfile)
916
1080
revspec = revisionspec.RevisionSpec.from_string('1.1.1')
917
rev = revspec.in_history(wt.branch)
918
self.assertFormatterResult("""\
1082
rev = revspec.in_history(wtb)
1083
log.show_log(wtb, formatter, start_revision=rev, end_revision=rev)
1084
self.assertEqualDiff("""\
919
1085
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))
924
1089
def test_line_log_with_tags(self):
925
1090
wt = self._prepare_tree_with_merges(with_tags=True)
926
self.assertFormatterResult("""\
1091
logfile = self.make_utf8_encoded_stringio()
1092
formatter = log.LineLogFormatter(to_file=logfile)
1093
log.show_log(wt.branch, formatter)
1094
self.assertEqualDiff("""\
927
1095
3: Jane Foo 2005-11-22 {v1.0, v1.0rc1} rev-3
928
1096
2: Joe Foo 2005-11-22 [merge] {v0.2} rev-2
929
1097
1: Joe Foo 2005-11-22 rev-1
931
wt.branch, log.LineLogFormatter)
934
class TestLineLogFormatterWithMergeRevisions(TestCaseForLogFormatter):
1101
class TestLineLogFormatterWithMergeRevisions(tests.TestCaseWithTransport):
936
1103
def test_line_merge_revs_log(self):
937
1104
"""Line log should show revno
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)
1108
wt = self.make_branch_and_tree('.')
1110
self.build_tree(['a'])
1112
b.nick = 'test-line-log'
1113
wt.commit(message='add a',
1114
timestamp=1132711707,
1116
committer='Line-Log-Formatter Tester <test@line.log>')
1117
logfile = file('out.tmp', 'w+')
1118
formatter = log.LineLogFormatter(to_file=logfile, levels=0)
1119
log.show_log(b, formatter)
1122
log_contents = logfile.read()
1123
self.assertEqualDiff('1: Line-Log-Formatte... 2005-11-23 add a\n',
949
1126
def test_line_merge_revs_log_single_merge_revision(self):
950
1127
wt = self.make_branch_and_memory_tree('.')
1527
1707
log.show_branch_change(tree.branch, s, 3, '3b')
1528
1708
self.assertContainsRe(s.getvalue(), 'Removed Revisions:')
1529
1709
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')