33
33
super(TestCaseWithoutPropsHandler, self).setUp()
34
34
# keep a reference to the "current" custom prop. handler registry
35
35
self.properties_handler_registry = log.properties_handler_registry
36
# clean up the registry in log
36
# Use a clean registry for log
37
37
log.properties_handler_registry = registry.Registry()
40
super(TestCaseWithoutPropsHandler, self)._cleanup()
41
# restore the custom properties handler registry
42
log.properties_handler_registry = self.properties_handler_registry
40
log.properties_handler_registry = self.properties_handler_registry
41
self.addCleanup(restore)
45
44
class LogCatcher(log.LogFormatter):
46
"""Pull log messages into list rather than displaying them.
48
For ease of testing we save log messages here rather than actually
49
formatting them, so that we can precisely check the result without
50
being too dependent on the exact formatting.
52
We should also test the LogFormatter.
45
"""Pull log messages into a list rather than displaying them.
47
To simplify testing we save logged revisions here rather than actually
48
formatting anything, so that we can precisely check the result without
49
being dependent on the formatting.
55
52
supports_delta = True
57
54
def __init__(self):
58
55
super(LogCatcher, self).__init__(to_file=None)
61
58
def log_revision(self, revision):
62
self.logs.append(revision)
59
self.revisions.append(revision)
65
62
class TestShowLog(tests.TestCaseWithTransport):
114
111
wt.commit('empty commit')
115
112
lf = LogCatcher()
116
113
log.show_log(wt.branch, lf, verbose=True)
117
self.assertEqual(1, len(lf.logs))
118
self.assertEqual('1', lf.logs[0].revno)
119
self.assertEqual('empty commit', lf.logs[0].rev.message)
120
self.checkDelta(lf.logs[0].delta)
115
self.assertEqual(1, len(revs))
116
self.assertEqual('1', revs[0].revno)
117
self.assertEqual('empty commit', revs[0].rev.message)
118
self.checkDelta(revs[0].delta)
122
120
def test_simple_commit(self):
123
121
wt = self.make_branch_and_tree('.')
129
127
u'<test@example.com>')
130
128
lf = LogCatcher()
131
129
log.show_log(wt.branch, lf, verbose=True)
132
self.assertEqual(2, len(lf.logs))
130
self.assertEqual(2, len(lf.revisions))
133
131
# first one is most recent
134
log_entry = lf.logs[0]
132
log_entry = lf.revisions[0]
135
133
self.assertEqual('2', log_entry.revno)
136
134
self.assertEqual('add one file', log_entry.rev.message)
137
135
self.checkDelta(log_entry.delta, added=['hello'])
144
142
lf = LogCatcher()
145
143
log.show_log(wt.branch, lf, verbose=True)
146
committed_msg = lf.logs[0].rev.message
147
self.assertNotEqual(msg, committed_msg)
148
self.assertTrue(len(committed_msg) > len(msg))
144
committed_msg = lf.revisions[0].rev.message
145
if wt.branch.repository._serializer.squashes_xml_invalid_characters:
146
self.assertNotEqual(msg, committed_msg)
147
self.assertTrue(len(committed_msg) > len(msg))
149
self.assertEqual(msg, committed_msg)
150
151
def test_commit_message_without_control_chars(self):
151
152
wt = self.make_branch_and_tree('.')
181
182
lf.supports_merge_revisions = True
182
183
log.show_log(b, lf, verbose=True)
184
self.assertEqual(3, len(lf.logs))
186
self.assertEqual(3, len(revs))
186
logentry = lf.logs[0]
187
189
self.assertEqual('2', logentry.revno)
188
190
self.assertEqual('merge child branch', logentry.rev.message)
189
191
self.checkDelta(logentry.delta, removed=['file1'], modified=['file2'])
191
logentry = lf.logs[1]
192
194
self.assertEqual('1.1.1', logentry.revno)
193
195
self.assertEqual('remove file1 and modify file2', logentry.rev.message)
194
196
self.checkDelta(logentry.delta, removed=['file1'], modified=['file2'])
196
logentry = lf.logs[2]
197
199
self.assertEqual('1', logentry.revno)
198
200
self.assertEqual('add file1 and file2', logentry.rev.message)
199
201
self.checkDelta(logentry.delta, added=['file1', 'file2'])
1199
1201
return mainline_revs, rev_nos, wt
1201
def make_tree_with_many_merges(self):
1203
def make_branch_with_many_merges(self):
1202
1204
"""Create a tree with well-known revision ids"""
1203
wt = self.make_branch_and_tree('tree1')
1204
self.build_tree_contents([('tree1/f', '1\n')])
1205
wt.add(['f'], ['f-id'])
1206
wt.commit('commit one', rev_id='1')
1207
wt.commit('commit two', rev_id='2')
1209
tree3 = wt.bzrdir.sprout('tree3').open_workingtree()
1210
self.build_tree_contents([('tree3/f', '1\n2\n3a\n')])
1211
tree3.commit('commit three a', rev_id='3a')
1213
tree2 = wt.bzrdir.sprout('tree2').open_workingtree()
1214
tree2.merge_from_branch(tree3.branch)
1215
tree2.commit('commit three b', rev_id='3b')
1217
wt.merge_from_branch(tree2.branch)
1218
wt.commit('commit three c', rev_id='3c')
1219
tree2.commit('four-a', rev_id='4a')
1221
wt.merge_from_branch(tree2.branch)
1222
wt.commit('four-b', rev_id='4b')
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()
1224
1233
mainline_revs = [None, '1', '2', '3c', '4b']
1225
1234
rev_nos = {'1':1, '2':2, '3c': 3, '4b':4}
1232
1241
'4a': '2.2.2', # second commit tree 2
1233
1242
'4b': '4', # merges 4a to main
1235
return mainline_revs, rev_nos, wt
1244
return mainline_revs, rev_nos, builder.get_branch()
1237
1246
def test_get_view_revisions_forward(self):
1238
1247
"""Test the get_view_revisions method"""
1299
1308
def test_get_view_revisions_merge2(self):
1300
1309
"""Test get_view_revisions when there are merges"""
1301
mainline_revs, rev_nos, wt = self.make_tree_with_many_merges()
1303
self.addCleanup(wt.unlock)
1310
mainline_revs, rev_nos, b = self.make_branch_with_many_merges()
1312
self.addCleanup(b.unlock)
1304
1313
revisions = list(log.get_view_revisions(
1305
mainline_revs, rev_nos, wt.branch, 'forward'))
1314
mainline_revs, rev_nos, b, 'forward'))
1306
1315
expected = [('1', '1', 0), ('2', '2', 0), ('3c', '3', 0),
1307
('3a', '2.1.1', 1), ('3b', '2.2.1', 1), ('4b', '4', 0),
1316
('3b', '2.2.1', 1), ('3a', '2.1.1', 2), ('4b', '4', 0),
1308
1317
('4a', '2.2.2', 1)]
1309
1318
self.assertEqual(expected, revisions)
1310
1319
revisions = list(log.get_view_revisions(
1311
mainline_revs, rev_nos, wt.branch, 'forward',
1320
mainline_revs, rev_nos, b, 'forward',
1312
1321
include_merges=False))
1313
1322
self.assertEqual([('1', '1', 0), ('2', '2', 0), ('3c', '3', 0),
1314
1323
('4b', '4', 0)],
1318
1327
def test_file_id_for_range(self):
1319
mainline_revs, rev_nos, wt = self.make_tree_with_many_merges()
1321
self.addCleanup(wt.unlock)
1328
mainline_revs, rev_nos, b = self.make_branch_with_many_merges()
1330
self.addCleanup(b.unlock)
1323
1332
def rev_from_rev_id(revid, branch):
1324
1333
revspec = revisionspec.RevisionSpec.from_string('revid:%s' % revid)
1338
rev_3a = rev_from_rev_id('3a', wt.branch)
1339
rev_4b = rev_from_rev_id('4b', wt.branch)
1340
self.assertEqual([('3c', '3', 0), ('3a', '2.1.1', 1)],
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)],
1341
1350
view_revs(rev_3a, rev_4b, 'f-id', 'reverse'))
1342
1351
# Note: 3c still appears before 3a here because of depth-based sorting
1343
self.assertEqual([('3c', '3', 0), ('3a', '2.1.1', 1)],
1352
self.assertEqual([('3c', '3', 0), ('3b', '2.2.1', 1), ('3a', '2.1.1', 2)],
1344
1353
view_revs(rev_3a, rev_4b, 'f-id', 'forward'))