162
154
# commit a log message with control characters
163
155
msg = "All 8-bit chars: " + ''.join([unichr(x) for x in range(256)])
164
self.log("original commit message: %r", msg)
166
157
lf = LogCatcher()
167
158
show_log(b, lf, verbose=True)
168
159
committed_msg = lf.logs[0].rev.message
169
160
self.log("escaped commit message: %r", committed_msg)
170
161
self.assert_(msg != committed_msg)
171
162
self.assert_(len(committed_msg) > len(msg))
173
# Check that log message with only XML-valid characters isn't
174
# escaped. As ElementTree apparently does some kind of
175
# newline conversion, neither LF (\x0A) nor CR (\x0D) are
176
# included in the test commit message, even though they are
177
# valid XML 1.0 characters.
178
msg = "\x09" + ''.join([unichr(x) for x in range(0x20, 256)])
179
self.log("original commit message: %r", msg)
182
show_log(b, lf, verbose=True)
183
committed_msg = lf.logs[0].rev.message
184
self.log("escaped commit message: %r", committed_msg)
185
self.assert_(msg == committed_msg)
187
def test_trailing_newlines(self):
188
wt = self.make_branch_and_tree('.')
191
open('a', 'wb').write('hello moto\n')
193
wt.commit('simple log message', rev_id='a1'
194
, timestamp=1132586655.459960938, timezone=-6*3600
195
, committer='Joe Foo <joe@foo.com>')
196
open('b', 'wb').write('goodbye\n')
198
wt.commit('multiline\nlog\nmessage\n', rev_id='a2'
199
, timestamp=1132586842.411175966, timezone=-6*3600
200
, committer='Joe Foo <joe@foo.com>')
202
open('c', 'wb').write('just another manic monday\n')
204
wt.commit('single line with trailing newline\n', rev_id='a3'
205
, timestamp=1132587176.835228920, timezone=-6*3600
206
, committer = 'Joe Foo <joe@foo.com>')
209
lf = ShortLogFormatter(to_file=sio)
211
self.assertEquals(sio.getvalue(), """\
212
3 Joe Foo\t2005-11-21
213
single line with trailing newline
215
2 Joe Foo\t2005-11-21
220
1 Joe Foo\t2005-11-21
226
lf = LongLogFormatter(to_file=sio)
228
self.assertEquals(sio.getvalue(), """\
229
------------------------------------------------------------
231
committer: Joe Foo <joe@foo.com>
233
timestamp: Mon 2005-11-21 09:32:56 -0600
235
single line with trailing newline
236
------------------------------------------------------------
238
committer: Joe Foo <joe@foo.com>
240
timestamp: Mon 2005-11-21 09:27:22 -0600
245
------------------------------------------------------------
247
committer: Joe Foo <joe@foo.com>
249
timestamp: Mon 2005-11-21 09:24:15 -0600
254
def test_verbose_log(self):
255
"""Verbose log includes changed files
259
wt = self.make_branch_and_tree('.')
261
self.build_tree(['a'])
263
# XXX: why does a longer nick show up?
264
b.nick = 'test_verbose_log'
265
wt.commit(message='add a',
266
timestamp=1132711707,
268
committer='Lorem Ipsum <test@example.com>')
269
logfile = file('out.tmp', 'w+')
270
formatter = LongLogFormatter(to_file=logfile)
271
show_log(b, formatter, verbose=True)
274
log_contents = logfile.read()
275
self.assertEqualDiff(log_contents, '''\
276
------------------------------------------------------------
278
committer: Lorem Ipsum <test@example.com>
279
branch nick: test_verbose_log
280
timestamp: Wed 2005-11-23 12:08:27 +1000
287
def test_line_log(self):
288
"""Line log should show revno
292
wt = self.make_branch_and_tree('.')
294
self.build_tree(['a'])
296
b.nick = 'test-line-log'
297
wt.commit(message='add a',
298
timestamp=1132711707,
300
committer='Line-Log-Formatter Tester <test@line.log>')
301
logfile = file('out.tmp', 'w+')
302
formatter = LineLogFormatter(to_file=logfile)
303
show_log(b, formatter)
306
log_contents = logfile.read()
307
self.assertEqualDiff(log_contents, '1: Line-Log-Formatte... 2005-11-23 add a\n')
309
def make_tree_with_commits(self):
310
"""Create a tree with well-known revision ids"""
311
wt = self.make_branch_and_tree('tree1')
312
wt.commit('commit one', rev_id='1')
313
wt.commit('commit two', rev_id='2')
314
wt.commit('commit three', rev_id='3')
315
mainline_revs = [None, '1', '2', '3']
316
rev_nos = {'1': 1, '2': 2, '3': 3}
317
return mainline_revs, rev_nos, wt
319
def pseudo_merge(self, source, target):
320
revision_id = source.last_revision()
321
target.branch.fetch(source.branch, revision_id)
322
target.add_pending_merge(revision_id)
324
def make_tree_with_merges(self):
325
"""Create a tree with well-known revision ids and a merge"""
326
mainline_revs, rev_nos, wt = self.make_tree_with_commits()
327
tree2 = wt.bzrdir.sprout('tree2').open_workingtree()
328
tree2.commit('four-a', rev_id='4a')
329
self.pseudo_merge(tree2, wt)
330
wt.commit('four-b', rev_id='4b')
331
mainline_revs.append('4b')
333
return mainline_revs, rev_nos, wt
335
def make_tree_with_many_merges(self):
336
"""Create a tree with well-known revision ids"""
337
wt = self.make_branch_and_tree('tree1')
338
wt.commit('commit one', rev_id='1')
339
wt.commit('commit two', rev_id='2')
340
tree2 = wt.bzrdir.sprout('tree2').open_workingtree()
341
tree3 = wt.bzrdir.sprout('tree3').open_workingtree()
342
tree3.commit('commit three a', rev_id='3a')
343
self.pseudo_merge(tree3, tree2)
344
tree2.commit('commit three b', rev_id='3b')
345
self.pseudo_merge(tree2, wt)
346
wt.commit('commit three c', rev_id='3c')
347
tree2.commit('four-a', rev_id='4a')
348
self.pseudo_merge(tree2, wt)
349
wt.commit('four-b', rev_id='4b')
350
mainline_revs = [None, '1', '2', '3c', '4b']
351
rev_nos = {'1': 1, '2': 2, '3c': 3, '4b': 4}
352
return mainline_revs, rev_nos, wt
354
def test_get_view_revisions_forward(self):
355
"""Test the get_view_revisions method"""
356
mainline_revs, rev_nos, wt = self.make_tree_with_commits()
357
revisions = list(get_view_revisions(mainline_revs, rev_nos, wt.branch,
359
self.assertEqual(revisions, [('1', 1, 0), ('2', 2, 0), ('3', 3, 0)])
360
revisions2 = list(get_view_revisions(mainline_revs, rev_nos, wt.branch,
361
'forward', include_merges=False))
362
self.assertEqual(revisions, revisions2)
364
def test_get_view_revisions_reverse(self):
365
"""Test the get_view_revisions with reverse"""
366
mainline_revs, rev_nos, wt = self.make_tree_with_commits()
367
revisions = list(get_view_revisions(mainline_revs, rev_nos, wt.branch,
369
self.assertEqual(revisions, [('3', 3, 0), ('2', 2, 0), ('1', 1, 0), ])
370
revisions2 = list(get_view_revisions(mainline_revs, rev_nos, wt.branch,
371
'reverse', include_merges=False))
372
self.assertEqual(revisions, revisions2)
374
def test_get_view_revisions_merge(self):
375
"""Test get_view_revisions when there are merges"""
376
mainline_revs, rev_nos, wt = self.make_tree_with_merges()
377
revisions = list(get_view_revisions(mainline_revs, rev_nos, wt.branch,
379
self.assertEqual(revisions, [('1', 1, 0), ('2', 2, 0), ('3', 3, 0),
380
('4b', 4, 0), ('4a', None, 1)])
381
revisions = list(get_view_revisions(mainline_revs, rev_nos, wt.branch,
382
'forward', include_merges=False))
383
self.assertEqual(revisions, [('1', 1, 0), ('2', 2, 0), ('3', 3, 0),
386
def test_get_view_revisions_merge_reverse(self):
387
"""Test get_view_revisions in reverse when there are merges"""
388
mainline_revs, rev_nos, wt = self.make_tree_with_merges()
389
revisions = list(get_view_revisions(mainline_revs, rev_nos, wt.branch,
391
self.assertEqual(revisions, [('4b', 4, 0), ('4a', None, 1),
392
('3', 3, 0), ('2', 2, 0), ('1', 1, 0)])
393
revisions = list(get_view_revisions(mainline_revs, rev_nos, wt.branch,
394
'reverse', include_merges=False))
395
self.assertEqual(revisions, [('4b', 4, 0), ('3', 3, 0), ('2', 2, 0),
398
def test_get_view_revisions_merge2(self):
399
"""Test get_view_revisions when there are merges"""
400
mainline_revs, rev_nos, wt = self.make_tree_with_many_merges()
401
revisions = list(get_view_revisions(mainline_revs, rev_nos, wt.branch,
403
expected = [('1', 1, 0), ('2', 2, 0), ('3c', 3, 0), ('3a', None, 1),
404
('3b', None, 1), ('4b', 4, 0), ('4a', None, 1)]
405
self.assertEqual(revisions, expected)
406
revisions = list(get_view_revisions(mainline_revs, rev_nos, wt.branch,
407
'forward', include_merges=False))
408
self.assertEqual(revisions, [('1', 1, 0), ('2', 2, 0), ('3c', 3, 0),