30
class TestCaseWithoutPropsHandler(tests.TestCaseWithTransport):
31
class TestLogMixin(object):
33
def wt_commit(self, wt, message, **kwargs):
34
"""Use some mostly fixed values for commits to simplify tests.
36
Tests can use this function to get some commit attributes. The time
37
stamp is incremented at each commit.
39
if getattr(self, 'timestamp', None) is None:
40
self.timestamp = 1132617600 # Mon 2005-11-22 00:00:00 +0000
42
self.timestamp += 1 # 1 second between each commit
43
kwargs.setdefault('timestamp', self.timestamp)
44
kwargs.setdefault('timezone', 0) # UTC
45
kwargs.setdefault('committer', 'Joe Foo <joe@foo.com>')
47
return wt.commit(message, **kwargs)
50
class TestCaseForLogFormatter(tests.TestCaseWithTransport, TestLogMixin):
33
super(TestCaseWithoutPropsHandler, self).setUp()
53
super(TestCaseForLogFormatter, self).setUp()
34
54
# keep a reference to the "current" custom prop. handler registry
35
55
self.properties_handler_registry = log.properties_handler_registry
36
# clean up the registry in log
56
# Use a clean registry for log
37
57
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
60
log.properties_handler_registry = self.properties_handler_registry
61
self.addCleanup(restore)
63
def assertFormatterResult(self, result, branch, formatter_class,
64
formatter_kwargs=None, show_log_kwargs=None):
65
logfile = self.make_utf8_encoded_stringio()
66
if formatter_kwargs is None:
68
formatter = formatter_class(to_file=logfile, **formatter_kwargs)
69
if show_log_kwargs is None:
71
log.show_log(branch, formatter, **show_log_kwargs)
72
self.assertEqualDiff(result, logfile.getvalue())
74
def make_standard_commit(self, branch_nick, **kwargs):
75
wt = self.make_branch_and_tree('.')
77
self.addCleanup(wt.unlock)
78
self.build_tree(['a'])
80
wt.branch.nick = branch_nick
81
kwargs.setdefault('committer', 'Lorem Ipsum <test@example.com>')
82
kwargs.setdefault('authors', ['John Doe <jdoe@example.com>'])
83
self.wt_commit(wt, 'add a', **kwargs)
86
def make_commits_with_trailing_newlines(self, wt):
87
"""Helper method for LogFormatter tests"""
90
self.build_tree_contents([('a', 'hello moto\n')])
91
self.wt_commit(wt, 'simple log message', rev_id='a1')
92
self.build_tree_contents([('b', 'goodbye\n')])
94
self.wt_commit(wt, 'multiline\nlog\nmessage\n', rev_id='a2')
96
self.build_tree_contents([('c', 'just another manic monday\n')])
98
self.wt_commit(wt, 'single line with trailing newline\n', rev_id='a3')
101
def _prepare_tree_with_merges(self, with_tags=False):
102
wt = self.make_branch_and_memory_tree('.')
104
self.addCleanup(wt.unlock)
106
self.wt_commit(wt, 'rev-1', rev_id='rev-1')
107
self.wt_commit(wt, 'rev-merged', rev_id='rev-2a')
108
wt.set_parent_ids(['rev-1', 'rev-2a'])
109
wt.branch.set_last_revision_info(1, 'rev-1')
110
self.wt_commit(wt, 'rev-2', rev_id='rev-2b')
113
branch.tags.set_tag('v0.2', 'rev-2b')
114
self.wt_commit(wt, 'rev-3', rev_id='rev-3')
115
branch.tags.set_tag('v1.0rc1', 'rev-3')
116
branch.tags.set_tag('v1.0', 'rev-3')
45
119
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.
120
"""Pull log messages into a list rather than displaying them.
122
To simplify testing we save logged revisions here rather than actually
123
formatting anything, so that we can precisely check the result without
124
being dependent on the formatting.
127
supports_merge_revisions = True
55
128
supports_delta = True
58
super(LogCatcher, self).__init__(to_file=None)
132
def __init__(self, *args, **kwargs):
133
kwargs.update(dict(to_file=None))
134
super(LogCatcher, self).__init__(*args, **kwargs)
61
137
def log_revision(self, revision):
62
self.logs.append(revision)
138
self.revisions.append(revision)
65
141
class TestShowLog(tests.TestCaseWithTransport):
181
261
lf.supports_merge_revisions = True
182
262
log.show_log(b, lf, verbose=True)
184
self.assertEqual(3, len(lf.logs))
265
self.assertEqual(3, len(revs))
186
logentry = lf.logs[0]
187
268
self.assertEqual('2', logentry.revno)
188
269
self.assertEqual('merge child branch', logentry.rev.message)
189
270
self.checkDelta(logentry.delta, removed=['file1'], modified=['file2'])
191
logentry = lf.logs[1]
192
273
self.assertEqual('1.1.1', logentry.revno)
193
274
self.assertEqual('remove file1 and modify file2', logentry.rev.message)
194
275
self.checkDelta(logentry.delta, removed=['file1'], modified=['file2'])
196
logentry = lf.logs[2]
197
278
self.assertEqual('1', logentry.revno)
198
279
self.assertEqual('add file1 and file2', logentry.rev.message)
199
280
self.checkDelta(logentry.delta, added=['file1', 'file2'])
201
def test_merges_nonsupporting_formatter(self):
202
"""Tests that show_log will raise if the formatter doesn't
203
support merge revisions."""
204
wt = self.make_branch_and_memory_tree('.')
206
self.addCleanup(wt.unlock)
208
wt.commit('rev-1', rev_id='rev-1',
209
timestamp=1132586655, timezone=36000,
210
committer='Joe Foo <joe@foo.com>')
211
wt.commit('rev-merged', rev_id='rev-2a',
212
timestamp=1132586700, timezone=36000,
213
committer='Joe Foo <joe@foo.com>')
214
wt.set_parent_ids(['rev-1', 'rev-2a'])
215
wt.branch.set_last_revision_info(1, 'rev-1')
216
wt.commit('rev-2', rev_id='rev-2b',
217
timestamp=1132586800, timezone=36000,
218
committer='Joe Foo <joe@foo.com>')
219
logfile = self.make_utf8_encoded_stringio()
220
formatter = log.ShortLogFormatter(to_file=logfile)
223
revspec = revisionspec.RevisionSpec.from_string('1.1.1')
224
rev = revspec.in_history(wtb)
225
self.assertRaises(errors.BzrCommandError, log.show_log, wtb, lf,
226
start_revision=rev, end_revision=rev)
229
def make_commits_with_trailing_newlines(wt):
230
"""Helper method for LogFormatter tests"""
233
open('a', 'wb').write('hello moto\n')
235
wt.commit('simple log message', rev_id='a1',
236
timestamp=1132586655.459960938, timezone=-6*3600,
237
committer='Joe Foo <joe@foo.com>')
238
open('b', 'wb').write('goodbye\n')
240
wt.commit('multiline\nlog\nmessage\n', rev_id='a2',
241
timestamp=1132586842.411175966, timezone=-6*3600,
242
committer='Joe Foo <joe@foo.com>',
243
author='Joe Bar <joe@bar.com>')
245
open('c', 'wb').write('just another manic monday\n')
247
wt.commit('single line with trailing newline\n', rev_id='a3',
248
timestamp=1132587176.835228920, timezone=-6*3600,
249
committer = 'Joe Foo <joe@foo.com>')
253
def normalize_log(log):
254
"""Replaces the variable lines of logs with fixed lines"""
255
author = 'author: Dolor Sit <test@example.com>'
256
committer = 'committer: Lorem Ipsum <test@example.com>'
257
lines = log.splitlines(True)
258
for idx,line in enumerate(lines):
259
stripped_line = line.lstrip()
260
indent = ' ' * (len(line) - len(stripped_line))
261
if stripped_line.startswith('author:'):
262
lines[idx] = indent + author + '\n'
263
elif stripped_line.startswith('committer:'):
264
lines[idx] = indent + committer + '\n'
265
elif stripped_line.startswith('timestamp:'):
266
lines[idx] = indent + 'timestamp: Just now\n'
267
return ''.join(lines)
270
class TestShortLogFormatter(tests.TestCaseWithTransport):
283
class TestShortLogFormatter(TestCaseForLogFormatter):
272
285
def test_trailing_newlines(self):
273
286
wt = self.make_branch_and_tree('.')
274
b = make_commits_with_trailing_newlines(wt)
275
sio = self.make_utf8_encoded_stringio()
276
lf = log.ShortLogFormatter(to_file=sio)
278
self.assertEqualDiff("""\
279
3 Joe Foo\t2005-11-21
287
b = self.make_commits_with_trailing_newlines(wt)
288
self.assertFormatterResult("""\
289
3 Joe Foo\t2005-11-22
280
290
single line with trailing newline
282
2 Joe Bar\t2005-11-21
292
2 Joe Foo\t2005-11-22
287
1 Joe Foo\t2005-11-21
297
1 Joe Foo\t2005-11-22
288
298
simple log message
293
def _prepare_tree_with_merges(self, with_tags=False):
294
wt = self.make_branch_and_memory_tree('.')
296
self.addCleanup(wt.unlock)
298
wt.commit('rev-1', rev_id='rev-1',
299
timestamp=1132586655, timezone=36000,
300
committer='Joe Foo <joe@foo.com>')
301
wt.commit('rev-merged', rev_id='rev-2a',
302
timestamp=1132586700, timezone=36000,
303
committer='Joe Foo <joe@foo.com>')
304
wt.set_parent_ids(['rev-1', 'rev-2a'])
305
wt.branch.set_last_revision_info(1, 'rev-1')
306
wt.commit('rev-2', rev_id='rev-2b',
307
timestamp=1132586800, timezone=36000,
308
committer='Joe Foo <joe@foo.com>')
311
branch.tags.set_tag('v0.2', 'rev-2b')
312
wt.commit('rev-3', rev_id='rev-3',
313
timestamp=1132586900, timezone=36000,
314
committer='Jane Foo <jane@foo.com>')
315
branch.tags.set_tag('v1.0rc1', 'rev-3')
316
branch.tags.set_tag('v1.0', 'rev-3')
301
b, log.ShortLogFormatter)
319
303
def test_short_log_with_merges(self):
320
304
wt = self._prepare_tree_with_merges()
321
logfile = self.make_utf8_encoded_stringio()
322
formatter = log.ShortLogFormatter(to_file=logfile)
323
log.show_log(wt.branch, formatter)
324
self.assertEqualDiff("""\
325
2 Joe Foo\t2005-11-22 [merge]
328
1 Joe Foo\t2005-11-22
305
self.assertFormatterResult("""\
306
2 Joe Foo\t2005-11-22 [merge]
309
1 Joe Foo\t2005-11-22
313
wt.branch, log.ShortLogFormatter)
315
def test_short_log_with_merges_and_advice(self):
316
wt = self._prepare_tree_with_merges()
317
self.assertFormatterResult("""\
318
2 Joe Foo\t2005-11-22 [merge]
321
1 Joe Foo\t2005-11-22
324
Use --include-merges or -n0 to see merged revisions.
326
wt.branch, log.ShortLogFormatter,
327
formatter_kwargs=dict(show_advice=True))
334
329
def test_short_log_with_merges_and_range(self):
335
wt = self.make_branch_and_memory_tree('.')
337
self.addCleanup(wt.unlock)
339
wt.commit('rev-1', rev_id='rev-1',
340
timestamp=1132586655, timezone=36000,
341
committer='Joe Foo <joe@foo.com>')
342
wt.commit('rev-merged', rev_id='rev-2a',
343
timestamp=1132586700, timezone=36000,
344
committer='Joe Foo <joe@foo.com>')
345
wt.branch.set_last_revision_info(1, 'rev-1')
346
wt.set_parent_ids(['rev-1', 'rev-2a'])
347
wt.commit('rev-2b', rev_id='rev-2b',
348
timestamp=1132586800, timezone=36000,
349
committer='Joe Foo <joe@foo.com>')
350
wt.commit('rev-3a', rev_id='rev-3a',
351
timestamp=1132586800, timezone=36000,
352
committer='Joe Foo <joe@foo.com>')
330
wt = self._prepare_tree_with_merges()
331
self.wt_commit(wt, 'rev-3a', rev_id='rev-3a')
353
332
wt.branch.set_last_revision_info(2, 'rev-2b')
354
333
wt.set_parent_ids(['rev-2b', 'rev-3a'])
355
wt.commit('rev-3b', rev_id='rev-3b',
356
timestamp=1132586800, timezone=36000,
357
committer='Joe Foo <joe@foo.com>')
358
logfile = self.make_utf8_encoded_stringio()
359
formatter = log.ShortLogFormatter(to_file=logfile)
360
log.show_log(wt.branch, formatter,
361
start_revision=2, end_revision=3)
362
self.assertEqualDiff("""\
334
self.wt_commit(wt, 'rev-3b', rev_id='rev-3b')
335
self.assertFormatterResult("""\
363
336
3 Joe Foo\t2005-11-22 [merge]
366
339
2 Joe Foo\t2005-11-22 [merge]
343
wt.branch, log.ShortLogFormatter,
344
show_log_kwargs=dict(start_revision=2, end_revision=3))
372
346
def test_short_log_with_tags(self):
373
347
wt = self._prepare_tree_with_merges(with_tags=True)
374
logfile = self.make_utf8_encoded_stringio()
375
formatter = log.ShortLogFormatter(to_file=logfile)
376
log.show_log(wt.branch, formatter)
377
self.assertEqualDiff("""\
378
3 Jane Foo\t2005-11-22 {v1.0, v1.0rc1}
348
self.assertFormatterResult("""\
349
3 Joe Foo\t2005-11-22 {v1.0, v1.0rc1}
381
352
2 Joe Foo\t2005-11-22 {v0.2} [merge]
359
wt.branch, log.ShortLogFormatter)
390
361
def test_short_log_single_merge_revision(self):
391
wt = self.make_branch_and_memory_tree('.')
393
self.addCleanup(wt.unlock)
395
wt.commit('rev-1', rev_id='rev-1',
396
timestamp=1132586655, timezone=36000,
397
committer='Joe Foo <joe@foo.com>')
398
wt.commit('rev-merged', rev_id='rev-2a',
399
timestamp=1132586700, timezone=36000,
400
committer='Joe Foo <joe@foo.com>')
401
wt.set_parent_ids(['rev-1', 'rev-2a'])
402
wt.branch.set_last_revision_info(1, 'rev-1')
403
wt.commit('rev-2', rev_id='rev-2b',
404
timestamp=1132586800, timezone=36000,
405
committer='Joe Foo <joe@foo.com>')
406
logfile = self.make_utf8_encoded_stringio()
407
formatter = log.ShortLogFormatter(to_file=logfile)
362
wt = self._prepare_tree_with_merges()
408
363
revspec = revisionspec.RevisionSpec.from_string('1.1.1')
410
rev = revspec.in_history(wtb)
411
log.show_log(wtb, formatter, start_revision=rev, end_revision=rev)
412
self.assertEqualDiff("""\
364
rev = revspec.in_history(wt.branch)
365
self.assertFormatterResult("""\
413
366
1.1.1 Joe Foo\t2005-11-22
420
class TestShortLogFormatterWithMergeRevisions(tests.TestCaseWithTransport):
370
wt.branch, log.ShortLogFormatter,
371
show_log_kwargs=dict(start_revision=rev, end_revision=rev))
374
class TestShortLogFormatterWithMergeRevisions(TestCaseForLogFormatter):
422
376
def test_short_merge_revs_log_with_merges(self):
423
wt = self.make_branch_and_memory_tree('.')
425
self.addCleanup(wt.unlock)
427
wt.commit('rev-1', rev_id='rev-1',
428
timestamp=1132586655, timezone=36000,
429
committer='Joe Foo <joe@foo.com>')
430
wt.commit('rev-merged', rev_id='rev-2a',
431
timestamp=1132586700, timezone=36000,
432
committer='Joe Foo <joe@foo.com>')
433
wt.set_parent_ids(['rev-1', 'rev-2a'])
434
wt.branch.set_last_revision_info(1, 'rev-1')
435
wt.commit('rev-2', rev_id='rev-2b',
436
timestamp=1132586800, timezone=36000,
437
committer='Joe Foo <joe@foo.com>')
438
logfile = self.make_utf8_encoded_stringio()
439
formatter = log.ShortLogFormatter(to_file=logfile, levels=0)
440
log.show_log(wt.branch, formatter)
377
wt = self._prepare_tree_with_merges()
441
378
# Note that the 1.1.1 indenting is in fact correct given that
442
379
# the revision numbers are right justified within 5 characters
443
380
# for mainline revnos and 9 characters for dotted revnos.
444
self.assertEqualDiff("""\
381
self.assertFormatterResult("""\
445
382
2 Joe Foo\t2005-11-22 [merge]
392
wt.branch, log.ShortLogFormatter,
393
formatter_kwargs=dict(levels=0))
457
395
def test_short_merge_revs_log_single_merge_revision(self):
458
wt = self.make_branch_and_memory_tree('.')
460
self.addCleanup(wt.unlock)
462
wt.commit('rev-1', rev_id='rev-1',
463
timestamp=1132586655, timezone=36000,
464
committer='Joe Foo <joe@foo.com>')
465
wt.commit('rev-merged', rev_id='rev-2a',
466
timestamp=1132586700, timezone=36000,
467
committer='Joe Foo <joe@foo.com>')
468
wt.set_parent_ids(['rev-1', 'rev-2a'])
469
wt.branch.set_last_revision_info(1, 'rev-1')
470
wt.commit('rev-2', rev_id='rev-2b',
471
timestamp=1132586800, timezone=36000,
472
committer='Joe Foo <joe@foo.com>')
473
logfile = self.make_utf8_encoded_stringio()
474
formatter = log.ShortLogFormatter(to_file=logfile, levels=0)
396
wt = self._prepare_tree_with_merges()
475
397
revspec = revisionspec.RevisionSpec.from_string('1.1.1')
477
rev = revspec.in_history(wtb)
478
log.show_log(wtb, formatter, start_revision=rev, end_revision=rev)
479
self.assertEqualDiff("""\
398
rev = revspec.in_history(wt.branch)
399
self.assertFormatterResult("""\
480
400
1.1.1 Joe Foo\t2005-11-22
487
class TestLongLogFormatter(TestCaseWithoutPropsHandler):
404
wt.branch, log.ShortLogFormatter,
405
formatter_kwargs=dict(levels=0),
406
show_log_kwargs=dict(start_revision=rev, end_revision=rev))
409
class TestLongLogFormatter(TestCaseForLogFormatter):
489
411
def test_verbose_log(self):
490
412
"""Verbose log includes changed files
494
wt = self.make_branch_and_tree('.')
496
self.build_tree(['a'])
498
# XXX: why does a longer nick show up?
499
b.nick = 'test_verbose_log'
500
wt.commit(message='add a',
501
timestamp=1132711707,
503
committer='Lorem Ipsum <test@example.com>')
504
logfile = file('out.tmp', 'w+')
505
formatter = log.LongLogFormatter(to_file=logfile)
506
log.show_log(b, formatter, verbose=True)
509
log_contents = logfile.read()
510
self.assertEqualDiff('''\
416
wt = self.make_standard_commit('test_verbose_log', authors=[])
417
self.assertFormatterResult('''\
511
418
------------------------------------------------------------
513
420
committer: Lorem Ipsum <test@example.com>
514
421
branch nick: test_verbose_log
515
timestamp: Wed 2005-11-23 12:08:27 +1000
422
timestamp: Tue 2005-11-22 00:00:00 +0000
428
wt.branch, log.LongLogFormatter,
429
show_log_kwargs=dict(verbose=True))
523
431
def test_merges_are_indented_by_level(self):
524
432
wt = self.make_branch_and_tree('parent')
525
wt.commit('first post')
526
self.run_bzr('branch parent child')
527
self.run_bzr(['commit', '-m', 'branch 1', '--unchanged', 'child'])
528
self.run_bzr('branch child smallerchild')
529
self.run_bzr(['commit', '-m', 'branch 2', '--unchanged',
532
self.run_bzr('merge ../smallerchild')
533
self.run_bzr(['commit', '-m', 'merge branch 2'])
534
os.chdir('../parent')
535
self.run_bzr('merge ../child')
536
wt.commit('merge branch 1')
538
sio = self.make_utf8_encoded_stringio()
539
lf = log.LongLogFormatter(to_file=sio)
540
log.show_log(b, lf, verbose=True)
541
the_log = normalize_log(sio.getvalue())
542
self.assertEqualDiff("""\
433
self.wt_commit(wt, 'first post')
434
child_wt = wt.bzrdir.sprout('child').open_workingtree()
435
self.wt_commit(child_wt, 'branch 1')
436
smallerchild_wt = wt.bzrdir.sprout('smallerchild').open_workingtree()
437
self.wt_commit(smallerchild_wt, 'branch 2')
438
child_wt.merge_from_branch(smallerchild_wt.branch)
439
self.wt_commit(child_wt, 'merge branch 2')
440
wt.merge_from_branch(child_wt.branch)
441
self.wt_commit(wt, 'merge branch 1')
442
self.assertFormatterResult("""\
543
443
------------------------------------------------------------
545
committer: Lorem Ipsum <test@example.com>
445
committer: Joe Foo <joe@foo.com>
546
446
branch nick: parent
447
timestamp: Tue 2005-11-22 00:00:04 +0000
550
450
------------------------------------------------------------
552
committer: Lorem Ipsum <test@example.com>
452
committer: Joe Foo <joe@foo.com>
553
453
branch nick: child
454
timestamp: Tue 2005-11-22 00:00:03 +0000
557
457
------------------------------------------------------------
559
committer: Lorem Ipsum <test@example.com>
459
committer: Joe Foo <joe@foo.com>
560
460
branch nick: smallerchild
461
timestamp: Tue 2005-11-22 00:00:02 +0000
564
464
------------------------------------------------------------
566
committer: Lorem Ipsum <test@example.com>
466
committer: Joe Foo <joe@foo.com>
567
467
branch nick: child
468
timestamp: Tue 2005-11-22 00:00:01 +0000
571
471
------------------------------------------------------------
573
committer: Lorem Ipsum <test@example.com>
473
committer: Joe Foo <joe@foo.com>
574
474
branch nick: parent
475
timestamp: Tue 2005-11-22 00:00:00 +0000
479
wt.branch, log.LongLogFormatter,
480
formatter_kwargs=dict(levels=0),
481
show_log_kwargs=dict(verbose=True))
581
483
def test_verbose_merge_revisions_contain_deltas(self):
582
484
wt = self.make_branch_and_tree('parent')
583
485
self.build_tree(['parent/f1', 'parent/f2'])
584
486
wt.add(['f1','f2'])
585
wt.commit('first post')
586
self.run_bzr('branch parent child')
487
self.wt_commit(wt, 'first post')
488
child_wt = wt.bzrdir.sprout('child').open_workingtree()
587
489
os.unlink('child/f1')
588
file('child/f2', 'wb').write('hello\n')
589
self.run_bzr(['commit', '-m', 'removed f1 and modified f2',
592
self.run_bzr('merge ../child')
593
wt.commit('merge branch 1')
595
sio = self.make_utf8_encoded_stringio()
596
lf = log.LongLogFormatter(to_file=sio)
597
log.show_log(b, lf, verbose=True)
598
the_log = normalize_log(sio.getvalue())
599
self.assertEqualDiff("""\
490
self.build_tree_contents([('child/f2', 'hello\n')])
491
self.wt_commit(child_wt, 'removed f1 and modified f2')
492
wt.merge_from_branch(child_wt.branch)
493
self.wt_commit(wt, 'merge branch 1')
494
self.assertFormatterResult("""\
600
495
------------------------------------------------------------
602
committer: Lorem Ipsum <test@example.com>
497
committer: Joe Foo <joe@foo.com>
603
498
branch nick: parent
499
timestamp: Tue 2005-11-22 00:00:02 +0000
661
554
committer: Joe Foo <joe@foo.com>
662
555
branch nick: test
663
timestamp: Mon 2005-11-21 09:24:15 -0600
556
timestamp: Tue 2005-11-22 00:00:00 +0000
665
558
simple log message
560
b, log.LongLogFormatter)
669
562
def test_author_in_log(self):
670
563
"""Log includes the author name if it's set in
671
564
the revision properties
673
wt = self.make_branch_and_tree('.')
675
self.build_tree(['a'])
677
b.nick = 'test_author_log'
678
wt.commit(message='add a',
679
timestamp=1132711707,
681
committer='Lorem Ipsum <test@example.com>',
682
author='John Doe <jdoe@example.com>')
684
formatter = log.LongLogFormatter(to_file=sio)
685
log.show_log(b, formatter)
686
self.assertEqualDiff('''\
566
wt = self.make_standard_commit('test_author_log',
567
authors=['John Doe <jdoe@example.com>',
568
'Jane Rey <jrey@example.com>'])
569
self.assertFormatterResult("""\
687
570
------------------------------------------------------------
689
author: John Doe <jdoe@example.com>
572
author: John Doe <jdoe@example.com>, Jane Rey <jrey@example.com>
690
573
committer: Lorem Ipsum <test@example.com>
691
574
branch nick: test_author_log
692
timestamp: Wed 2005-11-23 12:08:27 +1000
575
timestamp: Tue 2005-11-22 00:00:00 +0000
579
wt.branch, log.LongLogFormatter)
698
581
def test_properties_in_log(self):
699
"""Log includes the custom properties returned by the registered
582
"""Log includes the custom properties returned by the registered
702
wt = self.make_branch_and_tree('.')
704
self.build_tree(['a'])
706
b.nick = 'test_properties_in_log'
707
wt.commit(message='add a',
708
timestamp=1132711707,
710
committer='Lorem Ipsum <test@example.com>',
711
author='John Doe <jdoe@example.com>')
713
formatter = log.LongLogFormatter(to_file=sio)
715
def trivial_custom_prop_handler(revision):
716
return {'test_prop':'test_value'}
585
wt = self.make_standard_commit('test_properties_in_log')
586
def trivial_custom_prop_handler(revision):
587
return {'test_prop':'test_value'}
718
log.properties_handler_registry.register(
719
'trivial_custom_prop_handler',
720
trivial_custom_prop_handler)
721
log.show_log(b, formatter)
723
log.properties_handler_registry.remove(
724
'trivial_custom_prop_handler')
725
self.assertEqualDiff('''\
589
# Cleaned up in setUp()
590
log.properties_handler_registry.register(
591
'trivial_custom_prop_handler',
592
trivial_custom_prop_handler)
593
self.assertFormatterResult("""\
726
594
------------------------------------------------------------
728
596
test_prop: test_value
729
597
author: John Doe <jdoe@example.com>
730
598
committer: Lorem Ipsum <test@example.com>
731
599
branch nick: test_properties_in_log
732
timestamp: Wed 2005-11-23 12:08:27 +1000
600
timestamp: Tue 2005-11-22 00:00:00 +0000
604
wt.branch, log.LongLogFormatter)
738
606
def test_properties_in_short_log(self):
739
"""Log includes the custom properties returned by the registered
607
"""Log includes the custom properties returned by the registered
742
wt = self.make_branch_and_tree('.')
744
self.build_tree(['a'])
746
b.nick = 'test_properties_in_short_log'
747
wt.commit(message='add a',
748
timestamp=1132711707,
750
committer='Lorem Ipsum <test@example.com>',
751
author='John Doe <jdoe@example.com>')
753
formatter = log.ShortLogFormatter(to_file=sio)
755
def trivial_custom_prop_handler(revision):
756
return {'test_prop':'test_value'}
610
wt = self.make_standard_commit('test_properties_in_short_log')
611
def trivial_custom_prop_handler(revision):
612
return {'test_prop':'test_value'}
758
log.properties_handler_registry.register(
759
'trivial_custom_prop_handler',
760
trivial_custom_prop_handler)
761
log.show_log(b, formatter)
763
log.properties_handler_registry.remove(
764
'trivial_custom_prop_handler')
765
self.assertEqualDiff('''\
766
1 John Doe\t2005-11-23
614
log.properties_handler_registry.register(
615
'trivial_custom_prop_handler',
616
trivial_custom_prop_handler)
617
self.assertFormatterResult("""\
618
1 John Doe\t2005-11-22
767
619
test_prop: test_value
623
wt.branch, log.ShortLogFormatter)
773
625
def test_error_in_properties_handler(self):
774
"""Log includes the custom properties returned by the registered
626
"""Log includes the custom properties returned by the registered
777
wt = self.make_branch_and_tree('.')
779
self.build_tree(['a'])
781
b.nick = 'test_author_log'
782
wt.commit(message='add a',
783
timestamp=1132711707,
785
committer='Lorem Ipsum <test@example.com>',
786
author='John Doe <jdoe@example.com>',
787
revprops={'first_prop':'first_value'})
629
wt = self.make_standard_commit('error_in_properties_handler',
630
revprops={'first_prop':'first_value'})
631
sio = self.make_utf8_encoded_stringio()
789
632
formatter = log.LongLogFormatter(to_file=sio)
791
def trivial_custom_prop_handler(revision):
792
raise StandardError("a test error")
633
def trivial_custom_prop_handler(revision):
634
raise StandardError("a test error")
794
log.properties_handler_registry.register(
795
'trivial_custom_prop_handler',
796
trivial_custom_prop_handler)
797
self.assertRaises(StandardError, log.show_log, b, formatter,)
799
log.properties_handler_registry.remove(
800
'trivial_custom_prop_handler')
636
log.properties_handler_registry.register(
637
'trivial_custom_prop_handler',
638
trivial_custom_prop_handler)
639
self.assertRaises(StandardError, log.show_log, wt.branch, formatter,)
802
641
def test_properties_handler_bad_argument(self):
803
wt = self.make_branch_and_tree('.')
805
self.build_tree(['a'])
807
b.nick = 'test_author_log'
808
wt.commit(message='add a',
809
timestamp=1132711707,
811
committer='Lorem Ipsum <test@example.com>',
812
author='John Doe <jdoe@example.com>',
813
revprops={'a_prop':'test_value'})
642
wt = self.make_standard_commit('bad_argument',
643
revprops={'a_prop':'test_value'})
644
sio = self.make_utf8_encoded_stringio()
815
645
formatter = log.LongLogFormatter(to_file=sio)
817
def bad_argument_prop_handler(revision):
818
return {'custom_prop_name':revision.properties['a_prop']}
820
log.properties_handler_registry.register(
821
'bad_argument_prop_handler',
822
bad_argument_prop_handler)
824
self.assertRaises(AttributeError, formatter.show_properties,
827
revision = b.repository.get_revision(b.last_revision())
828
formatter.show_properties(revision, '')
829
self.assertEqualDiff('''custom_prop_name: test_value\n''',
832
log.properties_handler_registry.remove(
833
'bad_argument_prop_handler')
836
class TestLongLogFormatterWithoutMergeRevisions(TestCaseWithoutPropsHandler):
646
def bad_argument_prop_handler(revision):
647
return {'custom_prop_name':revision.properties['a_prop']}
649
log.properties_handler_registry.register(
650
'bad_argument_prop_handler',
651
bad_argument_prop_handler)
653
self.assertRaises(AttributeError, formatter.show_properties,
656
revision = wt.branch.repository.get_revision(wt.branch.last_revision())
657
formatter.show_properties(revision, '')
658
self.assertEqualDiff('''custom_prop_name: test_value\n''',
662
class TestLongLogFormatterWithoutMergeRevisions(TestCaseForLogFormatter):
838
664
def test_long_verbose_log(self):
839
665
"""Verbose log includes changed files
843
wt = self.make_branch_and_tree('.')
845
self.build_tree(['a'])
847
# XXX: why does a longer nick show up?
848
b.nick = 'test_verbose_log'
849
wt.commit(message='add a',
850
timestamp=1132711707,
852
committer='Lorem Ipsum <test@example.com>')
853
logfile = file('out.tmp', 'w+')
854
formatter = log.LongLogFormatter(to_file=logfile, levels=1)
855
log.show_log(b, formatter, verbose=True)
858
log_contents = logfile.read()
859
self.assertEqualDiff('''\
669
wt = self.make_standard_commit('test_long_verbose_log', authors=[])
670
self.assertFormatterResult("""\
860
671
------------------------------------------------------------
862
673
committer: Lorem Ipsum <test@example.com>
863
branch nick: test_verbose_log
864
timestamp: Wed 2005-11-23 12:08:27 +1000
674
branch nick: test_long_verbose_log
675
timestamp: Tue 2005-11-22 00:00:00 +0000
681
wt.branch, log.LongLogFormatter,
682
formatter_kwargs=dict(levels=1),
683
show_log_kwargs=dict(verbose=True))
872
685
def test_long_verbose_contain_deltas(self):
873
686
wt = self.make_branch_and_tree('parent')
874
687
self.build_tree(['parent/f1', 'parent/f2'])
875
688
wt.add(['f1','f2'])
876
wt.commit('first post')
877
self.run_bzr('branch parent child')
689
self.wt_commit(wt, 'first post')
690
child_wt = wt.bzrdir.sprout('child').open_workingtree()
878
691
os.unlink('child/f1')
879
file('child/f2', 'wb').write('hello\n')
880
self.run_bzr(['commit', '-m', 'removed f1 and modified f2',
883
self.run_bzr('merge ../child')
884
wt.commit('merge branch 1')
886
sio = self.make_utf8_encoded_stringio()
887
lf = log.LongLogFormatter(to_file=sio, levels=1)
888
log.show_log(b, lf, verbose=True)
889
the_log = normalize_log(sio.getvalue())
890
self.assertEqualDiff("""\
692
self.build_tree_contents([('child/f2', 'hello\n')])
693
self.wt_commit(child_wt, 'removed f1 and modified f2')
694
wt.merge_from_branch(child_wt.branch)
695
self.wt_commit(wt, 'merge branch 1')
696
self.assertFormatterResult("""\
891
697
------------------------------------------------------------
893
committer: Lorem Ipsum <test@example.com>
699
committer: Joe Foo <joe@foo.com>
894
700
branch nick: parent
701
timestamp: Tue 2005-11-22 00:00:02 +0000
941
745
committer: Joe Foo <joe@foo.com>
942
746
branch nick: test
943
timestamp: Mon 2005-11-21 09:24:15 -0600
747
timestamp: Tue 2005-11-22 00:00:00 +0000
945
749
simple log message
751
b, log.LongLogFormatter,
752
formatter_kwargs=dict(levels=1))
949
754
def test_long_author_in_log(self):
950
755
"""Log includes the author name if it's set in
951
756
the revision properties
953
wt = self.make_branch_and_tree('.')
955
self.build_tree(['a'])
957
b.nick = 'test_author_log'
958
wt.commit(message='add a',
959
timestamp=1132711707,
961
committer='Lorem Ipsum <test@example.com>',
962
author='John Doe <jdoe@example.com>')
964
formatter = log.LongLogFormatter(to_file=sio, levels=1)
965
log.show_log(b, formatter)
966
self.assertEqualDiff('''\
758
wt = self.make_standard_commit('test_author_log')
759
self.assertFormatterResult("""\
967
760
------------------------------------------------------------
969
762
author: John Doe <jdoe@example.com>
970
763
committer: Lorem Ipsum <test@example.com>
971
764
branch nick: test_author_log
972
timestamp: Wed 2005-11-23 12:08:27 +1000
765
timestamp: Tue 2005-11-22 00:00:00 +0000
769
wt.branch, log.LongLogFormatter,
770
formatter_kwargs=dict(levels=1))
978
772
def test_long_properties_in_log(self):
979
"""Log includes the custom properties returned by the registered
773
"""Log includes the custom properties returned by the registered
982
wt = self.make_branch_and_tree('.')
984
self.build_tree(['a'])
986
b.nick = 'test_properties_in_log'
987
wt.commit(message='add a',
988
timestamp=1132711707,
990
committer='Lorem Ipsum <test@example.com>',
991
author='John Doe <jdoe@example.com>')
993
formatter = log.LongLogFormatter(to_file=sio, levels=1)
995
def trivial_custom_prop_handler(revision):
996
return {'test_prop':'test_value'}
776
wt = self.make_standard_commit('test_properties_in_log')
777
def trivial_custom_prop_handler(revision):
778
return {'test_prop':'test_value'}
998
log.properties_handler_registry.register(
999
'trivial_custom_prop_handler',
1000
trivial_custom_prop_handler)
1001
log.show_log(b, formatter)
1003
log.properties_handler_registry.remove(
1004
'trivial_custom_prop_handler')
1005
self.assertEqualDiff('''\
780
log.properties_handler_registry.register(
781
'trivial_custom_prop_handler',
782
trivial_custom_prop_handler)
783
self.assertFormatterResult("""\
1006
784
------------------------------------------------------------
1008
786
test_prop: test_value
1009
787
author: John Doe <jdoe@example.com>
1010
788
committer: Lorem Ipsum <test@example.com>
1011
789
branch nick: test_properties_in_log
1012
timestamp: Wed 2005-11-23 12:08:27 +1000
790
timestamp: Tue 2005-11-22 00:00:00 +0000
1019
class TestLineLogFormatter(tests.TestCaseWithTransport):
794
wt.branch, log.LongLogFormatter,
795
formatter_kwargs=dict(levels=1))
798
class TestLineLogFormatter(TestCaseForLogFormatter):
1021
800
def test_line_log(self):
1022
801
"""Line log should show revno
1026
wt = self.make_branch_and_tree('.')
1028
self.build_tree(['a'])
1030
b.nick = 'test-line-log'
1031
wt.commit(message='add a',
1032
timestamp=1132711707,
1034
committer='Line-Log-Formatter Tester <test@line.log>')
1035
logfile = file('out.tmp', 'w+')
1036
formatter = log.LineLogFormatter(to_file=logfile)
1037
log.show_log(b, formatter)
1040
log_contents = logfile.read()
1041
self.assertEqualDiff('1: Line-Log-Formatte... 2005-11-23 add a\n',
805
wt = self.make_standard_commit('test-line-log',
806
committer='Line-Log-Formatter Tester <test@line.log>',
808
self.assertFormatterResult("""\
809
1: Line-Log-Formatte... 2005-11-22 add a
811
wt.branch, log.LineLogFormatter)
1044
813
def test_trailing_newlines(self):
1045
814
wt = self.make_branch_and_tree('.')
1046
b = make_commits_with_trailing_newlines(wt)
1047
sio = self.make_utf8_encoded_stringio()
1048
lf = log.LineLogFormatter(to_file=sio)
1050
self.assertEqualDiff("""\
1051
3: Joe Foo 2005-11-21 single line with trailing newline
1052
2: Joe Bar 2005-11-21 multiline
1053
1: Joe Foo 2005-11-21 simple log message
815
b = self.make_commits_with_trailing_newlines(wt)
816
self.assertFormatterResult("""\
817
3: Joe Foo 2005-11-22 single line with trailing newline
818
2: Joe Foo 2005-11-22 multiline
819
1: Joe Foo 2005-11-22 simple log message
1057
def _prepare_tree_with_merges(self, with_tags=False):
1058
wt = self.make_branch_and_memory_tree('.')
1060
self.addCleanup(wt.unlock)
1062
wt.commit('rev-1', rev_id='rev-1',
1063
timestamp=1132586655, timezone=36000,
1064
committer='Joe Foo <joe@foo.com>')
1065
wt.commit('rev-merged', rev_id='rev-2a',
1066
timestamp=1132586700, timezone=36000,
1067
committer='Joe Foo <joe@foo.com>')
1068
wt.set_parent_ids(['rev-1', 'rev-2a'])
1069
wt.branch.set_last_revision_info(1, 'rev-1')
1070
wt.commit('rev-2', rev_id='rev-2b',
1071
timestamp=1132586800, timezone=36000,
1072
committer='Joe Foo <joe@foo.com>')
1075
branch.tags.set_tag('v0.2', 'rev-2b')
1076
wt.commit('rev-3', rev_id='rev-3',
1077
timestamp=1132586900, timezone=36000,
1078
committer='Jane Foo <jane@foo.com>')
1079
branch.tags.set_tag('v1.0rc1', 'rev-3')
1080
branch.tags.set_tag('v1.0', 'rev-3')
821
b, log.LineLogFormatter)
1083
823
def test_line_log_single_merge_revision(self):
1084
824
wt = self._prepare_tree_with_merges()
1085
logfile = self.make_utf8_encoded_stringio()
1086
formatter = log.LineLogFormatter(to_file=logfile)
1087
825
revspec = revisionspec.RevisionSpec.from_string('1.1.1')
1089
rev = revspec.in_history(wtb)
1090
log.show_log(wtb, formatter, start_revision=rev, end_revision=rev)
1091
self.assertEqualDiff("""\
826
rev = revspec.in_history(wt.branch)
827
self.assertFormatterResult("""\
1092
828
1.1.1: Joe Foo 2005-11-22 rev-merged
830
wt.branch, log.LineLogFormatter,
831
show_log_kwargs=dict(start_revision=rev, end_revision=rev))
1096
833
def test_line_log_with_tags(self):
1097
834
wt = self._prepare_tree_with_merges(with_tags=True)
1098
logfile = self.make_utf8_encoded_stringio()
1099
formatter = log.LineLogFormatter(to_file=logfile)
1100
log.show_log(wt.branch, formatter)
1101
self.assertEqualDiff("""\
1102
3: Jane Foo 2005-11-22 {v1.0, v1.0rc1} rev-3
1103
2: Joe Foo 2005-11-22 {v0.2} rev-2
835
self.assertFormatterResult("""\
836
3: Joe Foo 2005-11-22 {v1.0, v1.0rc1} rev-3
837
2: Joe Foo 2005-11-22 [merge] {v0.2} rev-2
1104
838
1: Joe Foo 2005-11-22 rev-1
1108
class TestLineLogFormatterWithMergeRevisions(tests.TestCaseWithTransport):
840
wt.branch, log.LineLogFormatter)
843
class TestLineLogFormatterWithMergeRevisions(TestCaseForLogFormatter):
1110
845
def test_line_merge_revs_log(self):
1111
846
"""Line log should show revno
1115
wt = self.make_branch_and_tree('.')
1117
self.build_tree(['a'])
1119
b.nick = 'test-line-log'
1120
wt.commit(message='add a',
1121
timestamp=1132711707,
1123
committer='Line-Log-Formatter Tester <test@line.log>')
1124
logfile = file('out.tmp', 'w+')
1125
formatter = log.LineLogFormatter(to_file=logfile, levels=0)
1126
log.show_log(b, formatter)
1129
log_contents = logfile.read()
1130
self.assertEqualDiff('1: Line-Log-Formatte... 2005-11-23 add a\n',
850
wt = self.make_standard_commit('test-line-log',
851
committer='Line-Log-Formatter Tester <test@line.log>',
853
self.assertFormatterResult("""\
854
1: Line-Log-Formatte... 2005-11-22 add a
856
wt.branch, log.LineLogFormatter)
1133
858
def test_line_merge_revs_log_single_merge_revision(self):
1134
wt = self.make_branch_and_memory_tree('.')
1136
self.addCleanup(wt.unlock)
1138
wt.commit('rev-1', rev_id='rev-1',
1139
timestamp=1132586655, timezone=36000,
1140
committer='Joe Foo <joe@foo.com>')
1141
wt.commit('rev-merged', rev_id='rev-2a',
1142
timestamp=1132586700, timezone=36000,
1143
committer='Joe Foo <joe@foo.com>')
1144
wt.set_parent_ids(['rev-1', 'rev-2a'])
1145
wt.branch.set_last_revision_info(1, 'rev-1')
1146
wt.commit('rev-2', rev_id='rev-2b',
1147
timestamp=1132586800, timezone=36000,
1148
committer='Joe Foo <joe@foo.com>')
1149
logfile = self.make_utf8_encoded_stringio()
1150
formatter = log.LineLogFormatter(to_file=logfile, levels=0)
859
wt = self._prepare_tree_with_merges()
1151
860
revspec = revisionspec.RevisionSpec.from_string('1.1.1')
1153
rev = revspec.in_history(wtb)
1154
log.show_log(wtb, formatter, start_revision=rev, end_revision=rev)
1155
self.assertEqualDiff("""\
861
rev = revspec.in_history(wt.branch)
862
self.assertFormatterResult("""\
1156
863
1.1.1: Joe Foo 2005-11-22 rev-merged
865
wt.branch, log.LineLogFormatter,
866
formatter_kwargs=dict(levels=0),
867
show_log_kwargs=dict(start_revision=rev, end_revision=rev))
1160
869
def test_line_merge_revs_log_with_merges(self):
1161
wt = self.make_branch_and_memory_tree('.')
1163
self.addCleanup(wt.unlock)
1165
wt.commit('rev-1', rev_id='rev-1',
1166
timestamp=1132586655, timezone=36000,
1167
committer='Joe Foo <joe@foo.com>')
1168
wt.commit('rev-merged', rev_id='rev-2a',
1169
timestamp=1132586700, timezone=36000,
1170
committer='Joe Foo <joe@foo.com>')
1171
wt.set_parent_ids(['rev-1', 'rev-2a'])
1172
wt.branch.set_last_revision_info(1, 'rev-1')
1173
wt.commit('rev-2', rev_id='rev-2b',
1174
timestamp=1132586800, timezone=36000,
1175
committer='Joe Foo <joe@foo.com>')
1176
logfile = self.make_utf8_encoded_stringio()
1177
formatter = log.LineLogFormatter(to_file=logfile, levels=0)
1178
log.show_log(wt.branch, formatter)
1179
self.assertEqualDiff("""\
1180
2: Joe Foo 2005-11-22 rev-2
870
wt = self._prepare_tree_with_merges()
871
self.assertFormatterResult("""\
872
2: Joe Foo 2005-11-22 [merge] rev-2
1181
873
1.1.1: Joe Foo 2005-11-22 rev-merged
1182
874
1: Joe Foo 2005-11-22 rev-1
1186
class TestGetViewRevisions(tests.TestCaseWithTransport):
876
wt.branch, log.LineLogFormatter,
877
formatter_kwargs=dict(levels=0))
880
class TestGetViewRevisions(tests.TestCaseWithTransport, TestLogMixin):
882
def _get_view_revisions(self, *args, **kwargs):
883
return self.applyDeprecated(symbol_versioning.deprecated_in((2, 2, 0)),
884
log.get_view_revisions, *args, **kwargs)
1188
886
def make_tree_with_commits(self):
1189
887
"""Create a tree with well-known revision ids"""
1190
888
wt = self.make_branch_and_tree('tree1')
1191
wt.commit('commit one', rev_id='1')
1192
wt.commit('commit two', rev_id='2')
1193
wt.commit('commit three', rev_id='3')
889
self.wt_commit(wt, 'commit one', rev_id='1')
890
self.wt_commit(wt, 'commit two', rev_id='2')
891
self.wt_commit(wt, 'commit three', rev_id='3')
1194
892
mainline_revs = [None, '1', '2', '3']
1195
893
rev_nos = {'1': 1, '2': 2, '3': 3}
1196
894
return mainline_revs, rev_nos, wt
1199
897
"""Create a tree with well-known revision ids and a merge"""
1200
898
mainline_revs, rev_nos, wt = self.make_tree_with_commits()
1201
899
tree2 = wt.bzrdir.sprout('tree2').open_workingtree()
1202
tree2.commit('four-a', rev_id='4a')
900
self.wt_commit(tree2, 'four-a', rev_id='4a')
1203
901
wt.merge_from_branch(tree2.branch)
1204
wt.commit('four-b', rev_id='4b')
902
self.wt_commit(wt, 'four-b', rev_id='4b')
1205
903
mainline_revs.append('4b')
1206
904
rev_nos['4b'] = 4
1208
906
return mainline_revs, rev_nos, wt
1210
def make_tree_with_many_merges(self):
908
def make_branch_with_many_merges(self):
1211
909
"""Create a tree with well-known revision ids"""
1212
wt = self.make_branch_and_tree('tree1')
1213
self.build_tree_contents([('tree1/f', '1\n')])
1214
wt.add(['f'], ['f-id'])
1215
wt.commit('commit one', rev_id='1')
1216
wt.commit('commit two', rev_id='2')
1218
tree3 = wt.bzrdir.sprout('tree3').open_workingtree()
1219
self.build_tree_contents([('tree3/f', '1\n2\n3a\n')])
1220
tree3.commit('commit three a', rev_id='3a')
1222
tree2 = wt.bzrdir.sprout('tree2').open_workingtree()
1223
tree2.merge_from_branch(tree3.branch)
1224
tree2.commit('commit three b', rev_id='3b')
1226
wt.merge_from_branch(tree2.branch)
1227
wt.commit('commit three c', rev_id='3c')
1228
tree2.commit('four-a', rev_id='4a')
1230
wt.merge_from_branch(tree2.branch)
1231
wt.commit('four-b', rev_id='4b')
910
builder = self.make_branch_builder('tree1')
911
builder.start_series()
912
builder.build_snapshot('1', None, [
913
('add', ('', 'TREE_ROOT', 'directory', '')),
914
('add', ('f', 'f-id', 'file', '1\n'))])
915
builder.build_snapshot('2', ['1'], [])
916
builder.build_snapshot('3a', ['2'], [
917
('modify', ('f-id', '1\n2\n3a\n'))])
918
builder.build_snapshot('3b', ['2', '3a'], [
919
('modify', ('f-id', '1\n2\n3a\n'))])
920
builder.build_snapshot('3c', ['2', '3b'], [
921
('modify', ('f-id', '1\n2\n3a\n'))])
922
builder.build_snapshot('4a', ['3b'], [])
923
builder.build_snapshot('4b', ['3c', '4a'], [])
924
builder.finish_series()
1233
938
mainline_revs = [None, '1', '2', '3c', '4b']
1234
939
rev_nos = {'1':1, '2':2, '3c': 3, '4b':4}
1308
1013
def test_get_view_revisions_merge2(self):
1309
1014
"""Test get_view_revisions when there are merges"""
1310
mainline_revs, rev_nos, wt = self.make_tree_with_many_merges()
1312
self.addCleanup(wt.unlock)
1313
revisions = list(log.get_view_revisions(
1314
mainline_revs, rev_nos, wt.branch, 'forward'))
1015
mainline_revs, rev_nos, b = self.make_branch_with_many_merges()
1017
self.addCleanup(b.unlock)
1018
revisions = list(self._get_view_revisions(
1019
mainline_revs, rev_nos, b, 'forward'))
1315
1020
expected = [('1', '1', 0), ('2', '2', 0), ('3c', '3', 0),
1316
('3a', '2.1.1', 1), ('3b', '2.2.1', 1), ('4b', '4', 0),
1021
('3b', '2.2.1', 1), ('3a', '2.1.1', 2), ('4b', '4', 0),
1317
1022
('4a', '2.2.2', 1)]
1318
1023
self.assertEqual(expected, revisions)
1319
revisions = list(log.get_view_revisions(
1320
mainline_revs, rev_nos, wt.branch, 'forward',
1024
revisions = list(self._get_view_revisions(
1025
mainline_revs, rev_nos, b, 'forward',
1321
1026
include_merges=False))
1322
1027
self.assertEqual([('1', '1', 0), ('2', '2', 0), ('3c', '3', 0),
1323
1028
('4b', '4', 0)],
1327
1031
def test_file_id_for_range(self):
1328
mainline_revs, rev_nos, wt = self.make_tree_with_many_merges()
1330
self.addCleanup(wt.unlock)
1032
mainline_revs, rev_nos, b = self.make_branch_with_many_merges()
1034
self.addCleanup(b.unlock)
1332
1036
def rev_from_rev_id(revid, branch):
1333
1037
revspec = revisionspec.RevisionSpec.from_string('revid:%s' % revid)
1334
1038
return revspec.in_history(branch)
1336
1040
def view_revs(start_rev, end_rev, file_id, direction):
1337
revs = log.calculate_view_revisions(
1041
revs = self.applyDeprecated(
1042
symbol_versioning.deprecated_in((2, 2, 0)),
1043
log.calculate_view_revisions,
1339
1045
start_rev, # start_revision
1340
1046
end_rev, # end_revision
1341
1047
direction, # direction
1342
1048
file_id, # specific_fileid
1343
1049
True, # generate_merge_revisions
1344
True, # allow_single_merge_revision
1348
rev_3a = rev_from_rev_id('3a', wt.branch)
1349
rev_4b = rev_from_rev_id('4b', wt.branch)
1350
self.assertEqual([('3c', '3', 0), ('3a', '2.1.1', 1)],
1053
rev_3a = rev_from_rev_id('3a', b)
1054
rev_4b = rev_from_rev_id('4b', b)
1055
self.assertEqual([('3c', '3', 0), ('3b', '2.2.1', 1),
1056
('3a', '2.1.1', 2)],
1351
1057
view_revs(rev_3a, rev_4b, 'f-id', 'reverse'))
1352
1058
# Note: 3c still appears before 3a here because of depth-based sorting
1353
self.assertEqual([('3c', '3', 0), ('3a', '2.1.1', 1)],
1059
self.assertEqual([('3c', '3', 0), ('3b', '2.2.1', 1),
1060
('3a', '2.1.1', 2)],
1354
1061
view_revs(rev_3a, rev_4b, 'f-id', 'forward'))
1357
1064
class TestGetRevisionsTouchingFileID(tests.TestCaseWithTransport):
1066
def get_view_revisions(self, *args):
1067
return self.applyDeprecated(symbol_versioning.deprecated_in((2, 2, 0)),
1068
log.get_view_revisions, *args)
1359
1070
def create_tree_with_single_merge(self):
1360
1071
"""Create a branch with a moderate layout.
1515
1237
class TestLogFormatter(tests.TestCase):
1240
super(TestLogFormatter, self).setUp()
1241
self.rev = revision.Revision('a-id')
1242
self.lf = log.LogFormatter(None)
1517
1244
def test_short_committer(self):
1518
rev = revision.Revision('a-id')
1519
rev.committer = 'John Doe <jdoe@example.com>'
1520
lf = log.LogFormatter(None)
1521
self.assertEqual('John Doe', lf.short_committer(rev))
1522
rev.committer = 'John Smith <jsmith@example.com>'
1523
self.assertEqual('John Smith', lf.short_committer(rev))
1524
rev.committer = 'John Smith'
1525
self.assertEqual('John Smith', lf.short_committer(rev))
1526
rev.committer = 'jsmith@example.com'
1527
self.assertEqual('jsmith@example.com', lf.short_committer(rev))
1528
rev.committer = '<jsmith@example.com>'
1529
self.assertEqual('jsmith@example.com', lf.short_committer(rev))
1530
rev.committer = 'John Smith jsmith@example.com'
1531
self.assertEqual('John Smith', lf.short_committer(rev))
1245
def assertCommitter(expected, committer):
1246
self.rev.committer = committer
1247
self.assertEqual(expected, self.lf.short_committer(self.rev))
1249
assertCommitter('John Doe', 'John Doe <jdoe@example.com>')
1250
assertCommitter('John Smith', 'John Smith <jsmith@example.com>')
1251
assertCommitter('John Smith', 'John Smith')
1252
assertCommitter('jsmith@example.com', 'jsmith@example.com')
1253
assertCommitter('jsmith@example.com', '<jsmith@example.com>')
1254
assertCommitter('John Smith', 'John Smith jsmith@example.com')
1533
1256
def test_short_author(self):
1534
rev = revision.Revision('a-id')
1535
rev.committer = 'John Doe <jdoe@example.com>'
1536
lf = log.LogFormatter(None)
1537
self.assertEqual('John Doe', lf.short_author(rev))
1538
rev.properties['author'] = 'John Smith <jsmith@example.com>'
1539
self.assertEqual('John Smith', lf.short_author(rev))
1540
rev.properties['author'] = 'John Smith'
1541
self.assertEqual('John Smith', lf.short_author(rev))
1542
rev.properties['author'] = 'jsmith@example.com'
1543
self.assertEqual('jsmith@example.com', lf.short_author(rev))
1544
rev.properties['author'] = '<jsmith@example.com>'
1545
self.assertEqual('jsmith@example.com', lf.short_author(rev))
1546
rev.properties['author'] = 'John Smith jsmith@example.com'
1547
self.assertEqual('John Smith', lf.short_author(rev))
1257
def assertAuthor(expected, author):
1258
self.rev.properties['author'] = author
1259
self.assertEqual(expected, self.lf.short_author(self.rev))
1261
assertAuthor('John Smith', 'John Smith <jsmith@example.com>')
1262
assertAuthor('John Smith', 'John Smith')
1263
assertAuthor('jsmith@example.com', 'jsmith@example.com')
1264
assertAuthor('jsmith@example.com', '<jsmith@example.com>')
1265
assertAuthor('John Smith', 'John Smith jsmith@example.com')
1267
def test_short_author_from_committer(self):
1268
self.rev.committer = 'John Doe <jdoe@example.com>'
1269
self.assertEqual('John Doe', self.lf.short_author(self.rev))
1271
def test_short_author_from_authors(self):
1272
self.rev.properties['authors'] = ('John Smith <jsmith@example.com>\n'
1273
'Jane Rey <jrey@example.com>')
1274
self.assertEqual('John Smith', self.lf.short_author(self.rev))
1550
1277
class TestReverseByDepth(tests.TestCase):
1696
1423
log.show_branch_change(tree.branch, s, 3, '3b')
1697
1424
self.assertContainsRe(s.getvalue(), 'Removed Revisions:')
1698
1425
self.assertNotContainsRe(s.getvalue(), 'Added Revisions:')
1429
class TestLogWithBugs(TestCaseForLogFormatter, TestLogMixin):
1432
TestCaseForLogFormatter.setUp(self)
1433
log.properties_handler_registry.register(
1434
'bugs_properties_handler',
1435
log._bugs_properties_handler)
1437
def make_commits_with_bugs(self):
1438
"""Helper method for LogFormatter tests"""
1439
tree = self.make_branch_and_tree(u'.')
1440
self.build_tree(['a', 'b'])
1442
self.wt_commit(tree, 'simple log message', rev_id='a1',
1443
revprops={'bugs': 'test://bug/id fixed'})
1445
self.wt_commit(tree, 'multiline\nlog\nmessage\n', rev_id='a2',
1446
authors=['Joe Bar <joe@bar.com>'],
1447
revprops={'bugs': 'test://bug/id fixed\n'
1448
'test://bug/2 fixed'})
1452
def test_long_bugs(self):
1453
tree = self.make_commits_with_bugs()
1454
self.assertFormatterResult("""\
1455
------------------------------------------------------------
1457
fixes bug(s): test://bug/id test://bug/2
1458
author: Joe Bar <joe@bar.com>
1459
committer: Joe Foo <joe@foo.com>
1461
timestamp: Tue 2005-11-22 00:00:01 +0000
1466
------------------------------------------------------------
1468
fixes bug(s): test://bug/id
1469
committer: Joe Foo <joe@foo.com>
1471
timestamp: Tue 2005-11-22 00:00:00 +0000
1475
tree.branch, log.LongLogFormatter)
1477
def test_short_bugs(self):
1478
tree = self.make_commits_with_bugs()
1479
self.assertFormatterResult("""\
1480
2 Joe Bar\t2005-11-22
1481
fixes bug(s): test://bug/id test://bug/2
1486
1 Joe Foo\t2005-11-22
1487
fixes bug(s): test://bug/id
1491
tree.branch, log.ShortLogFormatter)
1493
def test_wrong_bugs_property(self):
1494
tree = self.make_branch_and_tree(u'.')
1495
self.build_tree(['foo'])
1496
self.wt_commit(tree, 'simple log message', rev_id='a1',
1497
revprops={'bugs': 'test://bug/id invalid_value'})
1498
self.assertFormatterResult("""\
1499
1 Joe Foo\t2005-11-22
1503
tree.branch, log.ShortLogFormatter)
1505
def test_bugs_handler_present(self):
1506
self.properties_handler_registry.get('bugs_properties_handler')