110
108
self.addCleanup(wt.unlock)
112
self.wt_commit(wt, 'rev-1', rev_id=b'rev-1')
113
self.wt_commit(wt, 'rev-merged', rev_id=b'rev-2a')
114
wt.set_parent_ids([b'rev-1', b'rev-2a'])
115
wt.branch.set_last_revision_info(1, b'rev-1')
116
self.wt_commit(wt, 'rev-2', rev_id=b'rev-2b')
110
self.wt_commit(wt, 'rev-1', rev_id='rev-1')
111
self.wt_commit(wt, 'rev-merged', rev_id='rev-2a')
112
wt.set_parent_ids(['rev-1', 'rev-2a'])
113
wt.branch.set_last_revision_info(1, 'rev-1')
114
self.wt_commit(wt, 'rev-2', rev_id='rev-2b')
118
116
branch = wt.branch
119
branch.tags.set_tag('v0.2', b'rev-2b')
120
self.wt_commit(wt, 'rev-3', rev_id=b'rev-3')
121
branch.tags.set_tag('v1.0rc1', b'rev-3')
122
branch.tags.set_tag('v1.0', b'rev-3')
117
branch.tags.set_tag('v0.2', 'rev-2b')
118
self.wt_commit(wt, 'rev-3', rev_id='rev-3')
119
branch.tags.set_tag('v1.0rc1', 'rev-3')
120
branch.tags.set_tag('v1.0', 'rev-3')
322
319
class TestFormatSignatureValidity(tests.TestCaseWithTransport):
324
def verify_revision_signature(self, revid, gpg_strategy):
325
return (gpg.SIGNATURE_VALID,
320
class UTFLoopbackGPGStrategy(gpg.LoopbackGPGStrategy):
321
def verify(self, content, testament):
322
return (gpg.SIGNATURE_VALID,
326
323
u'UTF8 Test \xa1\xb1\xc1\xd1\xe1\xf1 <jrandom@example.com>')
325
def has_signature_for_revision_id(self, revision_id):
328
def get_signature_text(self, revision_id):
328
331
def test_format_signature_validity_utf(self):
329
332
"""Check that GPG signatures containing UTF-8 names are formatted
334
# Monkey patch to use our UTF-8 generating GPGStrategy
335
self.overrideAttr(gpg, 'GPGStrategy', self.UTFLoopbackGPGStrategy)
331
336
wt = self.make_branch_and_tree('.')
332
337
revid = wt.commit('empty commit')
333
338
repo = wt.branch.repository
334
339
# Monkey patch out checking if this rev is actually signed, since we
335
340
# can't sign it without a heavier TestCase and LoopbackGPGStrategy
336
341
# doesn't care anyways.
337
self.overrideAttr(repo, 'verify_revision_signature',
338
self.verify_revision_signature)
342
self.overrideAttr(repo, 'has_signature_for_revision_id',
343
self.has_signature_for_revision_id)
344
self.overrideAttr(repo, 'get_signature_text', self.get_signature_text)
339
345
out = log.format_signature_validity(revid, wt.branch)
340
346
self.assertEqual(
341
u'valid signature from UTF8 Test \xa1\xb1\xc1\xd1\xe1\xf1 <jrandom@example.com>',
347
u'valid signature from UTF8 Test \xa1\xb1\xc1\xd1\xe1\xf1 <jrandom@example.com>',
345
351
class TestShortLogFormatter(TestCaseForLogFormatter):
421
wt.branch, log.ShortLogFormatter)
427
wt.branch, log.ShortLogFormatter)
423
429
def test_short_log_single_merge_revision(self):
424
430
wt = self._prepare_tree_with_merges()
425
431
revspec = revisionspec.RevisionSpec.from_string('1.1.1')
426
432
rev = revspec.in_history(wt.branch)
427
self.assertFormatterResult(b"""\
433
self.assertFormatterResult("""\
428
434
1.1.1 Joe Foo\t2005-11-22
432
wt.branch, log.ShortLogFormatter,
433
show_log_kwargs=dict(start_revision=rev, end_revision=rev))
438
wt.branch, log.ShortLogFormatter,
439
show_log_kwargs=dict(start_revision=rev, end_revision=rev))
435
441
def test_show_ids(self):
436
442
wt = self.make_branch_and_tree('parent')
437
443
self.build_tree(['parent/f1', 'parent/f2'])
438
444
wt.add(['f1', 'f2'])
439
self.wt_commit(wt, 'first post', rev_id=b'a')
445
self.wt_commit(wt, 'first post', rev_id='a')
440
446
child_wt = wt.controldir.sprout('child').open_workingtree()
441
self.wt_commit(child_wt, 'branch 1 changes', rev_id=b'b')
447
self.wt_commit(child_wt, 'branch 1 changes', rev_id='b')
442
448
wt.merge_from_branch(child_wt.branch)
443
self.wt_commit(wt, 'merge branch 1', rev_id=b'c')
444
self.assertFormatterResult(b"""\
449
self.wt_commit(wt, 'merge branch 1', rev_id='c')
450
self.assertFormatterResult("""\
445
451
2 Joe Foo\t2005-11-22 [merge]
694
wt.branch, log.LongLogFormatter)
698
wt.branch, log.LongLogFormatter)
696
700
def test_properties_in_short_log(self):
697
701
"""Log includes the custom properties returned by the registered
700
704
wt = self.make_standard_commit('test_properties_in_short_log')
702
705
def trivial_custom_prop_handler(revision):
703
return {'test_prop': 'test_value'}
706
return {'test_prop':'test_value'}
705
708
log.properties_handler_registry.register(
706
709
'trivial_custom_prop_handler',
707
710
trivial_custom_prop_handler)
708
self.assertFormatterResult(b"""\
711
self.assertFormatterResult("""\
709
712
1 John Doe\t2005-11-22
710
713
test_prop: test_value
714
wt.branch, log.ShortLogFormatter)
717
wt.branch, log.ShortLogFormatter)
716
719
def test_error_in_properties_handler(self):
717
720
"""Log includes the custom properties returned by the registered
720
723
wt = self.make_standard_commit('error_in_properties_handler',
721
revprops={u'first_prop': 'first_value'})
724
revprops={'first_prop':'first_value'})
722
725
sio = self.make_utf8_encoded_stringio()
723
726
formatter = log.LongLogFormatter(to_file=sio)
725
727
def trivial_custom_prop_handler(revision):
726
728
raise Exception("a test error")
728
730
log.properties_handler_registry.register(
729
731
'trivial_custom_prop_handler',
730
732
trivial_custom_prop_handler)
731
log.show_log(wt.branch, formatter)
732
self.assertContainsRe(
733
sio.getvalue(), b'brz: ERROR: Exception: a test error')
733
self.assertRaises(Exception, log.show_log, wt.branch, formatter,)
735
735
def test_properties_handler_bad_argument(self):
736
736
wt = self.make_standard_commit('bad_argument',
737
revprops={u'a_prop': 'test_value'})
737
revprops={'a_prop':'test_value'})
738
738
sio = self.make_utf8_encoded_stringio()
739
739
formatter = log.LongLogFormatter(to_file=sio)
741
740
def bad_argument_prop_handler(revision):
742
return {'custom_prop_name': revision.properties['a_prop']}
741
return {'custom_prop_name':revision.properties['a_prop']}
744
743
log.properties_handler_registry.register(
745
744
'bad_argument_prop_handler',
942
940
wt = self.make_standard_commit('test-line-log',
943
committer='Line-Log-Formatter Tester <test@line.log>',
945
self.assertFormatterResult(b"""\
941
committer='Line-Log-Formatter Tester <test@line.log>',
943
self.assertFormatterResult("""\
946
944
1: Line-Log-Formatte... 2005-11-22 add a
948
wt.branch, log.LineLogFormatter)
946
wt.branch, log.LineLogFormatter)
950
948
def test_trailing_newlines(self):
951
949
wt = self.make_branch_and_tree('.')
952
950
b = self.make_commits_with_trailing_newlines(wt)
953
self.assertFormatterResult(b"""\
951
self.assertFormatterResult("""\
954
952
3: Joe Foo 2005-11-22 single line with trailing newline
955
953
2: Joe Foo 2005-11-22 multiline
956
954
1: Joe Foo 2005-11-22 simple log message
958
b, log.LineLogFormatter)
956
b, log.LineLogFormatter)
960
958
def test_line_log_single_merge_revision(self):
961
959
wt = self._prepare_tree_with_merges()
962
960
revspec = revisionspec.RevisionSpec.from_string('1.1.1')
963
961
rev = revspec.in_history(wt.branch)
964
self.assertFormatterResult(b"""\
962
self.assertFormatterResult("""\
965
963
1.1.1: Joe Foo 2005-11-22 rev-merged
967
wt.branch, log.LineLogFormatter,
968
show_log_kwargs=dict(start_revision=rev, end_revision=rev))
965
wt.branch, log.LineLogFormatter,
966
show_log_kwargs=dict(start_revision=rev, end_revision=rev))
970
968
def test_line_log_with_tags(self):
971
969
wt = self._prepare_tree_with_merges(with_tags=True)
972
self.assertFormatterResult(b"""\
970
self.assertFormatterResult("""\
973
971
3: Joe Foo 2005-11-22 {v1.0, v1.0rc1} rev-3
974
972
2: Joe Foo 2005-11-22 [merge] {v0.2} rev-2
975
973
1: Joe Foo 2005-11-22 rev-1
977
wt.branch, log.LineLogFormatter)
975
wt.branch, log.LineLogFormatter)
980
978
class TestLineLogFormatterWithMergeRevisions(TestCaseForLogFormatter):
987
985
wt = self.make_standard_commit('test-line-log',
988
committer='Line-Log-Formatter Tester <test@line.log>',
990
self.assertFormatterResult(b"""\
986
committer='Line-Log-Formatter Tester <test@line.log>',
988
self.assertFormatterResult("""\
991
989
1: Line-Log-Formatte... 2005-11-22 add a
993
wt.branch, log.LineLogFormatter)
991
wt.branch, log.LineLogFormatter)
995
993
def test_line_merge_revs_log_single_merge_revision(self):
996
994
wt = self._prepare_tree_with_merges()
997
995
revspec = revisionspec.RevisionSpec.from_string('1.1.1')
998
996
rev = revspec.in_history(wt.branch)
999
self.assertFormatterResult(b"""\
997
self.assertFormatterResult("""\
1000
998
1.1.1: Joe Foo 2005-11-22 rev-merged
1002
wt.branch, log.LineLogFormatter,
1003
formatter_kwargs=dict(levels=0),
1004
show_log_kwargs=dict(start_revision=rev, end_revision=rev))
1000
wt.branch, log.LineLogFormatter,
1001
formatter_kwargs=dict(levels=0),
1002
show_log_kwargs=dict(start_revision=rev, end_revision=rev))
1006
1004
def test_line_merge_revs_log_with_merges(self):
1007
1005
wt = self._prepare_tree_with_merges()
1008
self.assertFormatterResult(b"""\
1006
self.assertFormatterResult("""\
1009
1007
2: Joe Foo 2005-11-22 [merge] rev-2
1010
1008
1.1.1: Joe Foo 2005-11-22 rev-merged
1011
1009
1: Joe Foo 2005-11-22 rev-1
1013
wt.branch, log.LineLogFormatter,
1014
formatter_kwargs=dict(levels=0))
1011
wt.branch, log.LineLogFormatter,
1012
formatter_kwargs=dict(levels=0))
1017
1015
class TestGnuChangelogFormatter(TestCaseForLogFormatter):
1019
1017
def test_gnu_changelog(self):
1020
1018
wt = self.make_standard_commit('nicky', authors=[])
1021
self.assertFormatterResult(b'''\
1019
self.assertFormatterResult('''\
1022
1020
2005-11-22 Lorem Ipsum <test@example.com>
1027
wt.branch, log.GnuChangelogLogFormatter)
1025
wt.branch, log.GnuChangelogLogFormatter)
1029
1027
def test_with_authors(self):
1030
1028
wt = self.make_standard_commit('nicky',
1031
authors=['Fooa Fooz <foo@example.com>',
1032
'Bari Baro <bar@example.com>'])
1033
self.assertFormatterResult(b'''\
1029
authors=['Fooa Fooz <foo@example.com>',
1030
'Bari Baro <bar@example.com>'])
1031
self.assertFormatterResult('''\
1034
1032
2005-11-22 Fooa Fooz <foo@example.com>
1039
wt.branch, log.GnuChangelogLogFormatter)
1037
wt.branch, log.GnuChangelogLogFormatter)
1041
1039
def test_verbose(self):
1042
1040
wt = self.make_standard_commit('nicky')
1043
self.assertFormatterResult(b'''\
1041
self.assertFormatterResult('''\
1044
1042
2005-11-22 John Doe <jdoe@example.com>
1123
1121
Tests use (revno, depth) whil the API expects (revid, revno, depth).
1124
1122
Since the revid is arbitrary, we just duplicate revno
1126
return [(r, r, d) for r, d in l]
1124
return [ (r, r, d) for r, d in l]
1127
1125
forward = complete_revisions(forward)
1128
backward = complete_revisions(backward)
1126
backward= complete_revisions(backward)
1129
1127
self.assertEqual(forward, log.reverse_by_depth(backward))
1131
1130
def test_mainline_revisions(self):
1132
self.assertReversed([('1', 0), ('2', 0)],
1131
self.assertReversed([( '1', 0), ('2', 0)],
1133
1132
[('2', 0), ('1', 0)])
1135
1134
def test_merged_revisions(self):
1136
self.assertReversed([('1', 0), ('2', 0), ('2.2', 1), ('2.1', 1), ],
1137
[('2', 0), ('2.1', 1), ('2.2', 1), ('1', 0), ])
1135
self.assertReversed([('1', 0), ('2', 0), ('2.2', 1), ('2.1', 1),],
1136
[('2', 0), ('2.1', 1), ('2.2', 1), ('1', 0),])
1139
1137
def test_shifted_merged_revisions(self):
1140
1138
"""Test irregular layout.
1142
1140
Requesting revisions touching a file can produce "holes" in the depths.
1144
self.assertReversed([('1', 0), ('2', 0), ('1.1', 2), ('1.2', 2), ],
1145
[('2', 0), ('1.2', 2), ('1.1', 2), ('1', 0), ])
1142
self.assertReversed([('1', 0), ('2', 0), ('1.1', 2), ('1.2', 2),],
1143
[('2', 0), ('1.2', 2), ('1.1', 2), ('1', 0),])
1147
1145
def test_merged_without_child_revisions(self):
1148
1146
"""Test irregular layout.
1152
1150
# When a revision of higher depth doesn't follow one of lower depth, we
1153
1151
# assume a lower depth one is virtually there
1154
1152
self.assertReversed([('1', 2), ('2', 2), ('3', 3), ('4', 4)],
1155
[('4', 4), ('3', 3), ('2', 2), ('1', 2), ])
1153
[('4', 4), ('3', 3), ('2', 2), ('1', 2),])
1156
1154
# So we get the same order after reversing below even if the original
1157
1155
# revisions are not in the same order.
1158
1156
self.assertReversed([('1', 2), ('2', 2), ('3', 3), ('4', 4)],
1159
[('3', 3), ('4', 4), ('2', 2), ('1', 2), ])
1157
[('3', 3), ('4', 4), ('2', 2), ('1', 2),])
1162
1160
class TestHistoryChange(tests.TestCaseWithTransport):
1165
1163
tree = self.make_branch_and_tree('tree')
1166
1164
tree.lock_write()
1167
1165
self.addCleanup(tree.unlock)
1168
tree.commit('1a', rev_id=b'1a')
1169
tree.commit('2a', rev_id=b'2a')
1170
tree.commit('3a', rev_id=b'3a')
1166
tree.commit('1a', rev_id='1a')
1167
tree.commit('2a', rev_id='2a')
1168
tree.commit('3a', rev_id='3a')
1173
1171
def setup_ab_tree(self):
1174
1172
tree = self.setup_a_tree()
1175
tree.set_last_revision(b'1a')
1176
tree.branch.set_last_revision_info(1, b'1a')
1177
tree.commit('2b', rev_id=b'2b')
1178
tree.commit('3b', rev_id=b'3b')
1173
tree.set_last_revision('1a')
1174
tree.branch.set_last_revision_info(1, '1a')
1175
tree.commit('2b', rev_id='2b')
1176
tree.commit('3b', rev_id='3b')
1181
1179
def setup_ac_tree(self):
1182
1180
tree = self.setup_a_tree()
1183
1181
tree.set_last_revision(revision.NULL_REVISION)
1184
1182
tree.branch.set_last_revision_info(0, revision.NULL_REVISION)
1185
tree.commit('1c', rev_id=b'1c')
1186
tree.commit('2c', rev_id=b'2c')
1187
tree.commit('3c', rev_id=b'3c')
1183
tree.commit('1c', rev_id='1c')
1184
tree.commit('2c', rev_id='2c')
1185
tree.commit('3c', rev_id='3c')
1190
1188
def test_all_new(self):
1191
1189
tree = self.setup_ab_tree()
1192
old, new = log.get_history_change(b'1a', b'3a', tree.branch.repository)
1190
old, new = log.get_history_change('1a', '3a', tree.branch.repository)
1193
1191
self.assertEqual([], old)
1194
self.assertEqual([b'2a', b'3a'], new)
1192
self.assertEqual(['2a', '3a'], new)
1196
1194
def test_all_old(self):
1197
1195
tree = self.setup_ab_tree()
1198
old, new = log.get_history_change(b'3a', b'1a', tree.branch.repository)
1196
old, new = log.get_history_change('3a', '1a', tree.branch.repository)
1199
1197
self.assertEqual([], new)
1200
self.assertEqual([b'2a', b'3a'], old)
1198
self.assertEqual(['2a', '3a'], old)
1202
1200
def test_null_old(self):
1203
1201
tree = self.setup_ab_tree()
1204
1202
old, new = log.get_history_change(revision.NULL_REVISION,
1205
b'3a', tree.branch.repository)
1203
'3a', tree.branch.repository)
1206
1204
self.assertEqual([], old)
1207
self.assertEqual([b'1a', b'2a', b'3a'], new)
1205
self.assertEqual(['1a', '2a', '3a'], new)
1209
1207
def test_null_new(self):
1210
1208
tree = self.setup_ab_tree()
1211
old, new = log.get_history_change(b'3a', revision.NULL_REVISION,
1209
old, new = log.get_history_change('3a', revision.NULL_REVISION,
1212
1210
tree.branch.repository)
1213
1211
self.assertEqual([], new)
1214
self.assertEqual([b'1a', b'2a', b'3a'], old)
1212
self.assertEqual(['1a', '2a', '3a'], old)
1216
1214
def test_diverged(self):
1217
1215
tree = self.setup_ab_tree()
1218
old, new = log.get_history_change(b'3a', b'3b', tree.branch.repository)
1219
self.assertEqual(old, [b'2a', b'3a'])
1220
self.assertEqual(new, [b'2b', b'3b'])
1216
old, new = log.get_history_change('3a', '3b', tree.branch.repository)
1217
self.assertEqual(old, ['2a', '3a'])
1218
self.assertEqual(new, ['2b', '3b'])
1222
1220
def test_unrelated(self):
1223
1221
tree = self.setup_ac_tree()
1224
old, new = log.get_history_change(b'3a', b'3c', tree.branch.repository)
1225
self.assertEqual(old, [b'1a', b'2a', b'3a'])
1226
self.assertEqual(new, [b'1c', b'2c', b'3c'])
1222
old, new = log.get_history_change('3a', '3c', tree.branch.repository)
1223
self.assertEqual(old, ['1a', '2a', '3a'])
1224
self.assertEqual(new, ['1c', '2c', '3c'])
1228
1226
def test_show_branch_change(self):
1229
1227
tree = self.setup_ab_tree()
1231
log.show_branch_change(tree.branch, s, 3, b'3a')
1229
log.show_branch_change(tree.branch, s, 3, '3a')
1232
1230
self.assertContainsRe(s.getvalue(),
1233
'[*]{60}\nRemoved Revisions:\n(.|\n)*2a(.|\n)*3a(.|\n)*'
1234
'[*]{60}\n\nAdded Revisions:\n(.|\n)*2b(.|\n)*3b')
1231
'[*]{60}\nRemoved Revisions:\n(.|\n)*2a(.|\n)*3a(.|\n)*'
1232
'[*]{60}\n\nAdded Revisions:\n(.|\n)*2b(.|\n)*3b')
1236
1234
def test_show_branch_change_no_change(self):
1237
1235
tree = self.setup_ab_tree()
1239
log.show_branch_change(tree.branch, s, 3, b'3b')
1237
log.show_branch_change(tree.branch, s, 3, '3b')
1240
1238
self.assertEqual(s.getvalue(),
1241
'Nothing seems to have changed\n')
1239
'Nothing seems to have changed\n')
1243
1241
def test_show_branch_change_no_old(self):
1244
1242
tree = self.setup_ab_tree()
1246
log.show_branch_change(tree.branch, s, 2, b'2b')
1244
log.show_branch_change(tree.branch, s, 2, '2b')
1247
1245
self.assertContainsRe(s.getvalue(), 'Added Revisions:')
1248
1246
self.assertNotContainsRe(s.getvalue(), 'Removed Revisions:')
1250
1248
def test_show_branch_change_no_new(self):
1251
1249
tree = self.setup_ab_tree()
1252
tree.branch.set_last_revision_info(2, b'2b')
1254
log.show_branch_change(tree.branch, s, 3, b'3b')
1250
tree.branch.set_last_revision_info(2, '2b')
1252
log.show_branch_change(tree.branch, s, 3, '3b')
1255
1253
self.assertContainsRe(s.getvalue(), 'Removed Revisions:')
1256
1254
self.assertNotContainsRe(s.getvalue(), 'Added Revisions:')
1264
1262
self.addCleanup(tree.unlock)
1266
1264
'committer': 'Joe Foo <joe@foo.com>',
1267
'timestamp': 1132617600, # Mon 2005-11-22 00:00:00 +0000
1268
'timezone': 0, # UTC
1265
'timestamp': 1132617600, # Mon 2005-11-22 00:00:00 +0000
1266
'timezone': 0, # UTC
1270
tree.commit('commit 1a', rev_id=b'1a', **kwargs)
1271
tree.commit('commit 2a', rev_id=b'2a', **kwargs)
1272
tree.commit('commit 3a', rev_id=b'3a', **kwargs)
1268
tree.commit('commit 1a', rev_id='1a', **kwargs)
1269
tree.commit('commit 2a', rev_id='2a', **kwargs)
1270
tree.commit('commit 3a', rev_id='3a', **kwargs)
1275
1273
def setup_ab_tree(self):
1276
1274
tree = self.setup_a_tree()
1277
tree.set_last_revision(b'1a')
1278
tree.branch.set_last_revision_info(1, b'1a')
1275
tree.set_last_revision('1a')
1276
tree.branch.set_last_revision_info(1, '1a')
1280
1278
'committer': 'Joe Foo <joe@foo.com>',
1281
'timestamp': 1132617600, # Mon 2005-11-22 00:00:00 +0000
1282
'timezone': 0, # UTC
1279
'timestamp': 1132617600, # Mon 2005-11-22 00:00:00 +0000
1280
'timezone': 0, # UTC
1284
tree.commit('commit 2b', rev_id=b'2b', **kwargs)
1285
tree.commit('commit 3b', rev_id=b'3b', **kwargs)
1282
tree.commit('commit 2b', rev_id='2b', **kwargs)
1283
tree.commit('commit 3b', rev_id='3b', **kwargs)
1288
1286
def test_one_revision(self):
1289
1287
tree = self.setup_ab_tree()
1290
1288
lf = LogCatcher()
1291
rev = revisionspec.RevisionInfo(tree.branch, None, b'3a')
1289
rev = revisionspec.RevisionInfo(tree.branch, None, '3a')
1292
1290
log.show_log(tree.branch, lf, verbose=True, start_revision=rev,
1293
1291
end_revision=rev)
1294
1292
self.assertEqual(1, len(lf.revisions))
1295
1293
self.assertEqual(None, lf.revisions[0].revno) # Out-of-branch
1296
self.assertEqual(b'3a', lf.revisions[0].rev.revision_id)
1294
self.assertEqual('3a', lf.revisions[0].rev.revision_id)
1298
1296
def test_many_revisions(self):
1299
1297
tree = self.setup_ab_tree()
1300
1298
lf = LogCatcher()
1301
start_rev = revisionspec.RevisionInfo(tree.branch, None, b'1a')
1302
end_rev = revisionspec.RevisionInfo(tree.branch, None, b'3a')
1299
start_rev = revisionspec.RevisionInfo(tree.branch, None, '1a')
1300
end_rev = revisionspec.RevisionInfo(tree.branch, None, '3a')
1303
1301
log.show_log(tree.branch, lf, verbose=True, start_revision=start_rev,
1304
1302
end_revision=end_rev)
1305
1303
self.assertEqual(3, len(lf.revisions))
1306
1304
self.assertEqual(None, lf.revisions[0].revno) # Out-of-branch
1307
self.assertEqual(b'3a', lf.revisions[0].rev.revision_id)
1305
self.assertEqual('3a', lf.revisions[0].rev.revision_id)
1308
1306
self.assertEqual(None, lf.revisions[1].revno) # Out-of-branch
1309
self.assertEqual(b'2a', lf.revisions[1].rev.revision_id)
1307
self.assertEqual('2a', lf.revisions[1].rev.revision_id)
1310
1308
self.assertEqual('1', lf.revisions[2].revno) # In-branch
1312
1310
def test_long_format(self):
1313
1311
tree = self.setup_ab_tree()
1314
start_rev = revisionspec.RevisionInfo(tree.branch, None, b'1a')
1315
end_rev = revisionspec.RevisionInfo(tree.branch, None, b'3a')
1316
self.assertFormatterResult(b"""\
1312
start_rev = revisionspec.RevisionInfo(tree.branch, None, '1a')
1313
end_rev = revisionspec.RevisionInfo(tree.branch, None, '3a')
1314
self.assertFormatterResult("""\
1317
1315
------------------------------------------------------------
1318
1316
revision-id: 3a
1319
1317
committer: Joe Foo <joe@foo.com>
1360
tree.branch, log.ShortLogFormatter, show_log_kwargs={
1361
'start_revision': start_rev, 'end_revision': end_rev
1358
tree.branch, log.ShortLogFormatter, show_log_kwargs={
1359
'start_revision': start_rev, 'end_revision': end_rev
1364
1362
def test_line_format(self):
1365
1363
tree = self.setup_ab_tree()
1366
start_rev = revisionspec.RevisionInfo(tree.branch, None, b'1a')
1367
end_rev = revisionspec.RevisionInfo(tree.branch, None, b'3a')
1368
self.assertFormatterResult(b"""\
1364
start_rev = revisionspec.RevisionInfo(tree.branch, None, '1a')
1365
end_rev = revisionspec.RevisionInfo(tree.branch, None, '3a')
1366
self.assertFormatterResult("""\
1369
1367
Joe Foo 2005-11-22 commit 3a
1370
1368
Joe Foo 2005-11-22 commit 2a
1371
1369
1: Joe Foo 2005-11-22 commit 1a
1373
tree.branch, log.LineLogFormatter, show_log_kwargs={
1374
'start_revision': start_rev, 'end_revision': end_rev
1371
tree.branch, log.LineLogFormatter, show_log_kwargs={
1372
'start_revision': start_rev, 'end_revision': end_rev
1378
1376
class TestLogWithBugs(TestCaseForLogFormatter, TestLogMixin):
1388
1386
tree = self.make_branch_and_tree(u'.')
1389
1387
self.build_tree(['a', 'b'])
1391
self.wt_commit(tree, 'simple log message', rev_id=b'a1',
1392
revprops={u'bugs': 'test://bug/id fixed'})
1389
self.wt_commit(tree, 'simple log message', rev_id='a1',
1390
revprops={'bugs': 'test://bug/id fixed'})
1394
self.wt_commit(tree, 'multiline\nlog\nmessage\n', rev_id=b'a2',
1392
self.wt_commit(tree, 'multiline\nlog\nmessage\n', rev_id='a2',
1395
1393
authors=['Joe Bar <joe@bar.com>'],
1396
revprops={u'bugs': 'test://bug/id fixed\n'
1394
revprops={'bugs': 'test://bug/id fixed\n'
1397
1395
'test://bug/2 fixed'})
1400
def test_bug_broken(self):
1401
tree = self.make_branch_and_tree(u'.')
1402
self.build_tree(['a', 'b'])
1404
self.wt_commit(tree, 'simple log message', rev_id=b'a1',
1405
revprops={u'bugs': 'test://bua g/id fixed'})
1407
logfile = self.make_utf8_encoded_stringio()
1408
formatter = log.LongLogFormatter(to_file=logfile)
1409
log.show_log(tree.branch, formatter)
1411
self.assertContainsRe(
1413
b'brz: ERROR: breezy.bugtracker.InvalidLineInBugsProperty: '
1414
b'Invalid line in bugs property: \'test://bua g/id fixed\'')
1416
text = logfile.getvalue()
1417
self.assertEqualDiff(
1418
text[text.index(b'-' * 60):],
1420
------------------------------------------------------------
1422
committer: Joe Foo <joe@foo.com>
1424
timestamp: Tue 2005-11-22 00:00:00 +0000
1429
1399
def test_long_bugs(self):
1430
1400
tree = self.make_commits_with_bugs()
1431
self.assertFormatterResult(b"""\
1401
self.assertFormatterResult("""\
1432
1402
------------------------------------------------------------
1434
1404
fixes bugs: test://bug/id test://bug/2
1507
1467
author_list_handler = log.author_list_registry.get(who)
1508
1468
formatter_kwargs['author_list_handler'] = author_list_handler
1509
1469
TestCaseForLogFormatter.assertFormatterResult(self, result,
1510
self.wt.branch, formatter, formatter_kwargs=formatter_kwargs)
1470
self.wt.branch, formatter, formatter_kwargs=formatter_kwargs)
1512
1472
def test_line_default(self):
1513
self.assertFormatterResult(log.LineLogFormatter, None, b"""\
1473
self.assertFormatterResult(log.LineLogFormatter, None, """\
1514
1474
1: John Doe 2005-11-22 add a
1517
1477
def test_line_committer(self):
1518
self.assertFormatterResult(log.LineLogFormatter, 'committer', b"""\
1478
self.assertFormatterResult(log.LineLogFormatter, 'committer', """\
1519
1479
1: Lorem Ipsum 2005-11-22 add a
1522
1482
def test_line_first(self):
1523
self.assertFormatterResult(log.LineLogFormatter, 'first', b"""\
1483
self.assertFormatterResult(log.LineLogFormatter, 'first', """\
1524
1484
1: John Doe 2005-11-22 add a
1527
1487
def test_line_all(self):
1528
self.assertFormatterResult(log.LineLogFormatter, 'all', b"""\
1488
self.assertFormatterResult(log.LineLogFormatter, 'all', """\
1529
1489
1: John Doe, Jane Rey 2005-11-22 add a
1532
1493
def test_short_default(self):
1533
self.assertFormatterResult(log.ShortLogFormatter, None, b"""\
1494
self.assertFormatterResult(log.ShortLogFormatter, None, """\
1534
1495
1 John Doe\t2005-11-22
1539
1500
def test_short_committer(self):
1540
self.assertFormatterResult(log.ShortLogFormatter, 'committer', b"""\
1501
self.assertFormatterResult(log.ShortLogFormatter, 'committer', """\
1541
1502
1 Lorem Ipsum\t2005-11-22
1546
1507
def test_short_first(self):
1547
self.assertFormatterResult(log.ShortLogFormatter, 'first', b"""\
1508
self.assertFormatterResult(log.ShortLogFormatter, 'first', """\
1548
1509
1 John Doe\t2005-11-22
1553
1514
def test_short_all(self):
1554
self.assertFormatterResult(log.ShortLogFormatter, 'all', b"""\
1515
self.assertFormatterResult(log.ShortLogFormatter, 'all', """\
1555
1516
1 John Doe, Jane Rey\t2005-11-22
1560
1521
def test_long_default(self):
1561
self.assertFormatterResult(log.LongLogFormatter, None, b"""\
1522
self.assertFormatterResult(log.LongLogFormatter, None, """\
1562
1523
------------------------------------------------------------
1564
1525
author: John Doe <jdoe@example.com>, Jane Rey <jrey@example.com>
1661
1622
builder.start_series()
1662
1623
builder.build_snapshot(None, [
1663
('add', ('', b'TREE_ROOT', 'directory', '')), ],
1665
builder.build_snapshot([b'1'], [], revision_id=b'1.1.1')
1666
builder.build_snapshot([b'1'], [], revision_id=b'2')
1667
builder.build_snapshot([b'1.1.1'], [], revision_id=b'1.2.1')
1668
builder.build_snapshot([b'1.1.1', b'1.2.1'], [], revision_id=b'1.1.2')
1669
builder.build_snapshot([b'2', b'1.1.2'], [], revision_id=b'3')
1624
('add', ('', 'TREE_ROOT', 'directory', '')),],
1626
builder.build_snapshot(['1'], [], revision_id='1.1.1')
1627
builder.build_snapshot(['1'], [], revision_id='2')
1628
builder.build_snapshot(['1.1.1'], [], revision_id='1.2.1')
1629
builder.build_snapshot(['1.1.1', '1.2.1'], [], revision_id='1.1.2')
1630
builder.build_snapshot(['2', '1.1.2'], [], revision_id='3')
1670
1631
builder.finish_series()
1671
1632
br = builder.get_branch()
1688
1649
def test_merge_sorted_exclude_ancestry(self):
1689
1650
b = self.make_branch_with_alternate_ancestries()
1690
self.assertLogRevnos([b'3', b'1.1.2', b'1.2.1', b'1.1.1', b'2', b'1'],
1691
b, b'1', b'3', exclude_common_ancestry=False)
1651
self.assertLogRevnos(['3', '1.1.2', '1.2.1', '1.1.1', '2', '1'],
1652
b, '1', '3', exclude_common_ancestry=False)
1692
1653
# '2' is part of the '3' ancestry but not part of '1.1.1' ancestry so
1693
1654
# it should be mentioned even if merge_sort order will make it appear
1695
self.assertLogRevnos([b'3', b'1.1.2', b'1.2.1', b'2'],
1696
b, b'1.1.1', b'3', exclude_common_ancestry=True)
1656
self.assertLogRevnos(['3', '1.1.2', '1.2.1', '2'],
1657
b, '1.1.1', '3', exclude_common_ancestry=True)
1698
1659
def test_merge_sorted_simple_revnos_exclude_ancestry(self):
1699
1660
b = self.make_branch_with_alternate_ancestries()
1700
self.assertLogRevnos([b'3', b'2'],
1701
b, b'1', b'3', exclude_common_ancestry=True,
1661
self.assertLogRevnos(['3', '2'],
1662
b, '1', '3', exclude_common_ancestry=True,
1702
1663
generate_merge_revisions=False)
1703
self.assertLogRevnos([b'3', b'1.1.2', b'1.2.1', b'1.1.1', b'2'],
1704
b, b'1', b'3', exclude_common_ancestry=True,
1664
self.assertLogRevnos(['3', '1.1.2', '1.2.1', '1.1.1', '2'],
1665
b, '1', '3', exclude_common_ancestry=True,
1705
1666
generate_merge_revisions=True)