420
wt.branch, log.ShortLogFormatter,
421
formatter_kwargs=dict(levels=0))
423
446
def test_short_merge_revs_log_single_merge_revision(self):
424
wt = self._prepare_tree_with_merges()
447
wt = self.make_branch_and_memory_tree('.')
449
self.addCleanup(wt.unlock)
451
wt.commit('rev-1', rev_id='rev-1',
452
timestamp=1132586655, timezone=36000,
453
committer='Joe Foo <joe@foo.com>')
454
wt.commit('rev-merged', rev_id='rev-2a',
455
timestamp=1132586700, timezone=36000,
456
committer='Joe Foo <joe@foo.com>')
457
wt.set_parent_ids(['rev-1', 'rev-2a'])
458
wt.branch.set_last_revision_info(1, 'rev-1')
459
wt.commit('rev-2', rev_id='rev-2b',
460
timestamp=1132586800, timezone=36000,
461
committer='Joe Foo <joe@foo.com>')
462
logfile = self.make_utf8_encoded_stringio()
463
formatter = log.ShortLogFormatter(to_file=logfile, levels=0)
425
464
revspec = revisionspec.RevisionSpec.from_string('1.1.1')
426
rev = revspec.in_history(wt.branch)
427
self.assertFormatterResult("""\
466
rev = revspec.in_history(wtb)
467
log.show_log(wtb, formatter, start_revision=rev, end_revision=rev)
468
self.assertEqualDiff("""\
428
469
1.1.1 Joe Foo\t2005-11-22
432
wt.branch, log.ShortLogFormatter,
433
formatter_kwargs=dict(levels=0),
434
show_log_kwargs=dict(start_revision=rev, end_revision=rev))
437
class TestLongLogFormatter(TestCaseForLogFormatter):
476
class TestLongLogFormatter(TestCaseWithoutPropsHandler):
439
478
def test_verbose_log(self):
440
479
"""Verbose log includes changed files
444
wt = self.make_standard_commit('test_verbose_log', authors=[])
445
self.assertFormatterResult('''\
483
wt = self.make_branch_and_tree('.')
485
self.build_tree(['a'])
487
# XXX: why does a longer nick show up?
488
b.nick = 'test_verbose_log'
489
wt.commit(message='add a',
490
timestamp=1132711707,
492
committer='Lorem Ipsum <test@example.com>')
493
logfile = file('out.tmp', 'w+')
494
formatter = log.LongLogFormatter(to_file=logfile)
495
log.show_log(b, formatter, verbose=True)
498
log_contents = logfile.read()
499
self.assertEqualDiff('''\
446
500
------------------------------------------------------------
448
502
committer: Lorem Ipsum <test@example.com>
449
503
branch nick: test_verbose_log
450
timestamp: Tue 2005-11-22 00:00:00 +0000
504
timestamp: Wed 2005-11-23 12:08:27 +1000
456
wt.branch, log.LongLogFormatter,
457
show_log_kwargs=dict(verbose=True))
459
512
def test_merges_are_indented_by_level(self):
460
513
wt = self.make_branch_and_tree('parent')
461
self.wt_commit(wt, 'first post')
462
child_wt = wt.bzrdir.sprout('child').open_workingtree()
463
self.wt_commit(child_wt, 'branch 1')
464
smallerchild_wt = wt.bzrdir.sprout('smallerchild').open_workingtree()
465
self.wt_commit(smallerchild_wt, 'branch 2')
466
child_wt.merge_from_branch(smallerchild_wt.branch)
467
self.wt_commit(child_wt, 'merge branch 2')
468
wt.merge_from_branch(child_wt.branch)
469
self.wt_commit(wt, 'merge branch 1')
470
self.assertFormatterResult("""\
514
wt.commit('first post')
515
self.run_bzr('branch parent child')
516
self.run_bzr(['commit', '-m', 'branch 1', '--unchanged', 'child'])
517
self.run_bzr('branch child smallerchild')
518
self.run_bzr(['commit', '-m', 'branch 2', '--unchanged',
521
self.run_bzr('merge ../smallerchild')
522
self.run_bzr(['commit', '-m', 'merge branch 2'])
523
os.chdir('../parent')
524
self.run_bzr('merge ../child')
525
wt.commit('merge branch 1')
527
sio = self.make_utf8_encoded_stringio()
528
lf = log.LongLogFormatter(to_file=sio, levels=0)
529
log.show_log(b, lf, verbose=True)
530
the_log = normalize_log(sio.getvalue())
531
self.assertEqualDiff("""\
471
532
------------------------------------------------------------
473
committer: Joe Foo <joe@foo.com>
534
committer: Lorem Ipsum <test@example.com>
474
535
branch nick: parent
475
timestamp: Tue 2005-11-22 00:00:04 +0000
478
539
------------------------------------------------------------
479
540
revno: 1.1.2 [merge]
480
committer: Joe Foo <joe@foo.com>
541
committer: Lorem Ipsum <test@example.com>
481
542
branch nick: child
482
timestamp: Tue 2005-11-22 00:00:03 +0000
485
546
------------------------------------------------------------
487
committer: Joe Foo <joe@foo.com>
548
committer: Lorem Ipsum <test@example.com>
488
549
branch nick: smallerchild
489
timestamp: Tue 2005-11-22 00:00:02 +0000
492
553
------------------------------------------------------------
494
committer: Joe Foo <joe@foo.com>
555
committer: Lorem Ipsum <test@example.com>
495
556
branch nick: child
496
timestamp: Tue 2005-11-22 00:00:01 +0000
499
560
------------------------------------------------------------
501
committer: Joe Foo <joe@foo.com>
562
committer: Lorem Ipsum <test@example.com>
502
563
branch nick: parent
503
timestamp: Tue 2005-11-22 00:00:00 +0000
507
wt.branch, log.LongLogFormatter,
508
formatter_kwargs=dict(levels=0),
509
show_log_kwargs=dict(verbose=True))
511
570
def test_verbose_merge_revisions_contain_deltas(self):
512
571
wt = self.make_branch_and_tree('parent')
513
572
self.build_tree(['parent/f1', 'parent/f2'])
514
573
wt.add(['f1','f2'])
515
self.wt_commit(wt, 'first post')
516
child_wt = wt.bzrdir.sprout('child').open_workingtree()
574
wt.commit('first post')
575
self.run_bzr('branch parent child')
517
576
os.unlink('child/f1')
518
self.build_tree_contents([('child/f2', 'hello\n')])
519
self.wt_commit(child_wt, 'removed f1 and modified f2')
520
wt.merge_from_branch(child_wt.branch)
521
self.wt_commit(wt, 'merge branch 1')
522
self.assertFormatterResult("""\
577
file('child/f2', 'wb').write('hello\n')
578
self.run_bzr(['commit', '-m', 'removed f1 and modified f2',
581
self.run_bzr('merge ../child')
582
wt.commit('merge branch 1')
584
sio = self.make_utf8_encoded_stringio()
585
lf = log.LongLogFormatter(to_file=sio, levels=0)
586
log.show_log(b, lf, verbose=True)
587
the_log = normalize_log(sio.getvalue())
588
self.assertEqualDiff("""\
523
589
------------------------------------------------------------
525
committer: Joe Foo <joe@foo.com>
591
committer: Lorem Ipsum <test@example.com>
526
592
branch nick: parent
527
timestamp: Tue 2005-11-22 00:00:02 +0000
582
650
committer: Joe Foo <joe@foo.com>
583
651
branch nick: test
584
timestamp: Tue 2005-11-22 00:00:00 +0000
652
timestamp: Mon 2005-11-21 09:24:15 -0600
586
654
simple log message
588
b, log.LongLogFormatter)
590
658
def test_author_in_log(self):
591
659
"""Log includes the author name if it's set in
592
660
the revision properties
594
wt = self.make_standard_commit('test_author_log',
595
authors=['John Doe <jdoe@example.com>',
596
'Jane Rey <jrey@example.com>'])
597
self.assertFormatterResult("""\
662
wt = self.make_branch_and_tree('.')
664
self.build_tree(['a'])
666
b.nick = 'test_author_log'
667
wt.commit(message='add a',
668
timestamp=1132711707,
670
committer='Lorem Ipsum <test@example.com>',
671
authors=['John Doe <jdoe@example.com>',
672
'Jane Rey <jrey@example.com>'])
674
formatter = log.LongLogFormatter(to_file=sio)
675
log.show_log(b, formatter)
676
self.assertEqualDiff('''\
598
677
------------------------------------------------------------
600
679
author: John Doe <jdoe@example.com>, Jane Rey <jrey@example.com>
601
680
committer: Lorem Ipsum <test@example.com>
602
681
branch nick: test_author_log
603
timestamp: Tue 2005-11-22 00:00:00 +0000
682
timestamp: Wed 2005-11-23 12:08:27 +1000
607
wt.branch, log.LongLogFormatter)
609
688
def test_properties_in_log(self):
610
689
"""Log includes the custom properties returned by the registered
613
wt = self.make_standard_commit('test_properties_in_log')
614
def trivial_custom_prop_handler(revision):
615
return {'test_prop':'test_value'}
692
wt = self.make_branch_and_tree('.')
694
self.build_tree(['a'])
696
b.nick = 'test_properties_in_log'
697
wt.commit(message='add a',
698
timestamp=1132711707,
700
committer='Lorem Ipsum <test@example.com>',
701
authors=['John Doe <jdoe@example.com>'])
703
formatter = log.LongLogFormatter(to_file=sio)
705
def trivial_custom_prop_handler(revision):
706
return {'test_prop':'test_value'}
617
# Cleaned up in setUp()
618
log.properties_handler_registry.register(
619
'trivial_custom_prop_handler',
620
trivial_custom_prop_handler)
621
self.assertFormatterResult("""\
708
log.properties_handler_registry.register(
709
'trivial_custom_prop_handler',
710
trivial_custom_prop_handler)
711
log.show_log(b, formatter)
713
log.properties_handler_registry.remove(
714
'trivial_custom_prop_handler')
715
self.assertEqualDiff('''\
622
716
------------------------------------------------------------
624
718
test_prop: test_value
625
719
author: John Doe <jdoe@example.com>
626
720
committer: Lorem Ipsum <test@example.com>
627
721
branch nick: test_properties_in_log
628
timestamp: Tue 2005-11-22 00:00:00 +0000
722
timestamp: Wed 2005-11-23 12:08:27 +1000
632
wt.branch, log.LongLogFormatter)
634
728
def test_properties_in_short_log(self):
635
729
"""Log includes the custom properties returned by the registered
638
wt = self.make_standard_commit('test_properties_in_short_log')
639
def trivial_custom_prop_handler(revision):
640
return {'test_prop':'test_value'}
732
wt = self.make_branch_and_tree('.')
734
self.build_tree(['a'])
736
b.nick = 'test_properties_in_short_log'
737
wt.commit(message='add a',
738
timestamp=1132711707,
740
committer='Lorem Ipsum <test@example.com>',
741
authors=['John Doe <jdoe@example.com>'])
743
formatter = log.ShortLogFormatter(to_file=sio)
745
def trivial_custom_prop_handler(revision):
746
return {'test_prop':'test_value'}
642
log.properties_handler_registry.register(
643
'trivial_custom_prop_handler',
644
trivial_custom_prop_handler)
645
self.assertFormatterResult("""\
646
1 John Doe\t2005-11-22
748
log.properties_handler_registry.register(
749
'trivial_custom_prop_handler',
750
trivial_custom_prop_handler)
751
log.show_log(b, formatter)
753
log.properties_handler_registry.remove(
754
'trivial_custom_prop_handler')
755
self.assertEqualDiff('''\
756
1 John Doe\t2005-11-23
647
757
test_prop: test_value
651
wt.branch, log.ShortLogFormatter)
653
763
def test_error_in_properties_handler(self):
654
764
"""Log includes the custom properties returned by the registered
657
wt = self.make_standard_commit('error_in_properties_handler',
658
revprops={'first_prop':'first_value'})
659
sio = self.make_utf8_encoded_stringio()
767
wt = self.make_branch_and_tree('.')
769
self.build_tree(['a'])
771
b.nick = 'test_author_log'
772
wt.commit(message='add a',
773
timestamp=1132711707,
775
committer='Lorem Ipsum <test@example.com>',
776
authors=['John Doe <jdoe@example.com>'],
777
revprops={'first_prop':'first_value'})
660
779
formatter = log.LongLogFormatter(to_file=sio)
661
def trivial_custom_prop_handler(revision):
662
raise StandardError("a test error")
781
def trivial_custom_prop_handler(revision):
782
raise StandardError("a test error")
664
log.properties_handler_registry.register(
665
'trivial_custom_prop_handler',
666
trivial_custom_prop_handler)
667
self.assertRaises(StandardError, log.show_log, wt.branch, formatter,)
784
log.properties_handler_registry.register(
785
'trivial_custom_prop_handler',
786
trivial_custom_prop_handler)
787
self.assertRaises(StandardError, log.show_log, b, formatter,)
789
log.properties_handler_registry.remove(
790
'trivial_custom_prop_handler')
669
792
def test_properties_handler_bad_argument(self):
670
wt = self.make_standard_commit('bad_argument',
671
revprops={'a_prop':'test_value'})
672
sio = self.make_utf8_encoded_stringio()
793
wt = self.make_branch_and_tree('.')
795
self.build_tree(['a'])
797
b.nick = 'test_author_log'
798
wt.commit(message='add a',
799
timestamp=1132711707,
801
committer='Lorem Ipsum <test@example.com>',
802
authors=['John Doe <jdoe@example.com>'],
803
revprops={'a_prop':'test_value'})
673
805
formatter = log.LongLogFormatter(to_file=sio)
674
def bad_argument_prop_handler(revision):
675
return {'custom_prop_name':revision.properties['a_prop']}
677
log.properties_handler_registry.register(
678
'bad_argument_prop_handler',
679
bad_argument_prop_handler)
681
self.assertRaises(AttributeError, formatter.show_properties,
684
revision = wt.branch.repository.get_revision(wt.branch.last_revision())
685
formatter.show_properties(revision, '')
686
self.assertEqualDiff('''custom_prop_name: test_value\n''',
689
def test_show_ids(self):
690
wt = self.make_branch_and_tree('parent')
691
self.build_tree(['parent/f1', 'parent/f2'])
693
self.wt_commit(wt, 'first post', rev_id='a')
694
child_wt = wt.bzrdir.sprout('child').open_workingtree()
695
self.wt_commit(child_wt, 'branch 1 changes', rev_id='b')
696
wt.merge_from_branch(child_wt.branch)
697
self.wt_commit(wt, 'merge branch 1', rev_id='c')
698
self.assertFormatterResult("""\
699
------------------------------------------------------------
704
committer: Joe Foo <joe@foo.com>
706
timestamp: Tue 2005-11-22 00:00:02 +0000
709
------------------------------------------------------------
713
committer: Joe Foo <joe@foo.com>
715
timestamp: Tue 2005-11-22 00:00:01 +0000
718
------------------------------------------------------------
721
committer: Joe Foo <joe@foo.com>
723
timestamp: Tue 2005-11-22 00:00:00 +0000
727
wt.branch, log.LongLogFormatter,
728
formatter_kwargs=dict(levels=0,show_ids=True))
731
class TestLongLogFormatterWithoutMergeRevisions(TestCaseForLogFormatter):
807
def bad_argument_prop_handler(revision):
808
return {'custom_prop_name':revision.properties['a_prop']}
810
log.properties_handler_registry.register(
811
'bad_argument_prop_handler',
812
bad_argument_prop_handler)
814
self.assertRaises(AttributeError, formatter.show_properties,
817
revision = b.repository.get_revision(b.last_revision())
818
formatter.show_properties(revision, '')
819
self.assertEqualDiff('''custom_prop_name: test_value\n''',
822
log.properties_handler_registry.remove(
823
'bad_argument_prop_handler')
826
class TestLongLogFormatterWithoutMergeRevisions(TestCaseWithoutPropsHandler):
733
828
def test_long_verbose_log(self):
734
829
"""Verbose log includes changed files
738
wt = self.make_standard_commit('test_long_verbose_log', authors=[])
739
self.assertFormatterResult("""\
833
wt = self.make_branch_and_tree('.')
835
self.build_tree(['a'])
837
# XXX: why does a longer nick show up?
838
b.nick = 'test_verbose_log'
839
wt.commit(message='add a',
840
timestamp=1132711707,
842
committer='Lorem Ipsum <test@example.com>')
843
logfile = file('out.tmp', 'w+')
844
formatter = log.LongLogFormatter(to_file=logfile, levels=1)
845
log.show_log(b, formatter, verbose=True)
848
log_contents = logfile.read()
849
self.assertEqualDiff('''\
740
850
------------------------------------------------------------
742
852
committer: Lorem Ipsum <test@example.com>
743
branch nick: test_long_verbose_log
744
timestamp: Tue 2005-11-22 00:00:00 +0000
853
branch nick: test_verbose_log
854
timestamp: Wed 2005-11-23 12:08:27 +1000
750
wt.branch, log.LongLogFormatter,
751
formatter_kwargs=dict(levels=1),
752
show_log_kwargs=dict(verbose=True))
754
862
def test_long_verbose_contain_deltas(self):
755
863
wt = self.make_branch_and_tree('parent')
756
864
self.build_tree(['parent/f1', 'parent/f2'])
757
865
wt.add(['f1','f2'])
758
self.wt_commit(wt, 'first post')
759
child_wt = wt.bzrdir.sprout('child').open_workingtree()
866
wt.commit('first post')
867
self.run_bzr('branch parent child')
760
868
os.unlink('child/f1')
761
self.build_tree_contents([('child/f2', 'hello\n')])
762
self.wt_commit(child_wt, 'removed f1 and modified f2')
763
wt.merge_from_branch(child_wt.branch)
764
self.wt_commit(wt, 'merge branch 1')
765
self.assertFormatterResult("""\
869
file('child/f2', 'wb').write('hello\n')
870
self.run_bzr(['commit', '-m', 'removed f1 and modified f2',
873
self.run_bzr('merge ../child')
874
wt.commit('merge branch 1')
876
sio = self.make_utf8_encoded_stringio()
877
lf = log.LongLogFormatter(to_file=sio, levels=1)
878
log.show_log(b, lf, verbose=True)
879
the_log = normalize_log(sio.getvalue())
880
self.assertEqualDiff("""\
766
881
------------------------------------------------------------
768
committer: Joe Foo <joe@foo.com>
883
committer: Lorem Ipsum <test@example.com>
769
884
branch nick: parent
770
timestamp: Tue 2005-11-22 00:00:02 +0000
814
931
committer: Joe Foo <joe@foo.com>
815
932
branch nick: test
816
timestamp: Tue 2005-11-22 00:00:00 +0000
933
timestamp: Mon 2005-11-21 09:24:15 -0600
818
935
simple log message
820
b, log.LongLogFormatter,
821
formatter_kwargs=dict(levels=1))
823
939
def test_long_author_in_log(self):
824
940
"""Log includes the author name if it's set in
825
941
the revision properties
827
wt = self.make_standard_commit('test_author_log')
828
self.assertFormatterResult("""\
943
wt = self.make_branch_and_tree('.')
945
self.build_tree(['a'])
947
b.nick = 'test_author_log'
948
wt.commit(message='add a',
949
timestamp=1132711707,
951
committer='Lorem Ipsum <test@example.com>',
952
authors=['John Doe <jdoe@example.com>'])
954
formatter = log.LongLogFormatter(to_file=sio, levels=1)
955
log.show_log(b, formatter)
956
self.assertEqualDiff('''\
829
957
------------------------------------------------------------
831
959
author: John Doe <jdoe@example.com>
832
960
committer: Lorem Ipsum <test@example.com>
833
961
branch nick: test_author_log
834
timestamp: Tue 2005-11-22 00:00:00 +0000
962
timestamp: Wed 2005-11-23 12:08:27 +1000
838
wt.branch, log.LongLogFormatter,
839
formatter_kwargs=dict(levels=1))
841
968
def test_long_properties_in_log(self):
842
969
"""Log includes the custom properties returned by the registered
845
wt = self.make_standard_commit('test_properties_in_log')
846
def trivial_custom_prop_handler(revision):
847
return {'test_prop':'test_value'}
972
wt = self.make_branch_and_tree('.')
974
self.build_tree(['a'])
976
b.nick = 'test_properties_in_log'
977
wt.commit(message='add a',
978
timestamp=1132711707,
980
committer='Lorem Ipsum <test@example.com>',
981
authors=['John Doe <jdoe@example.com>'])
983
formatter = log.LongLogFormatter(to_file=sio, levels=1)
985
def trivial_custom_prop_handler(revision):
986
return {'test_prop':'test_value'}
849
log.properties_handler_registry.register(
850
'trivial_custom_prop_handler',
851
trivial_custom_prop_handler)
852
self.assertFormatterResult("""\
988
log.properties_handler_registry.register(
989
'trivial_custom_prop_handler',
990
trivial_custom_prop_handler)
991
log.show_log(b, formatter)
993
log.properties_handler_registry.remove(
994
'trivial_custom_prop_handler')
995
self.assertEqualDiff('''\
853
996
------------------------------------------------------------
855
998
test_prop: test_value
856
999
author: John Doe <jdoe@example.com>
857
1000
committer: Lorem Ipsum <test@example.com>
858
1001
branch nick: test_properties_in_log
859
timestamp: Tue 2005-11-22 00:00:00 +0000
1002
timestamp: Wed 2005-11-23 12:08:27 +1000
863
wt.branch, log.LongLogFormatter,
864
formatter_kwargs=dict(levels=1))
867
class TestLineLogFormatter(TestCaseForLogFormatter):
1009
class TestLineLogFormatter(tests.TestCaseWithTransport):
869
1011
def test_line_log(self):
870
1012
"""Line log should show revno
874
wt = self.make_standard_commit('test-line-log',
875
committer='Line-Log-Formatter Tester <test@line.log>',
877
self.assertFormatterResult("""\
878
1: Line-Log-Formatte... 2005-11-22 add a
880
wt.branch, log.LineLogFormatter)
1016
wt = self.make_branch_and_tree('.')
1018
self.build_tree(['a'])
1020
b.nick = 'test-line-log'
1021
wt.commit(message='add a',
1022
timestamp=1132711707,
1024
committer='Line-Log-Formatter Tester <test@line.log>')
1025
logfile = file('out.tmp', 'w+')
1026
formatter = log.LineLogFormatter(to_file=logfile)
1027
log.show_log(b, formatter)
1030
log_contents = logfile.read()
1031
self.assertEqualDiff('1: Line-Log-Formatte... 2005-11-23 add a\n',
882
1034
def test_trailing_newlines(self):
883
1035
wt = self.make_branch_and_tree('.')
884
b = self.make_commits_with_trailing_newlines(wt)
885
self.assertFormatterResult("""\
886
3: Joe Foo 2005-11-22 single line with trailing newline
887
2: Joe Foo 2005-11-22 multiline
888
1: Joe Foo 2005-11-22 simple log message
1036
b = make_commits_with_trailing_newlines(wt)
1037
sio = self.make_utf8_encoded_stringio()
1038
lf = log.LineLogFormatter(to_file=sio)
1040
self.assertEqualDiff("""\
1041
3: Joe Foo 2005-11-21 single line with trailing newline
1042
2: Joe Bar 2005-11-21 multiline
1043
1: Joe Foo 2005-11-21 simple log message
890
b, log.LineLogFormatter)
1047
def _prepare_tree_with_merges(self, with_tags=False):
1048
wt = self.make_branch_and_memory_tree('.')
1050
self.addCleanup(wt.unlock)
1052
wt.commit('rev-1', rev_id='rev-1',
1053
timestamp=1132586655, timezone=36000,
1054
committer='Joe Foo <joe@foo.com>')
1055
wt.commit('rev-merged', rev_id='rev-2a',
1056
timestamp=1132586700, timezone=36000,
1057
committer='Joe Foo <joe@foo.com>')
1058
wt.set_parent_ids(['rev-1', 'rev-2a'])
1059
wt.branch.set_last_revision_info(1, 'rev-1')
1060
wt.commit('rev-2', rev_id='rev-2b',
1061
timestamp=1132586800, timezone=36000,
1062
committer='Joe Foo <joe@foo.com>')
1065
branch.tags.set_tag('v0.2', 'rev-2b')
1066
wt.commit('rev-3', rev_id='rev-3',
1067
timestamp=1132586900, timezone=36000,
1068
committer='Jane Foo <jane@foo.com>')
1069
branch.tags.set_tag('v1.0rc1', 'rev-3')
1070
branch.tags.set_tag('v1.0', 'rev-3')
892
1073
def test_line_log_single_merge_revision(self):
893
1074
wt = self._prepare_tree_with_merges()
1075
logfile = self.make_utf8_encoded_stringio()
1076
formatter = log.LineLogFormatter(to_file=logfile)
894
1077
revspec = revisionspec.RevisionSpec.from_string('1.1.1')
895
rev = revspec.in_history(wt.branch)
896
self.assertFormatterResult("""\
1079
rev = revspec.in_history(wtb)
1080
log.show_log(wtb, formatter, start_revision=rev, end_revision=rev)
1081
self.assertEqualDiff("""\
897
1082
1.1.1: Joe Foo 2005-11-22 rev-merged
899
wt.branch, log.LineLogFormatter,
900
show_log_kwargs=dict(start_revision=rev, end_revision=rev))
902
1086
def test_line_log_with_tags(self):
903
1087
wt = self._prepare_tree_with_merges(with_tags=True)
904
self.assertFormatterResult("""\
905
3: Joe Foo 2005-11-22 {v1.0, v1.0rc1} rev-3
1088
logfile = self.make_utf8_encoded_stringio()
1089
formatter = log.LineLogFormatter(to_file=logfile)
1090
log.show_log(wt.branch, formatter)
1091
self.assertEqualDiff("""\
1092
3: Jane Foo 2005-11-22 {v1.0, v1.0rc1} rev-3
906
1093
2: Joe Foo 2005-11-22 [merge] {v0.2} rev-2
907
1094
1: Joe Foo 2005-11-22 rev-1
909
wt.branch, log.LineLogFormatter)
912
class TestLineLogFormatterWithMergeRevisions(TestCaseForLogFormatter):
1098
class TestLineLogFormatterWithMergeRevisions(tests.TestCaseWithTransport):
914
1100
def test_line_merge_revs_log(self):
915
1101
"""Line log should show revno
919
wt = self.make_standard_commit('test-line-log',
920
committer='Line-Log-Formatter Tester <test@line.log>',
922
self.assertFormatterResult("""\
923
1: Line-Log-Formatte... 2005-11-22 add a
925
wt.branch, log.LineLogFormatter)
1105
wt = self.make_branch_and_tree('.')
1107
self.build_tree(['a'])
1109
b.nick = 'test-line-log'
1110
wt.commit(message='add a',
1111
timestamp=1132711707,
1113
committer='Line-Log-Formatter Tester <test@line.log>')
1114
logfile = file('out.tmp', 'w+')
1115
formatter = log.LineLogFormatter(to_file=logfile, levels=0)
1116
log.show_log(b, formatter)
1119
log_contents = logfile.read()
1120
self.assertEqualDiff('1: Line-Log-Formatte... 2005-11-23 add a\n',
927
1123
def test_line_merge_revs_log_single_merge_revision(self):
928
wt = self._prepare_tree_with_merges()
1124
wt = self.make_branch_and_memory_tree('.')
1126
self.addCleanup(wt.unlock)
1128
wt.commit('rev-1', rev_id='rev-1',
1129
timestamp=1132586655, timezone=36000,
1130
committer='Joe Foo <joe@foo.com>')
1131
wt.commit('rev-merged', rev_id='rev-2a',
1132
timestamp=1132586700, timezone=36000,
1133
committer='Joe Foo <joe@foo.com>')
1134
wt.set_parent_ids(['rev-1', 'rev-2a'])
1135
wt.branch.set_last_revision_info(1, 'rev-1')
1136
wt.commit('rev-2', rev_id='rev-2b',
1137
timestamp=1132586800, timezone=36000,
1138
committer='Joe Foo <joe@foo.com>')
1139
logfile = self.make_utf8_encoded_stringio()
1140
formatter = log.LineLogFormatter(to_file=logfile, levels=0)
929
1141
revspec = revisionspec.RevisionSpec.from_string('1.1.1')
930
rev = revspec.in_history(wt.branch)
931
self.assertFormatterResult("""\
1143
rev = revspec.in_history(wtb)
1144
log.show_log(wtb, formatter, start_revision=rev, end_revision=rev)
1145
self.assertEqualDiff("""\
932
1146
1.1.1: Joe Foo 2005-11-22 rev-merged
934
wt.branch, log.LineLogFormatter,
935
formatter_kwargs=dict(levels=0),
936
show_log_kwargs=dict(start_revision=rev, end_revision=rev))
938
1150
def test_line_merge_revs_log_with_merges(self):
939
wt = self._prepare_tree_with_merges()
940
self.assertFormatterResult("""\
1151
wt = self.make_branch_and_memory_tree('.')
1153
self.addCleanup(wt.unlock)
1155
wt.commit('rev-1', rev_id='rev-1',
1156
timestamp=1132586655, timezone=36000,
1157
committer='Joe Foo <joe@foo.com>')
1158
wt.commit('rev-merged', rev_id='rev-2a',
1159
timestamp=1132586700, timezone=36000,
1160
committer='Joe Foo <joe@foo.com>')
1161
wt.set_parent_ids(['rev-1', 'rev-2a'])
1162
wt.branch.set_last_revision_info(1, 'rev-1')
1163
wt.commit('rev-2', rev_id='rev-2b',
1164
timestamp=1132586800, timezone=36000,
1165
committer='Joe Foo <joe@foo.com>')
1166
logfile = self.make_utf8_encoded_stringio()
1167
formatter = log.LineLogFormatter(to_file=logfile, levels=0)
1168
log.show_log(wt.branch, formatter)
1169
self.assertEqualDiff("""\
941
1170
2: Joe Foo 2005-11-22 [merge] rev-2
942
1171
1.1.1: Joe Foo 2005-11-22 rev-merged
943
1172
1: Joe Foo 2005-11-22 rev-1
945
wt.branch, log.LineLogFormatter,
946
formatter_kwargs=dict(levels=0))
949
class TestGnuChangelogFormatter(TestCaseForLogFormatter):
951
def test_gnu_changelog(self):
952
wt = self.make_standard_commit('nicky', authors=[])
953
self.assertFormatterResult('''\
954
2005-11-22 Lorem Ipsum <test@example.com>
959
wt.branch, log.GnuChangelogLogFormatter)
961
def test_with_authors(self):
962
wt = self.make_standard_commit('nicky',
963
authors=['Fooa Fooz <foo@example.com>',
964
'Bari Baro <bar@example.com>'])
965
self.assertFormatterResult('''\
966
2005-11-22 Fooa Fooz <foo@example.com>
971
wt.branch, log.GnuChangelogLogFormatter)
973
def test_verbose(self):
974
wt = self.make_standard_commit('nicky')
975
self.assertFormatterResult('''\
976
2005-11-22 John Doe <jdoe@example.com>
983
wt.branch, log.GnuChangelogLogFormatter,
984
show_log_kwargs=dict(verbose=True))
1176
class TestGetViewRevisions(tests.TestCaseWithTransport):
1178
def make_tree_with_commits(self):
1179
"""Create a tree with well-known revision ids"""
1180
wt = self.make_branch_and_tree('tree1')
1181
wt.commit('commit one', rev_id='1')
1182
wt.commit('commit two', rev_id='2')
1183
wt.commit('commit three', rev_id='3')
1184
mainline_revs = [None, '1', '2', '3']
1185
rev_nos = {'1': 1, '2': 2, '3': 3}
1186
return mainline_revs, rev_nos, wt
1188
def make_tree_with_merges(self):
1189
"""Create a tree with well-known revision ids and a merge"""
1190
mainline_revs, rev_nos, wt = self.make_tree_with_commits()
1191
tree2 = wt.bzrdir.sprout('tree2').open_workingtree()
1192
tree2.commit('four-a', rev_id='4a')
1193
wt.merge_from_branch(tree2.branch)
1194
wt.commit('four-b', rev_id='4b')
1195
mainline_revs.append('4b')
1198
return mainline_revs, rev_nos, wt
1200
def make_tree_with_many_merges(self):
1201
"""Create a tree with well-known revision ids"""
1202
wt = self.make_branch_and_tree('tree1')
1203
self.build_tree_contents([('tree1/f', '1\n')])
1204
wt.add(['f'], ['f-id'])
1205
wt.commit('commit one', rev_id='1')
1206
wt.commit('commit two', rev_id='2')
1208
tree3 = wt.bzrdir.sprout('tree3').open_workingtree()
1209
self.build_tree_contents([('tree3/f', '1\n2\n3a\n')])
1210
tree3.commit('commit three a', rev_id='3a')
1212
tree2 = wt.bzrdir.sprout('tree2').open_workingtree()
1213
tree2.merge_from_branch(tree3.branch)
1214
tree2.commit('commit three b', rev_id='3b')
1216
wt.merge_from_branch(tree2.branch)
1217
wt.commit('commit three c', rev_id='3c')
1218
tree2.commit('four-a', rev_id='4a')
1220
wt.merge_from_branch(tree2.branch)
1221
wt.commit('four-b', rev_id='4b')
1223
mainline_revs = [None, '1', '2', '3c', '4b']
1224
rev_nos = {'1':1, '2':2, '3c': 3, '4b':4}
1225
full_rev_nos_for_reference = {
1228
'3a': '2.1.1', #first commit tree 3
1229
'3b': '2.2.1', # first commit tree 2
1230
'3c': '3', #merges 3b to main
1231
'4a': '2.2.2', # second commit tree 2
1232
'4b': '4', # merges 4a to main
1234
return mainline_revs, rev_nos, wt
1236
def test_get_view_revisions_forward(self):
1237
"""Test the get_view_revisions method"""
1238
mainline_revs, rev_nos, wt = self.make_tree_with_commits()
1240
self.addCleanup(wt.unlock)
1241
revisions = list(log.get_view_revisions(
1242
mainline_revs, rev_nos, wt.branch, 'forward'))
1243
self.assertEqual([('1', '1', 0), ('2', '2', 0), ('3', '3', 0)],
1245
revisions2 = list(log.get_view_revisions(
1246
mainline_revs, rev_nos, wt.branch, 'forward',
1247
include_merges=False))
1248
self.assertEqual(revisions, revisions2)
1250
def test_get_view_revisions_reverse(self):
1251
"""Test the get_view_revisions with reverse"""
1252
mainline_revs, rev_nos, wt = self.make_tree_with_commits()
1254
self.addCleanup(wt.unlock)
1255
revisions = list(log.get_view_revisions(
1256
mainline_revs, rev_nos, wt.branch, 'reverse'))
1257
self.assertEqual([('3', '3', 0), ('2', '2', 0), ('1', '1', 0), ],
1259
revisions2 = list(log.get_view_revisions(
1260
mainline_revs, rev_nos, wt.branch, 'reverse',
1261
include_merges=False))
1262
self.assertEqual(revisions, revisions2)
1264
def test_get_view_revisions_merge(self):
1265
"""Test get_view_revisions when there are merges"""
1266
mainline_revs, rev_nos, wt = self.make_tree_with_merges()
1268
self.addCleanup(wt.unlock)
1269
revisions = list(log.get_view_revisions(
1270
mainline_revs, rev_nos, wt.branch, 'forward'))
1271
self.assertEqual([('1', '1', 0), ('2', '2', 0), ('3', '3', 0),
1272
('4b', '4', 0), ('4a', '3.1.1', 1)],
1274
revisions = list(log.get_view_revisions(
1275
mainline_revs, rev_nos, wt.branch, 'forward',
1276
include_merges=False))
1277
self.assertEqual([('1', '1', 0), ('2', '2', 0), ('3', '3', 0),
1281
def test_get_view_revisions_merge_reverse(self):
1282
"""Test get_view_revisions in reverse when there are merges"""
1283
mainline_revs, rev_nos, wt = self.make_tree_with_merges()
1285
self.addCleanup(wt.unlock)
1286
revisions = list(log.get_view_revisions(
1287
mainline_revs, rev_nos, wt.branch, 'reverse'))
1288
self.assertEqual([('4b', '4', 0), ('4a', '3.1.1', 1),
1289
('3', '3', 0), ('2', '2', 0), ('1', '1', 0)],
1291
revisions = list(log.get_view_revisions(
1292
mainline_revs, rev_nos, wt.branch, 'reverse',
1293
include_merges=False))
1294
self.assertEqual([('4b', '4', 0), ('3', '3', 0), ('2', '2', 0),
1298
def test_get_view_revisions_merge2(self):
1299
"""Test get_view_revisions when there are merges"""
1300
mainline_revs, rev_nos, wt = self.make_tree_with_many_merges()
1302
self.addCleanup(wt.unlock)
1303
revisions = list(log.get_view_revisions(
1304
mainline_revs, rev_nos, wt.branch, 'forward'))
1305
expected = [('1', '1', 0), ('2', '2', 0), ('3c', '3', 0),
1306
('3a', '2.1.1', 1), ('3b', '2.2.1', 1), ('4b', '4', 0),
1308
self.assertEqual(expected, revisions)
1309
revisions = list(log.get_view_revisions(
1310
mainline_revs, rev_nos, wt.branch, 'forward',
1311
include_merges=False))
1312
self.assertEqual([('1', '1', 0), ('2', '2', 0), ('3c', '3', 0),
1317
def test_file_id_for_range(self):
1318
mainline_revs, rev_nos, wt = self.make_tree_with_many_merges()
1320
self.addCleanup(wt.unlock)
1322
def rev_from_rev_id(revid, branch):
1323
revspec = revisionspec.RevisionSpec.from_string('revid:%s' % revid)
1324
return revspec.in_history(branch)
1326
def view_revs(start_rev, end_rev, file_id, direction):
1327
revs = log.calculate_view_revisions(
1329
start_rev, # start_revision
1330
end_rev, # end_revision
1331
direction, # direction
1332
file_id, # specific_fileid
1333
True, # generate_merge_revisions
1337
rev_3a = rev_from_rev_id('3a', wt.branch)
1338
rev_4b = rev_from_rev_id('4b', wt.branch)
1339
self.assertEqual([('3c', '3', 0), ('3a', '2.1.1', 1)],
1340
view_revs(rev_3a, rev_4b, 'f-id', 'reverse'))
1341
# Note: 3c still appears before 3a here because of depth-based sorting
1342
self.assertEqual([('3c', '3', 0), ('3a', '2.1.1', 1)],
1343
view_revs(rev_3a, rev_4b, 'f-id', 'forward'))
1346
class TestGetRevisionsTouchingFileID(tests.TestCaseWithTransport):
1348
def create_tree_with_single_merge(self):
1349
"""Create a branch with a moderate layout.
1351
The revision graph looks like:
1359
In this graph, A introduced files f1 and f2 and f3.
1360
B modifies f1 and f3, and C modifies f2 and f3.
1361
D merges the changes from B and C and resolves the conflict for f3.
1363
# TODO: jam 20070218 This seems like it could really be done
1364
# with make_branch_and_memory_tree() if we could just
1365
# create the content of those files.
1366
# TODO: jam 20070218 Another alternative is that we would really
1367
# like to only create this tree 1 time for all tests that
1368
# use it. Since 'log' only uses the tree in a readonly
1369
# fashion, it seems a shame to regenerate an identical
1370
# tree for each test.
1371
tree = self.make_branch_and_tree('tree')
1373
self.addCleanup(tree.unlock)
1375
self.build_tree_contents([('tree/f1', 'A\n'),
1379
tree.add(['f1', 'f2', 'f3'], ['f1-id', 'f2-id', 'f3-id'])
1380
tree.commit('A', rev_id='A')
1382
self.build_tree_contents([('tree/f2', 'A\nC\n'),
1383
('tree/f3', 'A\nC\n'),
1385
tree.commit('C', rev_id='C')
1386
# Revert back to A to build the other history.
1387
tree.set_last_revision('A')
1388
tree.branch.set_last_revision_info(1, 'A')
1389
self.build_tree_contents([('tree/f1', 'A\nB\n'),
1391
('tree/f3', 'A\nB\n'),
1393
tree.commit('B', rev_id='B')
1394
tree.set_parent_ids(['B', 'C'])
1395
self.build_tree_contents([('tree/f1', 'A\nB\n'),
1396
('tree/f2', 'A\nC\n'),
1397
('tree/f3', 'A\nB\nC\n'),
1399
tree.commit('D', rev_id='D')
1401
# Switch to a read lock for this tree.
1402
# We still have an addCleanup(tree.unlock) pending
1407
def check_delta(self, delta, **kw):
1408
"""Check the filenames touched by a delta are as expected.
1410
Caller only have to pass in the list of files for each part, all
1411
unspecified parts are considered empty (and checked as such).
1413
for n in 'added', 'removed', 'renamed', 'modified', 'unchanged':
1414
# By default we expect an empty list
1415
expected = kw.get(n, [])
1416
# strip out only the path components
1417
got = [x[0] for x in getattr(delta, n)]
1418
self.assertEqual(expected, got)
1420
def test_tree_with_single_merge(self):
1421
"""Make sure the tree layout is correct."""
1422
tree = self.create_tree_with_single_merge()
1423
rev_A_tree = tree.branch.repository.revision_tree('A')
1424
rev_B_tree = tree.branch.repository.revision_tree('B')
1425
rev_C_tree = tree.branch.repository.revision_tree('C')
1426
rev_D_tree = tree.branch.repository.revision_tree('D')
1428
self.check_delta(rev_B_tree.changes_from(rev_A_tree),
1429
modified=['f1', 'f3'])
1431
self.check_delta(rev_C_tree.changes_from(rev_A_tree),
1432
modified=['f2', 'f3'])
1434
self.check_delta(rev_D_tree.changes_from(rev_B_tree),
1435
modified=['f2', 'f3'])
1437
self.check_delta(rev_D_tree.changes_from(rev_C_tree),
1438
modified=['f1', 'f3'])
1440
def assertAllRevisionsForFileID(self, tree, file_id, revisions):
1441
"""Ensure _filter_revisions_touching_file_id returns the right values.
1443
Get the return value from _filter_revisions_touching_file_id and make
1444
sure they are correct.
1446
# The api for _filter_revisions_touching_file_id is a little crazy.
1447
# So we do the setup here.
1448
mainline = tree.branch.revision_history()
1449
mainline.insert(0, None)
1450
revnos = dict((rev, idx+1) for idx, rev in enumerate(mainline))
1451
view_revs_iter = log.get_view_revisions(mainline, revnos, tree.branch,
1453
actual_revs = log._filter_revisions_touching_file_id(
1456
list(view_revs_iter))
1457
self.assertEqual(revisions, [r for r, revno, depth in actual_revs])
1459
def test_file_id_f1(self):
1460
tree = self.create_tree_with_single_merge()
1461
# f1 should be marked as modified by revisions A and B
1462
self.assertAllRevisionsForFileID(tree, 'f1-id', ['B', 'A'])
1464
def test_file_id_f2(self):
1465
tree = self.create_tree_with_single_merge()
1466
# f2 should be marked as modified by revisions A, C, and D
1467
# because D merged the changes from C.
1468
self.assertAllRevisionsForFileID(tree, 'f2-id', ['D', 'C', 'A'])
1470
def test_file_id_f3(self):
1471
tree = self.create_tree_with_single_merge()
1472
# f3 should be marked as modified by revisions A, B, C, and D
1473
self.assertAllRevisionsForFileID(tree, 'f3-id', ['D', 'C', 'B', 'A'])
1475
def test_file_id_with_ghosts(self):
1476
# This is testing bug #209948, where having a ghost would cause
1477
# _filter_revisions_touching_file_id() to fail.
1478
tree = self.create_tree_with_single_merge()
1479
# We need to add a revision, so switch back to a write-locked tree
1480
# (still a single addCleanup(tree.unlock) pending).
1483
first_parent = tree.last_revision()
1484
tree.set_parent_ids([first_parent, 'ghost-revision-id'])
1485
self.build_tree_contents([('tree/f1', 'A\nB\nXX\n')])
1486
tree.commit('commit with a ghost', rev_id='XX')
1487
self.assertAllRevisionsForFileID(tree, 'f1-id', ['XX', 'B', 'A'])
1488
self.assertAllRevisionsForFileID(tree, 'f2-id', ['D', 'C', 'A'])
1490
def test_unknown_file_id(self):
1491
tree = self.create_tree_with_single_merge()
1492
self.assertAllRevisionsForFileID(tree, 'unknown', [])
1494
def test_empty_branch_unknown_file_id(self):
1495
tree = self.make_branch_and_tree('tree')
1496
self.assertAllRevisionsForFileID(tree, 'unknown', [])
987
1499
class TestShowChangedRevisions(tests.TestCaseWithTransport):
1186
1697
log.show_branch_change(tree.branch, s, 3, '3b')
1187
1698
self.assertContainsRe(s.getvalue(), 'Removed Revisions:')
1188
1699
self.assertNotContainsRe(s.getvalue(), 'Added Revisions:')
1191
class TestRevisionNotInBranch(TestCaseForLogFormatter):
1193
def setup_a_tree(self):
1194
tree = self.make_branch_and_tree('tree')
1196
self.addCleanup(tree.unlock)
1198
'committer': 'Joe Foo <joe@foo.com>',
1199
'timestamp': 1132617600, # Mon 2005-11-22 00:00:00 +0000
1200
'timezone': 0, # UTC
1202
tree.commit('commit 1a', rev_id='1a', **kwargs)
1203
tree.commit('commit 2a', rev_id='2a', **kwargs)
1204
tree.commit('commit 3a', rev_id='3a', **kwargs)
1207
def setup_ab_tree(self):
1208
tree = self.setup_a_tree()
1209
tree.set_last_revision('1a')
1210
tree.branch.set_last_revision_info(1, '1a')
1212
'committer': 'Joe Foo <joe@foo.com>',
1213
'timestamp': 1132617600, # Mon 2005-11-22 00:00:00 +0000
1214
'timezone': 0, # UTC
1216
tree.commit('commit 2b', rev_id='2b', **kwargs)
1217
tree.commit('commit 3b', rev_id='3b', **kwargs)
1220
def test_one_revision(self):
1221
tree = self.setup_ab_tree()
1223
rev = revisionspec.RevisionInfo(tree.branch, None, '3a')
1224
log.show_log(tree.branch, lf, verbose=True, start_revision=rev,
1226
self.assertEqual(1, len(lf.revisions))
1227
self.assertEqual(None, lf.revisions[0].revno) # Out-of-branch
1228
self.assertEqual('3a', lf.revisions[0].rev.revision_id)
1230
def test_many_revisions(self):
1231
tree = self.setup_ab_tree()
1233
start_rev = revisionspec.RevisionInfo(tree.branch, None, '1a')
1234
end_rev = revisionspec.RevisionInfo(tree.branch, None, '3a')
1235
log.show_log(tree.branch, lf, verbose=True, start_revision=start_rev,
1236
end_revision=end_rev)
1237
self.assertEqual(3, len(lf.revisions))
1238
self.assertEqual(None, lf.revisions[0].revno) # Out-of-branch
1239
self.assertEqual('3a', lf.revisions[0].rev.revision_id)
1240
self.assertEqual(None, lf.revisions[1].revno) # Out-of-branch
1241
self.assertEqual('2a', lf.revisions[1].rev.revision_id)
1242
self.assertEqual('1', lf.revisions[2].revno) # In-branch
1244
def test_long_format(self):
1245
tree = self.setup_ab_tree()
1246
start_rev = revisionspec.RevisionInfo(tree.branch, None, '1a')
1247
end_rev = revisionspec.RevisionInfo(tree.branch, None, '3a')
1248
self.assertFormatterResult("""\
1249
------------------------------------------------------------
1251
committer: Joe Foo <joe@foo.com>
1253
timestamp: Tue 2005-11-22 00:00:00 +0000
1256
------------------------------------------------------------
1258
committer: Joe Foo <joe@foo.com>
1260
timestamp: Tue 2005-11-22 00:00:00 +0000
1263
------------------------------------------------------------
1265
committer: Joe Foo <joe@foo.com>
1267
timestamp: Tue 2005-11-22 00:00:00 +0000
1271
tree.branch, log.LongLogFormatter, show_log_kwargs={
1272
'start_revision': start_rev, 'end_revision': end_rev
1275
def test_short_format(self):
1276
tree = self.setup_ab_tree()
1277
start_rev = revisionspec.RevisionInfo(tree.branch, None, '1a')
1278
end_rev = revisionspec.RevisionInfo(tree.branch, None, '3a')
1279
self.assertFormatterResult("""\
1288
1 Joe Foo\t2005-11-22
1292
tree.branch, log.ShortLogFormatter, show_log_kwargs={
1293
'start_revision': start_rev, 'end_revision': end_rev
1296
def test_line_format(self):
1297
tree = self.setup_ab_tree()
1298
start_rev = revisionspec.RevisionInfo(tree.branch, None, '1a')
1299
end_rev = revisionspec.RevisionInfo(tree.branch, None, '3a')
1300
self.assertFormatterResult("""\
1301
Joe Foo 2005-11-22 commit 3a
1302
Joe Foo 2005-11-22 commit 2a
1303
1: Joe Foo 2005-11-22 commit 1a
1305
tree.branch, log.LineLogFormatter, show_log_kwargs={
1306
'start_revision': start_rev, 'end_revision': end_rev
1310
class TestLogWithBugs(TestCaseForLogFormatter, TestLogMixin):
1313
TestCaseForLogFormatter.setUp(self)
1314
log.properties_handler_registry.register(
1315
'bugs_properties_handler',
1316
log._bugs_properties_handler)
1318
def make_commits_with_bugs(self):
1319
"""Helper method for LogFormatter tests"""
1320
tree = self.make_branch_and_tree(u'.')
1321
self.build_tree(['a', 'b'])
1323
self.wt_commit(tree, 'simple log message', rev_id='a1',
1324
revprops={'bugs': 'test://bug/id fixed'})
1326
self.wt_commit(tree, 'multiline\nlog\nmessage\n', rev_id='a2',
1327
authors=['Joe Bar <joe@bar.com>'],
1328
revprops={'bugs': 'test://bug/id fixed\n'
1329
'test://bug/2 fixed'})
1333
def test_long_bugs(self):
1334
tree = self.make_commits_with_bugs()
1335
self.assertFormatterResult("""\
1336
------------------------------------------------------------
1338
fixes bug(s): test://bug/id test://bug/2
1339
author: Joe Bar <joe@bar.com>
1340
committer: Joe Foo <joe@foo.com>
1342
timestamp: Tue 2005-11-22 00:00:01 +0000
1347
------------------------------------------------------------
1349
fixes bug(s): test://bug/id
1350
committer: Joe Foo <joe@foo.com>
1352
timestamp: Tue 2005-11-22 00:00:00 +0000
1356
tree.branch, log.LongLogFormatter)
1358
def test_short_bugs(self):
1359
tree = self.make_commits_with_bugs()
1360
self.assertFormatterResult("""\
1361
2 Joe Bar\t2005-11-22
1362
fixes bug(s): test://bug/id test://bug/2
1367
1 Joe Foo\t2005-11-22
1368
fixes bug(s): test://bug/id
1372
tree.branch, log.ShortLogFormatter)
1374
def test_wrong_bugs_property(self):
1375
tree = self.make_branch_and_tree(u'.')
1376
self.build_tree(['foo'])
1377
self.wt_commit(tree, 'simple log message', rev_id='a1',
1378
revprops={'bugs': 'test://bug/id invalid_value'})
1379
self.assertFormatterResult("""\
1380
1 Joe Foo\t2005-11-22
1384
tree.branch, log.ShortLogFormatter)
1386
def test_bugs_handler_present(self):
1387
self.properties_handler_registry.get('bugs_properties_handler')
1390
class TestLogForAuthors(TestCaseForLogFormatter):
1393
TestCaseForLogFormatter.setUp(self)
1394
self.wt = self.make_standard_commit('nicky',
1395
authors=['John Doe <jdoe@example.com>',
1396
'Jane Rey <jrey@example.com>'])
1398
def assertFormatterResult(self, formatter, who, result):
1399
formatter_kwargs = dict()
1401
author_list_handler = log.author_list_registry.get(who)
1402
formatter_kwargs['author_list_handler'] = author_list_handler
1403
TestCaseForLogFormatter.assertFormatterResult(self, result,
1404
self.wt.branch, formatter, formatter_kwargs=formatter_kwargs)
1406
def test_line_default(self):
1407
self.assertFormatterResult(log.LineLogFormatter, None, """\
1408
1: John Doe 2005-11-22 add a
1411
def test_line_committer(self):
1412
self.assertFormatterResult(log.LineLogFormatter, 'committer', """\
1413
1: Lorem Ipsum 2005-11-22 add a
1416
def test_line_first(self):
1417
self.assertFormatterResult(log.LineLogFormatter, 'first', """\
1418
1: John Doe 2005-11-22 add a
1421
def test_line_all(self):
1422
self.assertFormatterResult(log.LineLogFormatter, 'all', """\
1423
1: John Doe, Jane Rey 2005-11-22 add a
1427
def test_short_default(self):
1428
self.assertFormatterResult(log.ShortLogFormatter, None, """\
1429
1 John Doe\t2005-11-22
1434
def test_short_committer(self):
1435
self.assertFormatterResult(log.ShortLogFormatter, 'committer', """\
1436
1 Lorem Ipsum\t2005-11-22
1441
def test_short_first(self):
1442
self.assertFormatterResult(log.ShortLogFormatter, 'first', """\
1443
1 John Doe\t2005-11-22
1448
def test_short_all(self):
1449
self.assertFormatterResult(log.ShortLogFormatter, 'all', """\
1450
1 John Doe, Jane Rey\t2005-11-22
1455
def test_long_default(self):
1456
self.assertFormatterResult(log.LongLogFormatter, None, """\
1457
------------------------------------------------------------
1459
author: John Doe <jdoe@example.com>, Jane Rey <jrey@example.com>
1460
committer: Lorem Ipsum <test@example.com>
1462
timestamp: Tue 2005-11-22 00:00:00 +0000
1467
def test_long_committer(self):
1468
self.assertFormatterResult(log.LongLogFormatter, 'committer', """\
1469
------------------------------------------------------------
1471
committer: Lorem Ipsum <test@example.com>
1473
timestamp: Tue 2005-11-22 00:00:00 +0000
1478
def test_long_first(self):
1479
self.assertFormatterResult(log.LongLogFormatter, 'first', """\
1480
------------------------------------------------------------
1482
author: John Doe <jdoe@example.com>
1483
committer: Lorem Ipsum <test@example.com>
1485
timestamp: Tue 2005-11-22 00:00:00 +0000
1490
def test_long_all(self):
1491
self.assertFormatterResult(log.LongLogFormatter, 'all', """\
1492
------------------------------------------------------------
1494
author: John Doe <jdoe@example.com>, Jane Rey <jrey@example.com>
1495
committer: Lorem Ipsum <test@example.com>
1497
timestamp: Tue 2005-11-22 00:00:00 +0000
1502
def test_gnu_changelog_default(self):
1503
self.assertFormatterResult(log.GnuChangelogLogFormatter, None, """\
1504
2005-11-22 John Doe <jdoe@example.com>
1510
def test_gnu_changelog_committer(self):
1511
self.assertFormatterResult(log.GnuChangelogLogFormatter, 'committer', """\
1512
2005-11-22 Lorem Ipsum <test@example.com>
1518
def test_gnu_changelog_first(self):
1519
self.assertFormatterResult(log.GnuChangelogLogFormatter, 'first', """\
1520
2005-11-22 John Doe <jdoe@example.com>
1526
def test_gnu_changelog_all(self):
1527
self.assertFormatterResult(log.GnuChangelogLogFormatter, 'all', """\
1528
2005-11-22 John Doe <jdoe@example.com>, Jane Rey <jrey@example.com>
1535
class TestLogExcludeAncestry(tests.TestCaseWithTransport):
1537
def make_branch_with_alternate_ancestries(self, relpath='.'):
1538
# See test_merge_sorted_exclude_ancestry below for the difference with
1539
# bt.per_branch.test_iter_merge_sorted_revision.
1540
# TestIterMergeSortedRevisionsBushyGraph.
1541
# make_branch_with_alternate_ancestries
1542
# and test_merge_sorted_exclude_ancestry
1543
# See the FIXME in assertLogRevnos too.
1544
builder = branchbuilder.BranchBuilder(self.get_transport(relpath))
1556
builder.start_series()
1557
builder.build_snapshot('1', None, [
1558
('add', ('', 'TREE_ROOT', 'directory', '')),])
1559
builder.build_snapshot('1.1.1', ['1'], [])
1560
builder.build_snapshot('2', ['1'], [])
1561
builder.build_snapshot('1.2.1', ['1.1.1'], [])
1562
builder.build_snapshot('1.1.2', ['1.1.1', '1.2.1'], [])
1563
builder.build_snapshot('3', ['2', '1.1.2'], [])
1564
builder.finish_series()
1565
br = builder.get_branch()
1567
self.addCleanup(br.unlock)
1570
def assertLogRevnos(self, expected_revnos, b, start, end,
1571
exclude_common_ancestry, generate_merge_revisions=True):
1572
# FIXME: the layering in log makes it hard to test intermediate levels,
1573
# I wish adding filters with their parameters were easier...
1575
iter_revs = log._calc_view_revisions(
1576
b, start, end, direction='reverse',
1577
generate_merge_revisions=generate_merge_revisions,
1578
exclude_common_ancestry=exclude_common_ancestry)
1579
self.assertEqual(expected_revnos,
1580
[revid for revid, revno, depth in iter_revs])
1582
def test_merge_sorted_exclude_ancestry(self):
1583
b = self.make_branch_with_alternate_ancestries()
1584
self.assertLogRevnos(['3', '1.1.2', '1.2.1', '1.1.1', '2', '1'],
1585
b, '1', '3', exclude_common_ancestry=False)
1586
# '2' is part of the '3' ancestry but not part of '1.1.1' ancestry so
1587
# it should be mentioned even if merge_sort order will make it appear
1589
self.assertLogRevnos(['3', '1.1.2', '1.2.1', '2'],
1590
b, '1.1.1', '3', exclude_common_ancestry=True)
1592
def test_merge_sorted_simple_revnos_exclude_ancestry(self):
1593
b = self.make_branch_with_alternate_ancestries()
1594
self.assertLogRevnos(['3', '2'],
1595
b, '1', '3', exclude_common_ancestry=True,
1596
generate_merge_revisions=False)
1597
self.assertLogRevnos(['3', '1.1.2', '1.2.1', '1.1.1', '2'],
1598
b, '1', '3', exclude_common_ancestry=True,
1599
generate_merge_revisions=True)
1602
class TestLogDefaults(TestCaseForLogFormatter):
1603
def test_default_log_level(self):
1605
Test to ensure that specifying 'levels=1' to make_log_request_dict
1606
doesn't get overwritten when using a LogFormatter that supports more
1610
wt = self._prepare_tree_with_merges()
1613
class CustomLogFormatter(log.LogFormatter):
1614
def __init__(self, *args, **kwargs):
1615
super(CustomLogFormatter, self).__init__(*args, **kwargs)
1617
def get_levels(self):
1618
# log formatter supports all levels:
1620
def log_revision(self, revision):
1621
self.revisions.append(revision)
1623
log_formatter = LogCatcher()
1624
# First request we don't specify number of levels, we should get a
1625
# sensible default (whatever the LogFormatter handles - which in this
1626
# case is 0/everything):
1627
request = log.make_log_request_dict(limit=10)
1628
log.Logger(b, request).show(log_formatter)
1629
# should have all three revisions:
1630
self.assertEquals(len(log_formatter.revisions), 3)
1633
log_formatter = LogCatcher()
1634
# now explicitly request mainline revisions only:
1635
request = log.make_log_request_dict(limit=10, levels=1)
1636
log.Logger(b, request).show(log_formatter)
1637
# should now only have 2 revisions:
1638
self.assertEquals(len(log_formatter.revisions), 2)