914
1016
wt.branch, log.GnuChangelogLogFormatter,
915
1017
show_log_kwargs=dict(verbose=True))
917
class TestGetViewRevisions(tests.TestCaseWithTransport, TestLogMixin):
919
def _get_view_revisions(self, *args, **kwargs):
920
return self.applyDeprecated(symbol_versioning.deprecated_in((2, 2, 0)),
921
log.get_view_revisions, *args, **kwargs)
923
def make_tree_with_commits(self):
924
"""Create a tree with well-known revision ids"""
925
wt = self.make_branch_and_tree('tree1')
926
self.wt_commit(wt, 'commit one', rev_id='1')
927
self.wt_commit(wt, 'commit two', rev_id='2')
928
self.wt_commit(wt, 'commit three', rev_id='3')
929
mainline_revs = [None, '1', '2', '3']
930
rev_nos = {'1': 1, '2': 2, '3': 3}
931
return mainline_revs, rev_nos, wt
933
def make_tree_with_merges(self):
934
"""Create a tree with well-known revision ids and a merge"""
935
mainline_revs, rev_nos, wt = self.make_tree_with_commits()
936
tree2 = wt.bzrdir.sprout('tree2').open_workingtree()
937
self.wt_commit(tree2, 'four-a', rev_id='4a')
938
wt.merge_from_branch(tree2.branch)
939
self.wt_commit(wt, 'four-b', rev_id='4b')
940
mainline_revs.append('4b')
943
return mainline_revs, rev_nos, wt
945
def make_branch_with_many_merges(self):
946
"""Create a tree with well-known revision ids"""
947
builder = self.make_branch_builder('tree1')
948
builder.start_series()
949
builder.build_snapshot('1', None, [
950
('add', ('', 'TREE_ROOT', 'directory', '')),
951
('add', ('f', 'f-id', 'file', '1\n'))])
952
builder.build_snapshot('2', ['1'], [])
953
builder.build_snapshot('3a', ['2'], [
954
('modify', ('f-id', '1\n2\n3a\n'))])
955
builder.build_snapshot('3b', ['2', '3a'], [
956
('modify', ('f-id', '1\n2\n3a\n'))])
957
builder.build_snapshot('3c', ['2', '3b'], [
958
('modify', ('f-id', '1\n2\n3a\n'))])
959
builder.build_snapshot('4a', ['3b'], [])
960
builder.build_snapshot('4b', ['3c', '4a'], [])
961
builder.finish_series()
975
mainline_revs = [None, '1', '2', '3c', '4b']
976
rev_nos = {'1':1, '2':2, '3c': 3, '4b':4}
977
full_rev_nos_for_reference = {
980
'3a': '2.1.1', #first commit tree 3
981
'3b': '2.2.1', # first commit tree 2
982
'3c': '3', #merges 3b to main
983
'4a': '2.2.2', # second commit tree 2
984
'4b': '4', # merges 4a to main
986
return mainline_revs, rev_nos, builder.get_branch()
988
def test_get_view_revisions_forward(self):
989
"""Test the get_view_revisions method"""
990
mainline_revs, rev_nos, wt = self.make_tree_with_commits()
992
self.addCleanup(wt.unlock)
993
revisions = list(self._get_view_revisions(
994
mainline_revs, rev_nos, wt.branch, 'forward'))
995
self.assertEqual([('1', '1', 0), ('2', '2', 0), ('3', '3', 0)],
997
revisions2 = list(self._get_view_revisions(
998
mainline_revs, rev_nos, wt.branch, 'forward',
999
include_merges=False))
1000
self.assertEqual(revisions, revisions2)
1002
def test_get_view_revisions_reverse(self):
1003
"""Test the get_view_revisions with reverse"""
1004
mainline_revs, rev_nos, wt = self.make_tree_with_commits()
1006
self.addCleanup(wt.unlock)
1007
revisions = list(self._get_view_revisions(
1008
mainline_revs, rev_nos, wt.branch, 'reverse'))
1009
self.assertEqual([('3', '3', 0), ('2', '2', 0), ('1', '1', 0), ],
1011
revisions2 = list(self._get_view_revisions(
1012
mainline_revs, rev_nos, wt.branch, 'reverse',
1013
include_merges=False))
1014
self.assertEqual(revisions, revisions2)
1016
def test_get_view_revisions_merge(self):
1017
"""Test get_view_revisions when there are merges"""
1018
mainline_revs, rev_nos, wt = self.make_tree_with_merges()
1020
self.addCleanup(wt.unlock)
1021
revisions = list(self._get_view_revisions(
1022
mainline_revs, rev_nos, wt.branch, 'forward'))
1023
self.assertEqual([('1', '1', 0), ('2', '2', 0), ('3', '3', 0),
1024
('4b', '4', 0), ('4a', '3.1.1', 1)],
1026
revisions = list(self._get_view_revisions(
1027
mainline_revs, rev_nos, wt.branch, 'forward',
1028
include_merges=False))
1029
self.assertEqual([('1', '1', 0), ('2', '2', 0), ('3', '3', 0),
1033
def test_get_view_revisions_merge_reverse(self):
1034
"""Test get_view_revisions in reverse when there are merges"""
1035
mainline_revs, rev_nos, wt = self.make_tree_with_merges()
1037
self.addCleanup(wt.unlock)
1038
revisions = list(self._get_view_revisions(
1039
mainline_revs, rev_nos, wt.branch, 'reverse'))
1040
self.assertEqual([('4b', '4', 0), ('4a', '3.1.1', 1),
1041
('3', '3', 0), ('2', '2', 0), ('1', '1', 0)],
1043
revisions = list(self._get_view_revisions(
1044
mainline_revs, rev_nos, wt.branch, 'reverse',
1045
include_merges=False))
1046
self.assertEqual([('4b', '4', 0), ('3', '3', 0), ('2', '2', 0),
1050
def test_get_view_revisions_merge2(self):
1051
"""Test get_view_revisions when there are merges"""
1052
mainline_revs, rev_nos, b = self.make_branch_with_many_merges()
1054
self.addCleanup(b.unlock)
1055
revisions = list(self._get_view_revisions(
1056
mainline_revs, rev_nos, b, 'forward'))
1057
expected = [('1', '1', 0), ('2', '2', 0), ('3c', '3', 0),
1058
('3b', '2.2.1', 1), ('3a', '2.1.1', 2), ('4b', '4', 0),
1060
self.assertEqual(expected, revisions)
1061
revisions = list(self._get_view_revisions(
1062
mainline_revs, rev_nos, b, 'forward',
1063
include_merges=False))
1064
self.assertEqual([('1', '1', 0), ('2', '2', 0), ('3c', '3', 0),
1068
def test_file_id_for_range(self):
1069
mainline_revs, rev_nos, b = self.make_branch_with_many_merges()
1071
self.addCleanup(b.unlock)
1073
def rev_from_rev_id(revid, branch):
1074
revspec = revisionspec.RevisionSpec.from_string('revid:%s' % revid)
1075
return revspec.in_history(branch)
1077
def view_revs(start_rev, end_rev, file_id, direction):
1078
revs = self.applyDeprecated(
1079
symbol_versioning.deprecated_in((2, 2, 0)),
1080
log.calculate_view_revisions,
1082
start_rev, # start_revision
1083
end_rev, # end_revision
1084
direction, # direction
1085
file_id, # specific_fileid
1086
True, # generate_merge_revisions
1090
rev_3a = rev_from_rev_id('3a', b)
1091
rev_4b = rev_from_rev_id('4b', b)
1092
self.assertEqual([('3c', '3', 0), ('3b', '2.2.1', 1),
1093
('3a', '2.1.1', 2)],
1094
view_revs(rev_3a, rev_4b, 'f-id', 'reverse'))
1095
# Note: 3c still appears before 3a here because of depth-based sorting
1096
self.assertEqual([('3c', '3', 0), ('3b', '2.2.1', 1),
1097
('3a', '2.1.1', 2)],
1098
view_revs(rev_3a, rev_4b, 'f-id', 'forward'))
1101
class TestGetRevisionsTouchingFileID(tests.TestCaseWithTransport):
1103
def get_view_revisions(self, *args):
1104
return self.applyDeprecated(symbol_versioning.deprecated_in((2, 2, 0)),
1105
log.get_view_revisions, *args)
1107
def create_tree_with_single_merge(self):
1108
"""Create a branch with a moderate layout.
1110
The revision graph looks like:
1118
In this graph, A introduced files f1 and f2 and f3.
1119
B modifies f1 and f3, and C modifies f2 and f3.
1120
D merges the changes from B and C and resolves the conflict for f3.
1122
# TODO: jam 20070218 This seems like it could really be done
1123
# with make_branch_and_memory_tree() if we could just
1124
# create the content of those files.
1125
# TODO: jam 20070218 Another alternative is that we would really
1126
# like to only create this tree 1 time for all tests that
1127
# use it. Since 'log' only uses the tree in a readonly
1128
# fashion, it seems a shame to regenerate an identical
1129
# tree for each test.
1130
# TODO: vila 20100122 One way to address the shame above will be to
1131
# create a memory tree during test parametrization and give a
1132
# *copy* of this tree to each test. Copying a memory tree ought
1133
# to be cheap, at least cheaper than creating them with such
1135
tree = self.make_branch_and_tree('tree')
1137
self.addCleanup(tree.unlock)
1139
self.build_tree_contents([('tree/f1', 'A\n'),
1143
tree.add(['f1', 'f2', 'f3'], ['f1-id', 'f2-id', 'f3-id'])
1144
tree.commit('A', rev_id='A')
1146
self.build_tree_contents([('tree/f2', 'A\nC\n'),
1147
('tree/f3', 'A\nC\n'),
1149
tree.commit('C', rev_id='C')
1150
# Revert back to A to build the other history.
1151
tree.set_last_revision('A')
1152
tree.branch.set_last_revision_info(1, 'A')
1153
self.build_tree_contents([('tree/f1', 'A\nB\n'),
1155
('tree/f3', 'A\nB\n'),
1157
tree.commit('B', rev_id='B')
1158
tree.set_parent_ids(['B', 'C'])
1159
self.build_tree_contents([('tree/f1', 'A\nB\n'),
1160
('tree/f2', 'A\nC\n'),
1161
('tree/f3', 'A\nB\nC\n'),
1163
tree.commit('D', rev_id='D')
1165
# Switch to a read lock for this tree.
1166
# We still have an addCleanup(tree.unlock) pending
1171
def check_delta(self, delta, **kw):
1172
"""Check the filenames touched by a delta are as expected.
1174
Caller only have to pass in the list of files for each part, all
1175
unspecified parts are considered empty (and checked as such).
1177
for n in 'added', 'removed', 'renamed', 'modified', 'unchanged':
1178
# By default we expect an empty list
1179
expected = kw.get(n, [])
1180
# strip out only the path components
1181
got = [x[0] for x in getattr(delta, n)]
1182
self.assertEqual(expected, got)
1184
def test_tree_with_single_merge(self):
1185
"""Make sure the tree layout is correct."""
1186
tree = self.create_tree_with_single_merge()
1187
rev_A_tree = tree.branch.repository.revision_tree('A')
1188
rev_B_tree = tree.branch.repository.revision_tree('B')
1189
rev_C_tree = tree.branch.repository.revision_tree('C')
1190
rev_D_tree = tree.branch.repository.revision_tree('D')
1192
self.check_delta(rev_B_tree.changes_from(rev_A_tree),
1193
modified=['f1', 'f3'])
1195
self.check_delta(rev_C_tree.changes_from(rev_A_tree),
1196
modified=['f2', 'f3'])
1198
self.check_delta(rev_D_tree.changes_from(rev_B_tree),
1199
modified=['f2', 'f3'])
1201
self.check_delta(rev_D_tree.changes_from(rev_C_tree),
1202
modified=['f1', 'f3'])
1204
def assertAllRevisionsForFileID(self, tree, file_id, revisions):
1205
"""Ensure _filter_revisions_touching_file_id returns the right values.
1207
Get the return value from _filter_revisions_touching_file_id and make
1208
sure they are correct.
1210
# The api for _filter_revisions_touching_file_id is a little crazy.
1211
# So we do the setup here.
1212
mainline = tree.branch.revision_history()
1213
mainline.insert(0, None)
1214
revnos = dict((rev, idx+1) for idx, rev in enumerate(mainline))
1215
view_revs_iter = self.get_view_revisions(
1216
mainline, revnos, tree.branch, 'reverse', True)
1217
actual_revs = log._filter_revisions_touching_file_id(
1218
tree.branch, file_id, list(view_revs_iter))
1219
self.assertEqual(revisions, [r for r, revno, depth in actual_revs])
1221
def test_file_id_f1(self):
1222
tree = self.create_tree_with_single_merge()
1223
# f1 should be marked as modified by revisions A and B
1224
self.assertAllRevisionsForFileID(tree, 'f1-id', ['B', 'A'])
1226
def test_file_id_f2(self):
1227
tree = self.create_tree_with_single_merge()
1228
# f2 should be marked as modified by revisions A, C, and D
1229
# because D merged the changes from C.
1230
self.assertAllRevisionsForFileID(tree, 'f2-id', ['D', 'C', 'A'])
1232
def test_file_id_f3(self):
1233
tree = self.create_tree_with_single_merge()
1234
# f3 should be marked as modified by revisions A, B, C, and D
1235
self.assertAllRevisionsForFileID(tree, 'f3-id', ['D', 'C', 'B', 'A'])
1237
def test_file_id_with_ghosts(self):
1238
# This is testing bug #209948, where having a ghost would cause
1239
# _filter_revisions_touching_file_id() to fail.
1240
tree = self.create_tree_with_single_merge()
1241
# We need to add a revision, so switch back to a write-locked tree
1242
# (still a single addCleanup(tree.unlock) pending).
1245
first_parent = tree.last_revision()
1246
tree.set_parent_ids([first_parent, 'ghost-revision-id'])
1247
self.build_tree_contents([('tree/f1', 'A\nB\nXX\n')])
1248
tree.commit('commit with a ghost', rev_id='XX')
1249
self.assertAllRevisionsForFileID(tree, 'f1-id', ['XX', 'B', 'A'])
1250
self.assertAllRevisionsForFileID(tree, 'f2-id', ['D', 'C', 'A'])
1252
def test_unknown_file_id(self):
1253
tree = self.create_tree_with_single_merge()
1254
self.assertAllRevisionsForFileID(tree, 'unknown', [])
1256
def test_empty_branch_unknown_file_id(self):
1257
tree = self.make_branch_and_tree('tree')
1258
self.assertAllRevisionsForFileID(tree, 'unknown', [])
1261
1020
class TestShowChangedRevisions(tests.TestCaseWithTransport):
1462
1221
self.assertNotContainsRe(s.getvalue(), 'Added Revisions:')
1224
class TestRevisionNotInBranch(TestCaseForLogFormatter):
1226
def setup_a_tree(self):
1227
tree = self.make_branch_and_tree('tree')
1229
self.addCleanup(tree.unlock)
1231
'committer': 'Joe Foo <joe@foo.com>',
1232
'timestamp': 1132617600, # Mon 2005-11-22 00:00:00 +0000
1233
'timezone': 0, # UTC
1235
tree.commit('commit 1a', rev_id='1a', **kwargs)
1236
tree.commit('commit 2a', rev_id='2a', **kwargs)
1237
tree.commit('commit 3a', rev_id='3a', **kwargs)
1240
def setup_ab_tree(self):
1241
tree = self.setup_a_tree()
1242
tree.set_last_revision('1a')
1243
tree.branch.set_last_revision_info(1, '1a')
1245
'committer': 'Joe Foo <joe@foo.com>',
1246
'timestamp': 1132617600, # Mon 2005-11-22 00:00:00 +0000
1247
'timezone': 0, # UTC
1249
tree.commit('commit 2b', rev_id='2b', **kwargs)
1250
tree.commit('commit 3b', rev_id='3b', **kwargs)
1253
def test_one_revision(self):
1254
tree = self.setup_ab_tree()
1256
rev = revisionspec.RevisionInfo(tree.branch, None, '3a')
1257
log.show_log(tree.branch, lf, verbose=True, start_revision=rev,
1259
self.assertEqual(1, len(lf.revisions))
1260
self.assertEqual(None, lf.revisions[0].revno) # Out-of-branch
1261
self.assertEqual('3a', lf.revisions[0].rev.revision_id)
1263
def test_many_revisions(self):
1264
tree = self.setup_ab_tree()
1266
start_rev = revisionspec.RevisionInfo(tree.branch, None, '1a')
1267
end_rev = revisionspec.RevisionInfo(tree.branch, None, '3a')
1268
log.show_log(tree.branch, lf, verbose=True, start_revision=start_rev,
1269
end_revision=end_rev)
1270
self.assertEqual(3, len(lf.revisions))
1271
self.assertEqual(None, lf.revisions[0].revno) # Out-of-branch
1272
self.assertEqual('3a', lf.revisions[0].rev.revision_id)
1273
self.assertEqual(None, lf.revisions[1].revno) # Out-of-branch
1274
self.assertEqual('2a', lf.revisions[1].rev.revision_id)
1275
self.assertEqual('1', lf.revisions[2].revno) # In-branch
1277
def test_long_format(self):
1278
tree = self.setup_ab_tree()
1279
start_rev = revisionspec.RevisionInfo(tree.branch, None, '1a')
1280
end_rev = revisionspec.RevisionInfo(tree.branch, None, '3a')
1281
self.assertFormatterResult("""\
1282
------------------------------------------------------------
1284
committer: Joe Foo <joe@foo.com>
1286
timestamp: Tue 2005-11-22 00:00:00 +0000
1289
------------------------------------------------------------
1291
committer: Joe Foo <joe@foo.com>
1293
timestamp: Tue 2005-11-22 00:00:00 +0000
1296
------------------------------------------------------------
1298
committer: Joe Foo <joe@foo.com>
1300
timestamp: Tue 2005-11-22 00:00:00 +0000
1304
tree.branch, log.LongLogFormatter, show_log_kwargs={
1305
'start_revision': start_rev, 'end_revision': end_rev
1308
def test_short_format(self):
1309
tree = self.setup_ab_tree()
1310
start_rev = revisionspec.RevisionInfo(tree.branch, None, '1a')
1311
end_rev = revisionspec.RevisionInfo(tree.branch, None, '3a')
1312
self.assertFormatterResult("""\
1321
1 Joe Foo\t2005-11-22
1325
tree.branch, log.ShortLogFormatter, show_log_kwargs={
1326
'start_revision': start_rev, 'end_revision': end_rev
1329
def test_line_format(self):
1330
tree = self.setup_ab_tree()
1331
start_rev = revisionspec.RevisionInfo(tree.branch, None, '1a')
1332
end_rev = revisionspec.RevisionInfo(tree.branch, None, '3a')
1333
self.assertFormatterResult("""\
1334
Joe Foo 2005-11-22 commit 3a
1335
Joe Foo 2005-11-22 commit 2a
1336
1: Joe Foo 2005-11-22 commit 1a
1338
tree.branch, log.LineLogFormatter, show_log_kwargs={
1339
'start_revision': start_rev, 'end_revision': end_rev
1466
1343
class TestLogWithBugs(TestCaseForLogFormatter, TestLogMixin):
1468
1345
def setUp(self):
1469
TestCaseForLogFormatter.setUp(self)
1346
super(TestLogWithBugs, self).setUp()
1470
1347
log.properties_handler_registry.register(
1471
1348
'bugs_properties_handler',
1472
1349
log._bugs_properties_handler)
1542
1419
def test_bugs_handler_present(self):
1543
1420
self.properties_handler_registry.get('bugs_properties_handler')
1423
class TestLogForAuthors(TestCaseForLogFormatter):
1426
super(TestLogForAuthors, self).setUp()
1427
self.wt = self.make_standard_commit('nicky',
1428
authors=['John Doe <jdoe@example.com>',
1429
'Jane Rey <jrey@example.com>'])
1431
def assertFormatterResult(self, formatter, who, result):
1432
formatter_kwargs = dict()
1434
author_list_handler = log.author_list_registry.get(who)
1435
formatter_kwargs['author_list_handler'] = author_list_handler
1436
TestCaseForLogFormatter.assertFormatterResult(self, result,
1437
self.wt.branch, formatter, formatter_kwargs=formatter_kwargs)
1439
def test_line_default(self):
1440
self.assertFormatterResult(log.LineLogFormatter, None, """\
1441
1: John Doe 2005-11-22 add a
1444
def test_line_committer(self):
1445
self.assertFormatterResult(log.LineLogFormatter, 'committer', """\
1446
1: Lorem Ipsum 2005-11-22 add a
1449
def test_line_first(self):
1450
self.assertFormatterResult(log.LineLogFormatter, 'first', """\
1451
1: John Doe 2005-11-22 add a
1454
def test_line_all(self):
1455
self.assertFormatterResult(log.LineLogFormatter, 'all', """\
1456
1: John Doe, Jane Rey 2005-11-22 add a
1460
def test_short_default(self):
1461
self.assertFormatterResult(log.ShortLogFormatter, None, """\
1462
1 John Doe\t2005-11-22
1467
def test_short_committer(self):
1468
self.assertFormatterResult(log.ShortLogFormatter, 'committer', """\
1469
1 Lorem Ipsum\t2005-11-22
1474
def test_short_first(self):
1475
self.assertFormatterResult(log.ShortLogFormatter, 'first', """\
1476
1 John Doe\t2005-11-22
1481
def test_short_all(self):
1482
self.assertFormatterResult(log.ShortLogFormatter, 'all', """\
1483
1 John Doe, Jane Rey\t2005-11-22
1488
def test_long_default(self):
1489
self.assertFormatterResult(log.LongLogFormatter, None, """\
1490
------------------------------------------------------------
1492
author: John Doe <jdoe@example.com>, Jane Rey <jrey@example.com>
1493
committer: Lorem Ipsum <test@example.com>
1495
timestamp: Tue 2005-11-22 00:00:00 +0000
1500
def test_long_committer(self):
1501
self.assertFormatterResult(log.LongLogFormatter, 'committer', """\
1502
------------------------------------------------------------
1504
committer: Lorem Ipsum <test@example.com>
1506
timestamp: Tue 2005-11-22 00:00:00 +0000
1511
def test_long_first(self):
1512
self.assertFormatterResult(log.LongLogFormatter, 'first', """\
1513
------------------------------------------------------------
1515
author: John Doe <jdoe@example.com>
1516
committer: Lorem Ipsum <test@example.com>
1518
timestamp: Tue 2005-11-22 00:00:00 +0000
1523
def test_long_all(self):
1524
self.assertFormatterResult(log.LongLogFormatter, 'all', """\
1525
------------------------------------------------------------
1527
author: John Doe <jdoe@example.com>, Jane Rey <jrey@example.com>
1528
committer: Lorem Ipsum <test@example.com>
1530
timestamp: Tue 2005-11-22 00:00:00 +0000
1535
def test_gnu_changelog_default(self):
1536
self.assertFormatterResult(log.GnuChangelogLogFormatter, None, """\
1537
2005-11-22 John Doe <jdoe@example.com>
1543
def test_gnu_changelog_committer(self):
1544
self.assertFormatterResult(log.GnuChangelogLogFormatter, 'committer', """\
1545
2005-11-22 Lorem Ipsum <test@example.com>
1551
def test_gnu_changelog_first(self):
1552
self.assertFormatterResult(log.GnuChangelogLogFormatter, 'first', """\
1553
2005-11-22 John Doe <jdoe@example.com>
1559
def test_gnu_changelog_all(self):
1560
self.assertFormatterResult(log.GnuChangelogLogFormatter, 'all', """\
1561
2005-11-22 John Doe <jdoe@example.com>, Jane Rey <jrey@example.com>
1568
class TestLogExcludeAncestry(tests.TestCaseWithTransport):
1570
def make_branch_with_alternate_ancestries(self, relpath='.'):
1571
# See test_merge_sorted_exclude_ancestry below for the difference with
1572
# bt.per_branch.test_iter_merge_sorted_revision.
1573
# TestIterMergeSortedRevisionsBushyGraph.
1574
# make_branch_with_alternate_ancestries
1575
# and test_merge_sorted_exclude_ancestry
1576
# See the FIXME in assertLogRevnos too.
1577
builder = branchbuilder.BranchBuilder(self.get_transport(relpath))
1589
builder.start_series()
1590
builder.build_snapshot('1', None, [
1591
('add', ('', 'TREE_ROOT', 'directory', '')),])
1592
builder.build_snapshot('1.1.1', ['1'], [])
1593
builder.build_snapshot('2', ['1'], [])
1594
builder.build_snapshot('1.2.1', ['1.1.1'], [])
1595
builder.build_snapshot('1.1.2', ['1.1.1', '1.2.1'], [])
1596
builder.build_snapshot('3', ['2', '1.1.2'], [])
1597
builder.finish_series()
1598
br = builder.get_branch()
1600
self.addCleanup(br.unlock)
1603
def assertLogRevnos(self, expected_revnos, b, start, end,
1604
exclude_common_ancestry, generate_merge_revisions=True):
1605
# FIXME: the layering in log makes it hard to test intermediate levels,
1606
# I wish adding filters with their parameters was easier...
1608
iter_revs = log._calc_view_revisions(
1609
b, start, end, direction='reverse',
1610
generate_merge_revisions=generate_merge_revisions,
1611
exclude_common_ancestry=exclude_common_ancestry)
1612
self.assertEqual(expected_revnos,
1613
[revid for revid, revno, depth in iter_revs])
1615
def test_merge_sorted_exclude_ancestry(self):
1616
b = self.make_branch_with_alternate_ancestries()
1617
self.assertLogRevnos(['3', '1.1.2', '1.2.1', '1.1.1', '2', '1'],
1618
b, '1', '3', exclude_common_ancestry=False)
1619
# '2' is part of the '3' ancestry but not part of '1.1.1' ancestry so
1620
# it should be mentioned even if merge_sort order will make it appear
1622
self.assertLogRevnos(['3', '1.1.2', '1.2.1', '2'],
1623
b, '1.1.1', '3', exclude_common_ancestry=True)
1625
def test_merge_sorted_simple_revnos_exclude_ancestry(self):
1626
b = self.make_branch_with_alternate_ancestries()
1627
self.assertLogRevnos(['3', '2'],
1628
b, '1', '3', exclude_common_ancestry=True,
1629
generate_merge_revisions=False)
1630
self.assertLogRevnos(['3', '1.1.2', '1.2.1', '1.1.1', '2'],
1631
b, '1', '3', exclude_common_ancestry=True,
1632
generate_merge_revisions=True)
1635
class TestLogDefaults(TestCaseForLogFormatter):
1636
def test_default_log_level(self):
1638
Test to ensure that specifying 'levels=1' to make_log_request_dict
1639
doesn't get overwritten when using a LogFormatter that supports more
1643
wt = self._prepare_tree_with_merges()
1646
class CustomLogFormatter(log.LogFormatter):
1647
def __init__(self, *args, **kwargs):
1648
super(CustomLogFormatter, self).__init__(*args, **kwargs)
1650
def get_levels(self):
1651
# log formatter supports all levels:
1653
def log_revision(self, revision):
1654
self.revisions.append(revision)
1656
log_formatter = LogCatcher()
1657
# First request we don't specify number of levels, we should get a
1658
# sensible default (whatever the LogFormatter handles - which in this
1659
# case is 0/everything):
1660
request = log.make_log_request_dict(limit=10)
1661
log.Logger(b, request).show(log_formatter)
1662
# should have all three revisions:
1663
self.assertEquals(len(log_formatter.revisions), 3)
1666
log_formatter = LogCatcher()
1667
# now explicitly request mainline revisions only:
1668
request = log.make_log_request_dict(limit=10, levels=1)
1669
log.Logger(b, request).show(log_formatter)
1670
# should now only have 2 revisions:
1671
self.assertEquals(len(log_formatter.revisions), 2)