420
wt.branch, log.ShortLogFormatter,
421
formatter_kwargs=dict(levels=0))
423
449
def test_short_merge_revs_log_single_merge_revision(self):
424
wt = self._prepare_tree_with_merges()
450
wt = self.make_branch_and_memory_tree('.')
452
self.addCleanup(wt.unlock)
454
wt.commit('rev-1', rev_id='rev-1',
455
timestamp=1132586655, timezone=36000,
456
committer='Joe Foo <joe@foo.com>')
457
wt.commit('rev-merged', rev_id='rev-2a',
458
timestamp=1132586700, timezone=36000,
459
committer='Joe Foo <joe@foo.com>')
460
wt.set_parent_ids(['rev-1', 'rev-2a'])
461
wt.branch.set_last_revision_info(1, 'rev-1')
462
wt.commit('rev-2', rev_id='rev-2b',
463
timestamp=1132586800, timezone=36000,
464
committer='Joe Foo <joe@foo.com>')
465
logfile = self.make_utf8_encoded_stringio()
466
formatter = log.ShortLogFormatter(to_file=logfile, levels=0)
425
467
revspec = revisionspec.RevisionSpec.from_string('1.1.1')
426
rev = revspec.in_history(wt.branch)
427
self.assertFormatterResult("""\
469
rev = revspec.in_history(wtb)
470
log.show_log(wtb, formatter, start_revision=rev, end_revision=rev)
471
self.assertEqualDiff("""\
428
472
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):
479
class TestLongLogFormatter(TestCaseWithoutPropsHandler):
439
481
def test_verbose_log(self):
440
482
"""Verbose log includes changed files
444
wt = self.make_standard_commit('test_verbose_log', authors=[])
445
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('''\
446
503
------------------------------------------------------------
448
505
committer: Lorem Ipsum <test@example.com>
449
506
branch nick: test_verbose_log
450
timestamp: Tue 2005-11-22 00:00:00 +0000
507
timestamp: Wed 2005-11-23 12:08:27 +1000
456
wt.branch, log.LongLogFormatter,
457
show_log_kwargs=dict(verbose=True))
459
515
def test_merges_are_indented_by_level(self):
460
516
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("""\
517
wt.commit('first post')
518
self.run_bzr('branch parent child')
519
self.run_bzr(['commit', '-m', 'branch 1', '--unchanged', 'child'])
520
self.run_bzr('branch child smallerchild')
521
self.run_bzr(['commit', '-m', 'branch 2', '--unchanged',
524
self.run_bzr('merge ../smallerchild')
525
self.run_bzr(['commit', '-m', 'merge branch 2'])
526
os.chdir('../parent')
527
self.run_bzr('merge ../child')
528
wt.commit('merge branch 1')
530
sio = self.make_utf8_encoded_stringio()
531
lf = log.LongLogFormatter(to_file=sio, levels=0)
532
log.show_log(b, lf, verbose=True)
533
the_log = normalize_log(sio.getvalue())
534
self.assertEqualDiff("""\
471
535
------------------------------------------------------------
473
committer: Joe Foo <joe@foo.com>
537
committer: Lorem Ipsum <test@example.com>
474
538
branch nick: parent
475
timestamp: Tue 2005-11-22 00:00:04 +0000
478
542
------------------------------------------------------------
479
543
revno: 1.1.2 [merge]
480
committer: Joe Foo <joe@foo.com>
544
committer: Lorem Ipsum <test@example.com>
481
545
branch nick: child
482
timestamp: Tue 2005-11-22 00:00:03 +0000
485
549
------------------------------------------------------------
487
committer: Joe Foo <joe@foo.com>
551
committer: Lorem Ipsum <test@example.com>
488
552
branch nick: smallerchild
489
timestamp: Tue 2005-11-22 00:00:02 +0000
492
556
------------------------------------------------------------
494
committer: Joe Foo <joe@foo.com>
558
committer: Lorem Ipsum <test@example.com>
495
559
branch nick: child
496
timestamp: Tue 2005-11-22 00:00:01 +0000
499
563
------------------------------------------------------------
501
committer: Joe Foo <joe@foo.com>
565
committer: Lorem Ipsum <test@example.com>
502
566
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
573
def test_verbose_merge_revisions_contain_deltas(self):
512
574
wt = self.make_branch_and_tree('parent')
513
575
self.build_tree(['parent/f1', 'parent/f2'])
514
576
wt.add(['f1','f2'])
515
self.wt_commit(wt, 'first post')
516
child_wt = wt.bzrdir.sprout('child').open_workingtree()
577
wt.commit('first post')
578
self.run_bzr('branch parent child')
517
579
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("""\
580
file('child/f2', 'wb').write('hello\n')
581
self.run_bzr(['commit', '-m', 'removed f1 and modified f2',
584
self.run_bzr('merge ../child')
585
wt.commit('merge branch 1')
587
sio = self.make_utf8_encoded_stringio()
588
lf = log.LongLogFormatter(to_file=sio, levels=0)
589
log.show_log(b, lf, verbose=True)
590
the_log = normalize_log(sio.getvalue())
591
self.assertEqualDiff("""\
523
592
------------------------------------------------------------
525
committer: Joe Foo <joe@foo.com>
594
committer: Lorem Ipsum <test@example.com>
526
595
branch nick: parent
527
timestamp: Tue 2005-11-22 00:00:02 +0000
582
653
committer: Joe Foo <joe@foo.com>
583
654
branch nick: test
584
timestamp: Tue 2005-11-22 00:00:00 +0000
655
timestamp: Mon 2005-11-21 09:24:15 -0600
586
657
simple log message
588
b, log.LongLogFormatter)
590
661
def test_author_in_log(self):
591
662
"""Log includes the author name if it's set in
592
663
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("""\
665
wt = self.make_branch_and_tree('.')
667
self.build_tree(['a'])
669
b.nick = 'test_author_log'
670
wt.commit(message='add a',
671
timestamp=1132711707,
673
committer='Lorem Ipsum <test@example.com>',
674
authors=['John Doe <jdoe@example.com>',
675
'Jane Rey <jrey@example.com>'])
677
formatter = log.LongLogFormatter(to_file=sio)
678
log.show_log(b, formatter)
679
self.assertEqualDiff('''\
598
680
------------------------------------------------------------
600
682
author: John Doe <jdoe@example.com>, Jane Rey <jrey@example.com>
601
683
committer: Lorem Ipsum <test@example.com>
602
684
branch nick: test_author_log
603
timestamp: Tue 2005-11-22 00:00:00 +0000
685
timestamp: Wed 2005-11-23 12:08:27 +1000
607
wt.branch, log.LongLogFormatter)
609
691
def test_properties_in_log(self):
610
692
"""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'}
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'}
617
# Cleaned up in setUp()
618
log.properties_handler_registry.register(
619
'trivial_custom_prop_handler',
620
trivial_custom_prop_handler)
621
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('''\
622
719
------------------------------------------------------------
624
721
test_prop: test_value
625
722
author: John Doe <jdoe@example.com>
626
723
committer: Lorem Ipsum <test@example.com>
627
724
branch nick: test_properties_in_log
628
timestamp: Tue 2005-11-22 00:00:00 +0000
725
timestamp: Wed 2005-11-23 12:08:27 +1000
632
wt.branch, log.LongLogFormatter)
634
731
def test_properties_in_short_log(self):
635
732
"""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'}
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'}
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
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('''\
759
1 John Doe\t2005-11-23
647
760
test_prop: test_value
651
wt.branch, log.ShortLogFormatter)
653
766
def test_error_in_properties_handler(self):
654
767
"""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()
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'})
660
782
formatter = log.LongLogFormatter(to_file=sio)
661
def trivial_custom_prop_handler(revision):
662
raise StandardError("a test error")
784
def trivial_custom_prop_handler(revision):
785
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,)
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')
669
795
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()
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'})
673
808
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):
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):
733
831
def test_long_verbose_log(self):
734
832
"""Verbose log includes changed files
738
wt = self.make_standard_commit('test_long_verbose_log', authors=[])
739
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('''\
740
853
------------------------------------------------------------
742
855
committer: Lorem Ipsum <test@example.com>
743
branch nick: test_long_verbose_log
744
timestamp: Tue 2005-11-22 00:00:00 +0000
856
branch nick: test_verbose_log
857
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
865
def test_long_verbose_contain_deltas(self):
755
866
wt = self.make_branch_and_tree('parent')
756
867
self.build_tree(['parent/f1', 'parent/f2'])
757
868
wt.add(['f1','f2'])
758
self.wt_commit(wt, 'first post')
759
child_wt = wt.bzrdir.sprout('child').open_workingtree()
869
wt.commit('first post')
870
self.run_bzr('branch parent child')
760
871
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("""\
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')
877
wt.commit('merge branch 1')
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("""\
766
884
------------------------------------------------------------
768
committer: Joe Foo <joe@foo.com>
886
committer: Lorem Ipsum <test@example.com>
769
887
branch nick: parent
770
timestamp: Tue 2005-11-22 00:00:02 +0000
814
934
committer: Joe Foo <joe@foo.com>
815
935
branch nick: test
816
timestamp: Tue 2005-11-22 00:00:00 +0000
936
timestamp: Mon 2005-11-21 09:24:15 -0600
818
938
simple log message
820
b, log.LongLogFormatter,
821
formatter_kwargs=dict(levels=1))
823
942
def test_long_author_in_log(self):
824
943
"""Log includes the author name if it's set in
825
944
the revision properties
827
wt = self.make_standard_commit('test_author_log')
828
self.assertFormatterResult("""\
946
wt = self.make_branch_and_tree('.')
948
self.build_tree(['a'])
950
b.nick = 'test_author_log'
951
wt.commit(message='add a',
952
timestamp=1132711707,
954
committer='Lorem Ipsum <test@example.com>',
955
authors=['John Doe <jdoe@example.com>'])
957
formatter = log.LongLogFormatter(to_file=sio, levels=1)
958
log.show_log(b, formatter)
959
self.assertEqualDiff('''\
829
960
------------------------------------------------------------
831
962
author: John Doe <jdoe@example.com>
832
963
committer: Lorem Ipsum <test@example.com>
833
964
branch nick: test_author_log
834
timestamp: Tue 2005-11-22 00:00:00 +0000
965
timestamp: Wed 2005-11-23 12:08:27 +1000
838
wt.branch, log.LongLogFormatter,
839
formatter_kwargs=dict(levels=1))
841
971
def test_long_properties_in_log(self):
842
972
"""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'}
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'}
849
log.properties_handler_registry.register(
850
'trivial_custom_prop_handler',
851
trivial_custom_prop_handler)
852
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('''\
853
999
------------------------------------------------------------
855
1001
test_prop: test_value
856
1002
author: John Doe <jdoe@example.com>
857
1003
committer: Lorem Ipsum <test@example.com>
858
1004
branch nick: test_properties_in_log
859
timestamp: Tue 2005-11-22 00:00:00 +0000
1005
timestamp: Wed 2005-11-23 12:08:27 +1000
863
wt.branch, log.LongLogFormatter,
864
formatter_kwargs=dict(levels=1))
867
class TestLineLogFormatter(TestCaseForLogFormatter):
1012
class TestLineLogFormatter(tests.TestCaseWithTransport):
869
1014
def test_line_log(self):
870
1015
"""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)
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',
882
1037
def test_trailing_newlines(self):
883
1038
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
1039
b = make_commits_with_trailing_newlines(wt)
1040
sio = self.make_utf8_encoded_stringio()
1041
lf = log.LineLogFormatter(to_file=sio)
1043
self.assertEqualDiff("""\
1044
3: Joe Foo 2005-11-21 single line with trailing newline
1045
2: Joe Bar 2005-11-21 multiline
1046
1: Joe Foo 2005-11-21 simple log message
890
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')
892
1076
def test_line_log_single_merge_revision(self):
893
1077
wt = self._prepare_tree_with_merges()
1078
logfile = self.make_utf8_encoded_stringio()
1079
formatter = log.LineLogFormatter(to_file=logfile)
894
1080
revspec = revisionspec.RevisionSpec.from_string('1.1.1')
895
rev = revspec.in_history(wt.branch)
896
self.assertFormatterResult("""\
1082
rev = revspec.in_history(wtb)
1083
log.show_log(wtb, formatter, start_revision=rev, end_revision=rev)
1084
self.assertEqualDiff("""\
897
1085
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
1089
def test_line_log_with_tags(self):
903
1090
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
1091
logfile = self.make_utf8_encoded_stringio()
1092
formatter = log.LineLogFormatter(to_file=logfile)
1093
log.show_log(wt.branch, formatter)
1094
self.assertEqualDiff("""\
1095
3: Jane Foo 2005-11-22 {v1.0, v1.0rc1} rev-3
906
1096
2: Joe Foo 2005-11-22 [merge] {v0.2} rev-2
907
1097
1: Joe Foo 2005-11-22 rev-1
909
wt.branch, log.LineLogFormatter)
912
class TestLineLogFormatterWithMergeRevisions(TestCaseForLogFormatter):
1101
class TestLineLogFormatterWithMergeRevisions(tests.TestCaseWithTransport):
914
1103
def test_line_merge_revs_log(self):
915
1104
"""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)
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',
927
1126
def test_line_merge_revs_log_single_merge_revision(self):
928
wt = self._prepare_tree_with_merges()
1127
wt = self.make_branch_and_memory_tree('.')
1129
self.addCleanup(wt.unlock)
1131
wt.commit('rev-1', rev_id='rev-1',
1132
timestamp=1132586655, timezone=36000,
1133
committer='Joe Foo <joe@foo.com>')
1134
wt.commit('rev-merged', rev_id='rev-2a',
1135
timestamp=1132586700, timezone=36000,
1136
committer='Joe Foo <joe@foo.com>')
1137
wt.set_parent_ids(['rev-1', 'rev-2a'])
1138
wt.branch.set_last_revision_info(1, 'rev-1')
1139
wt.commit('rev-2', rev_id='rev-2b',
1140
timestamp=1132586800, timezone=36000,
1141
committer='Joe Foo <joe@foo.com>')
1142
logfile = self.make_utf8_encoded_stringio()
1143
formatter = log.LineLogFormatter(to_file=logfile, levels=0)
929
1144
revspec = revisionspec.RevisionSpec.from_string('1.1.1')
930
rev = revspec.in_history(wt.branch)
931
self.assertFormatterResult("""\
1146
rev = revspec.in_history(wtb)
1147
log.show_log(wtb, formatter, start_revision=rev, end_revision=rev)
1148
self.assertEqualDiff("""\
932
1149
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
1153
def test_line_merge_revs_log_with_merges(self):
939
wt = self._prepare_tree_with_merges()
940
self.assertFormatterResult("""\
1154
wt = self.make_branch_and_memory_tree('.')
1156
self.addCleanup(wt.unlock)
1158
wt.commit('rev-1', rev_id='rev-1',
1159
timestamp=1132586655, timezone=36000,
1160
committer='Joe Foo <joe@foo.com>')
1161
wt.commit('rev-merged', rev_id='rev-2a',
1162
timestamp=1132586700, timezone=36000,
1163
committer='Joe Foo <joe@foo.com>')
1164
wt.set_parent_ids(['rev-1', 'rev-2a'])
1165
wt.branch.set_last_revision_info(1, 'rev-1')
1166
wt.commit('rev-2', rev_id='rev-2b',
1167
timestamp=1132586800, timezone=36000,
1168
committer='Joe Foo <joe@foo.com>')
1169
logfile = self.make_utf8_encoded_stringio()
1170
formatter = log.LineLogFormatter(to_file=logfile, levels=0)
1171
log.show_log(wt.branch, formatter)
1172
self.assertEqualDiff("""\
941
1173
2: Joe Foo 2005-11-22 [merge] rev-2
942
1174
1.1.1: Joe Foo 2005-11-22 rev-merged
943
1175
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))
1179
class TestGetViewRevisions(tests.TestCaseWithTransport):
1181
def make_tree_with_commits(self):
1182
"""Create a tree with well-known revision ids"""
1183
wt = self.make_branch_and_tree('tree1')
1184
wt.commit('commit one', rev_id='1')
1185
wt.commit('commit two', rev_id='2')
1186
wt.commit('commit three', rev_id='3')
1187
mainline_revs = [None, '1', '2', '3']
1188
rev_nos = {'1': 1, '2': 2, '3': 3}
1189
return mainline_revs, rev_nos, wt
1191
def make_tree_with_merges(self):
1192
"""Create a tree with well-known revision ids and a merge"""
1193
mainline_revs, rev_nos, wt = self.make_tree_with_commits()
1194
tree2 = wt.bzrdir.sprout('tree2').open_workingtree()
1195
tree2.commit('four-a', rev_id='4a')
1196
wt.merge_from_branch(tree2.branch)
1197
wt.commit('four-b', rev_id='4b')
1198
mainline_revs.append('4b')
1201
return mainline_revs, rev_nos, wt
1203
def make_branch_with_many_merges(self):
1204
"""Create a tree with well-known revision ids"""
1205
builder = self.make_branch_builder('tree1')
1206
builder.start_series()
1207
builder.build_snapshot('1', None, [
1208
('add', ('', 'TREE_ROOT', 'directory', '')),
1209
('add', ('f', 'f-id', 'file', '1\n'))])
1210
builder.build_snapshot('2', ['1'], [])
1211
builder.build_snapshot('3a', ['2'], [
1212
('modify', ('f-id', '1\n2\n3a\n'))])
1213
builder.build_snapshot('3b', ['2', '3a'], [
1214
('modify', ('f-id', '1\n2\n3a\n'))])
1215
builder.build_snapshot('3c', ['2', '3b'], [
1216
('modify', ('f-id', '1\n2\n3a\n'))])
1217
builder.build_snapshot('4a', ['3b'], [])
1218
builder.build_snapshot('4b', ['3c', '4a'], [])
1219
builder.finish_series()
1233
mainline_revs = [None, '1', '2', '3c', '4b']
1234
rev_nos = {'1':1, '2':2, '3c': 3, '4b':4}
1235
full_rev_nos_for_reference = {
1238
'3a': '2.1.1', #first commit tree 3
1239
'3b': '2.2.1', # first commit tree 2
1240
'3c': '3', #merges 3b to main
1241
'4a': '2.2.2', # second commit tree 2
1242
'4b': '4', # merges 4a to main
1244
return mainline_revs, rev_nos, builder.get_branch()
1246
def test_get_view_revisions_forward(self):
1247
"""Test the get_view_revisions method"""
1248
mainline_revs, rev_nos, wt = self.make_tree_with_commits()
1250
self.addCleanup(wt.unlock)
1251
revisions = list(log.get_view_revisions(
1252
mainline_revs, rev_nos, wt.branch, 'forward'))
1253
self.assertEqual([('1', '1', 0), ('2', '2', 0), ('3', '3', 0)],
1255
revisions2 = list(log.get_view_revisions(
1256
mainline_revs, rev_nos, wt.branch, 'forward',
1257
include_merges=False))
1258
self.assertEqual(revisions, revisions2)
1260
def test_get_view_revisions_reverse(self):
1261
"""Test the get_view_revisions with reverse"""
1262
mainline_revs, rev_nos, wt = self.make_tree_with_commits()
1264
self.addCleanup(wt.unlock)
1265
revisions = list(log.get_view_revisions(
1266
mainline_revs, rev_nos, wt.branch, 'reverse'))
1267
self.assertEqual([('3', '3', 0), ('2', '2', 0), ('1', '1', 0), ],
1269
revisions2 = list(log.get_view_revisions(
1270
mainline_revs, rev_nos, wt.branch, 'reverse',
1271
include_merges=False))
1272
self.assertEqual(revisions, revisions2)
1274
def test_get_view_revisions_merge(self):
1275
"""Test get_view_revisions when there are merges"""
1276
mainline_revs, rev_nos, wt = self.make_tree_with_merges()
1278
self.addCleanup(wt.unlock)
1279
revisions = list(log.get_view_revisions(
1280
mainline_revs, rev_nos, wt.branch, 'forward'))
1281
self.assertEqual([('1', '1', 0), ('2', '2', 0), ('3', '3', 0),
1282
('4b', '4', 0), ('4a', '3.1.1', 1)],
1284
revisions = list(log.get_view_revisions(
1285
mainline_revs, rev_nos, wt.branch, 'forward',
1286
include_merges=False))
1287
self.assertEqual([('1', '1', 0), ('2', '2', 0), ('3', '3', 0),
1291
def test_get_view_revisions_merge_reverse(self):
1292
"""Test get_view_revisions in reverse when there are merges"""
1293
mainline_revs, rev_nos, wt = self.make_tree_with_merges()
1295
self.addCleanup(wt.unlock)
1296
revisions = list(log.get_view_revisions(
1297
mainline_revs, rev_nos, wt.branch, 'reverse'))
1298
self.assertEqual([('4b', '4', 0), ('4a', '3.1.1', 1),
1299
('3', '3', 0), ('2', '2', 0), ('1', '1', 0)],
1301
revisions = list(log.get_view_revisions(
1302
mainline_revs, rev_nos, wt.branch, 'reverse',
1303
include_merges=False))
1304
self.assertEqual([('4b', '4', 0), ('3', '3', 0), ('2', '2', 0),
1308
def test_get_view_revisions_merge2(self):
1309
"""Test get_view_revisions when there are merges"""
1310
mainline_revs, rev_nos, b = self.make_branch_with_many_merges()
1312
self.addCleanup(b.unlock)
1313
revisions = list(log.get_view_revisions(
1314
mainline_revs, rev_nos, b, 'forward'))
1315
expected = [('1', '1', 0), ('2', '2', 0), ('3c', '3', 0),
1316
('3b', '2.2.1', 1), ('3a', '2.1.1', 2), ('4b', '4', 0),
1318
self.assertEqual(expected, revisions)
1319
revisions = list(log.get_view_revisions(
1320
mainline_revs, rev_nos, b, 'forward',
1321
include_merges=False))
1322
self.assertEqual([('1', '1', 0), ('2', '2', 0), ('3c', '3', 0),
1327
def test_file_id_for_range(self):
1328
mainline_revs, rev_nos, b = self.make_branch_with_many_merges()
1330
self.addCleanup(b.unlock)
1332
def rev_from_rev_id(revid, branch):
1333
revspec = revisionspec.RevisionSpec.from_string('revid:%s' % revid)
1334
return revspec.in_history(branch)
1336
def view_revs(start_rev, end_rev, file_id, direction):
1337
revs = log.calculate_view_revisions(
1339
start_rev, # start_revision
1340
end_rev, # end_revision
1341
direction, # direction
1342
file_id, # specific_fileid
1343
True, # generate_merge_revisions
1347
rev_3a = rev_from_rev_id('3a', b)
1348
rev_4b = rev_from_rev_id('4b', b)
1349
self.assertEqual([('3c', '3', 0), ('3b', '2.2.1', 1), ('3a', '2.1.1', 2)],
1350
view_revs(rev_3a, rev_4b, 'f-id', 'reverse'))
1351
# Note: 3c still appears before 3a here because of depth-based sorting
1352
self.assertEqual([('3c', '3', 0), ('3b', '2.2.1', 1), ('3a', '2.1.1', 2)],
1353
view_revs(rev_3a, rev_4b, 'f-id', 'forward'))
1356
class TestGetRevisionsTouchingFileID(tests.TestCaseWithTransport):
1358
def create_tree_with_single_merge(self):
1359
"""Create a branch with a moderate layout.
1361
The revision graph looks like:
1369
In this graph, A introduced files f1 and f2 and f3.
1370
B modifies f1 and f3, and C modifies f2 and f3.
1371
D merges the changes from B and C and resolves the conflict for f3.
1373
# TODO: jam 20070218 This seems like it could really be done
1374
# with make_branch_and_memory_tree() if we could just
1375
# create the content of those files.
1376
# TODO: jam 20070218 Another alternative is that we would really
1377
# like to only create this tree 1 time for all tests that
1378
# use it. Since 'log' only uses the tree in a readonly
1379
# fashion, it seems a shame to regenerate an identical
1380
# tree for each test.
1381
tree = self.make_branch_and_tree('tree')
1383
self.addCleanup(tree.unlock)
1385
self.build_tree_contents([('tree/f1', 'A\n'),
1389
tree.add(['f1', 'f2', 'f3'], ['f1-id', 'f2-id', 'f3-id'])
1390
tree.commit('A', rev_id='A')
1392
self.build_tree_contents([('tree/f2', 'A\nC\n'),
1393
('tree/f3', 'A\nC\n'),
1395
tree.commit('C', rev_id='C')
1396
# Revert back to A to build the other history.
1397
tree.set_last_revision('A')
1398
tree.branch.set_last_revision_info(1, 'A')
1399
self.build_tree_contents([('tree/f1', 'A\nB\n'),
1401
('tree/f3', 'A\nB\n'),
1403
tree.commit('B', rev_id='B')
1404
tree.set_parent_ids(['B', 'C'])
1405
self.build_tree_contents([('tree/f1', 'A\nB\n'),
1406
('tree/f2', 'A\nC\n'),
1407
('tree/f3', 'A\nB\nC\n'),
1409
tree.commit('D', rev_id='D')
1411
# Switch to a read lock for this tree.
1412
# We still have an addCleanup(tree.unlock) pending
1417
def check_delta(self, delta, **kw):
1418
"""Check the filenames touched by a delta are as expected.
1420
Caller only have to pass in the list of files for each part, all
1421
unspecified parts are considered empty (and checked as such).
1423
for n in 'added', 'removed', 'renamed', 'modified', 'unchanged':
1424
# By default we expect an empty list
1425
expected = kw.get(n, [])
1426
# strip out only the path components
1427
got = [x[0] for x in getattr(delta, n)]
1428
self.assertEqual(expected, got)
1430
def test_tree_with_single_merge(self):
1431
"""Make sure the tree layout is correct."""
1432
tree = self.create_tree_with_single_merge()
1433
rev_A_tree = tree.branch.repository.revision_tree('A')
1434
rev_B_tree = tree.branch.repository.revision_tree('B')
1435
rev_C_tree = tree.branch.repository.revision_tree('C')
1436
rev_D_tree = tree.branch.repository.revision_tree('D')
1438
self.check_delta(rev_B_tree.changes_from(rev_A_tree),
1439
modified=['f1', 'f3'])
1441
self.check_delta(rev_C_tree.changes_from(rev_A_tree),
1442
modified=['f2', 'f3'])
1444
self.check_delta(rev_D_tree.changes_from(rev_B_tree),
1445
modified=['f2', 'f3'])
1447
self.check_delta(rev_D_tree.changes_from(rev_C_tree),
1448
modified=['f1', 'f3'])
1450
def assertAllRevisionsForFileID(self, tree, file_id, revisions):
1451
"""Ensure _filter_revisions_touching_file_id returns the right values.
1453
Get the return value from _filter_revisions_touching_file_id and make
1454
sure they are correct.
1456
# The api for _filter_revisions_touching_file_id is a little crazy.
1457
# So we do the setup here.
1458
mainline = tree.branch.revision_history()
1459
mainline.insert(0, None)
1460
revnos = dict((rev, idx+1) for idx, rev in enumerate(mainline))
1461
view_revs_iter = log.get_view_revisions(mainline, revnos, tree.branch,
1463
actual_revs = log._filter_revisions_touching_file_id(
1466
list(view_revs_iter))
1467
self.assertEqual(revisions, [r for r, revno, depth in actual_revs])
1469
def test_file_id_f1(self):
1470
tree = self.create_tree_with_single_merge()
1471
# f1 should be marked as modified by revisions A and B
1472
self.assertAllRevisionsForFileID(tree, 'f1-id', ['B', 'A'])
1474
def test_file_id_f2(self):
1475
tree = self.create_tree_with_single_merge()
1476
# f2 should be marked as modified by revisions A, C, and D
1477
# because D merged the changes from C.
1478
self.assertAllRevisionsForFileID(tree, 'f2-id', ['D', 'C', 'A'])
1480
def test_file_id_f3(self):
1481
tree = self.create_tree_with_single_merge()
1482
# f3 should be marked as modified by revisions A, B, C, and D
1483
self.assertAllRevisionsForFileID(tree, 'f3-id', ['D', 'C', 'B', 'A'])
1485
def test_file_id_with_ghosts(self):
1486
# This is testing bug #209948, where having a ghost would cause
1487
# _filter_revisions_touching_file_id() to fail.
1488
tree = self.create_tree_with_single_merge()
1489
# We need to add a revision, so switch back to a write-locked tree
1490
# (still a single addCleanup(tree.unlock) pending).
1493
first_parent = tree.last_revision()
1494
tree.set_parent_ids([first_parent, 'ghost-revision-id'])
1495
self.build_tree_contents([('tree/f1', 'A\nB\nXX\n')])
1496
tree.commit('commit with a ghost', rev_id='XX')
1497
self.assertAllRevisionsForFileID(tree, 'f1-id', ['XX', 'B', 'A'])
1498
self.assertAllRevisionsForFileID(tree, 'f2-id', ['D', 'C', 'A'])
1500
def test_unknown_file_id(self):
1501
tree = self.create_tree_with_single_merge()
1502
self.assertAllRevisionsForFileID(tree, 'unknown', [])
1504
def test_empty_branch_unknown_file_id(self):
1505
tree = self.make_branch_and_tree('tree')
1506
self.assertAllRevisionsForFileID(tree, 'unknown', [])
987
1509
class TestShowChangedRevisions(tests.TestCaseWithTransport):
1186
1707
log.show_branch_change(tree.branch, s, 3, '3b')
1187
1708
self.assertContainsRe(s.getvalue(), 'Removed Revisions:')
1188
1709
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)