40
60
log.properties_handler_registry = self.properties_handler_registry
41
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')
44
119
class LogCatcher(log.LogFormatter):
45
120
"""Pull log messages into a list rather than displaying them.
201
280
self.checkDelta(logentry.delta, added=['file1', 'file2'])
204
def make_commits_with_trailing_newlines(wt):
205
"""Helper method for LogFormatter tests"""
208
open('a', 'wb').write('hello moto\n')
210
wt.commit('simple log message', rev_id='a1',
211
timestamp=1132586655.459960938, timezone=-6*3600,
212
committer='Joe Foo <joe@foo.com>')
213
open('b', 'wb').write('goodbye\n')
215
wt.commit('multiline\nlog\nmessage\n', rev_id='a2',
216
timestamp=1132586842.411175966, timezone=-6*3600,
217
committer='Joe Foo <joe@foo.com>',
218
authors=['Joe Bar <joe@bar.com>'])
220
open('c', 'wb').write('just another manic monday\n')
222
wt.commit('single line with trailing newline\n', rev_id='a3',
223
timestamp=1132587176.835228920, timezone=-6*3600,
224
committer = 'Joe Foo <joe@foo.com>')
228
def normalize_log(log):
229
"""Replaces the variable lines of logs with fixed lines"""
230
author = 'author: Dolor Sit <test@example.com>'
231
committer = 'committer: Lorem Ipsum <test@example.com>'
232
lines = log.splitlines(True)
233
for idx,line in enumerate(lines):
234
stripped_line = line.lstrip()
235
indent = ' ' * (len(line) - len(stripped_line))
236
if stripped_line.startswith('author:'):
237
lines[idx] = indent + author + '\n'
238
elif stripped_line.startswith('committer:'):
239
lines[idx] = indent + committer + '\n'
240
elif stripped_line.startswith('timestamp:'):
241
lines[idx] = indent + 'timestamp: Just now\n'
242
return ''.join(lines)
245
class TestShortLogFormatter(tests.TestCaseWithTransport):
283
class TestShortLogFormatter(TestCaseForLogFormatter):
247
285
def test_trailing_newlines(self):
248
286
wt = self.make_branch_and_tree('.')
249
b = make_commits_with_trailing_newlines(wt)
250
sio = self.make_utf8_encoded_stringio()
251
lf = log.ShortLogFormatter(to_file=sio)
253
self.assertEqualDiff("""\
254
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
255
290
single line with trailing newline
257
2 Joe Bar\t2005-11-21
292
2 Joe Foo\t2005-11-22
262
1 Joe Foo\t2005-11-21
297
1 Joe Foo\t2005-11-22
263
298
simple log message
268
def _prepare_tree_with_merges(self, with_tags=False):
269
wt = self.make_branch_and_memory_tree('.')
271
self.addCleanup(wt.unlock)
273
wt.commit('rev-1', rev_id='rev-1',
274
timestamp=1132586655, timezone=36000,
275
committer='Joe Foo <joe@foo.com>')
276
wt.commit('rev-merged', rev_id='rev-2a',
277
timestamp=1132586700, timezone=36000,
278
committer='Joe Foo <joe@foo.com>')
279
wt.set_parent_ids(['rev-1', 'rev-2a'])
280
wt.branch.set_last_revision_info(1, 'rev-1')
281
wt.commit('rev-2', rev_id='rev-2b',
282
timestamp=1132586800, timezone=36000,
283
committer='Joe Foo <joe@foo.com>')
286
branch.tags.set_tag('v0.2', 'rev-2b')
287
wt.commit('rev-3', rev_id='rev-3',
288
timestamp=1132586900, timezone=36000,
289
committer='Jane Foo <jane@foo.com>')
290
branch.tags.set_tag('v1.0rc1', 'rev-3')
291
branch.tags.set_tag('v1.0', 'rev-3')
301
b, log.ShortLogFormatter)
294
303
def test_short_log_with_merges(self):
295
304
wt = self._prepare_tree_with_merges()
296
logfile = self.make_utf8_encoded_stringio()
297
formatter = log.ShortLogFormatter(to_file=logfile)
298
log.show_log(wt.branch, formatter)
299
self.assertEqualDiff("""\
305
self.assertFormatterResult("""\
300
306
2 Joe Foo\t2005-11-22 [merge]
322
324
Use --include-merges or -n0 to see merged revisions.
326
wt.branch, log.ShortLogFormatter,
327
formatter_kwargs=dict(show_advice=True))
326
329
def test_short_log_with_merges_and_range(self):
327
wt = self.make_branch_and_memory_tree('.')
329
self.addCleanup(wt.unlock)
331
wt.commit('rev-1', rev_id='rev-1',
332
timestamp=1132586655, timezone=36000,
333
committer='Joe Foo <joe@foo.com>')
334
wt.commit('rev-merged', rev_id='rev-2a',
335
timestamp=1132586700, timezone=36000,
336
committer='Joe Foo <joe@foo.com>')
337
wt.branch.set_last_revision_info(1, 'rev-1')
338
wt.set_parent_ids(['rev-1', 'rev-2a'])
339
wt.commit('rev-2b', rev_id='rev-2b',
340
timestamp=1132586800, timezone=36000,
341
committer='Joe Foo <joe@foo.com>')
342
wt.commit('rev-3a', rev_id='rev-3a',
343
timestamp=1132586800, timezone=36000,
344
committer='Joe Foo <joe@foo.com>')
330
wt = self._prepare_tree_with_merges()
331
self.wt_commit(wt, 'rev-3a', rev_id='rev-3a')
345
332
wt.branch.set_last_revision_info(2, 'rev-2b')
346
333
wt.set_parent_ids(['rev-2b', 'rev-3a'])
347
wt.commit('rev-3b', rev_id='rev-3b',
348
timestamp=1132586800, timezone=36000,
349
committer='Joe Foo <joe@foo.com>')
350
logfile = self.make_utf8_encoded_stringio()
351
formatter = log.ShortLogFormatter(to_file=logfile)
352
log.show_log(wt.branch, formatter,
353
start_revision=2, end_revision=3)
354
self.assertEqualDiff("""\
334
self.wt_commit(wt, 'rev-3b', rev_id='rev-3b')
335
self.assertFormatterResult("""\
355
336
3 Joe Foo\t2005-11-22 [merge]
358
339
2 Joe Foo\t2005-11-22 [merge]
343
wt.branch, log.ShortLogFormatter,
344
show_log_kwargs=dict(start_revision=2, end_revision=3))
364
346
def test_short_log_with_tags(self):
365
347
wt = self._prepare_tree_with_merges(with_tags=True)
366
logfile = self.make_utf8_encoded_stringio()
367
formatter = log.ShortLogFormatter(to_file=logfile)
368
log.show_log(wt.branch, formatter)
369
self.assertEqualDiff("""\
370
3 Jane Foo\t2005-11-22 {v1.0, v1.0rc1}
348
self.assertFormatterResult("""\
349
3 Joe Foo\t2005-11-22 {v1.0, v1.0rc1}
373
352
2 Joe Foo\t2005-11-22 {v0.2} [merge]
359
wt.branch, log.ShortLogFormatter)
382
361
def test_short_log_single_merge_revision(self):
383
wt = self.make_branch_and_memory_tree('.')
385
self.addCleanup(wt.unlock)
387
wt.commit('rev-1', rev_id='rev-1',
388
timestamp=1132586655, timezone=36000,
389
committer='Joe Foo <joe@foo.com>')
390
wt.commit('rev-merged', rev_id='rev-2a',
391
timestamp=1132586700, timezone=36000,
392
committer='Joe Foo <joe@foo.com>')
393
wt.set_parent_ids(['rev-1', 'rev-2a'])
394
wt.branch.set_last_revision_info(1, 'rev-1')
395
wt.commit('rev-2', rev_id='rev-2b',
396
timestamp=1132586800, timezone=36000,
397
committer='Joe Foo <joe@foo.com>')
398
logfile = self.make_utf8_encoded_stringio()
399
formatter = log.ShortLogFormatter(to_file=logfile)
362
wt = self._prepare_tree_with_merges()
400
363
revspec = revisionspec.RevisionSpec.from_string('1.1.1')
402
rev = revspec.in_history(wtb)
403
log.show_log(wtb, formatter, start_revision=rev, end_revision=rev)
404
self.assertEqualDiff("""\
364
rev = revspec.in_history(wt.branch)
365
self.assertFormatterResult("""\
405
366
1.1.1 Joe Foo\t2005-11-22
412
class TestShortLogFormatterWithMergeRevisions(tests.TestCaseWithTransport):
370
wt.branch, log.ShortLogFormatter,
371
show_log_kwargs=dict(start_revision=rev, end_revision=rev))
374
class TestShortLogFormatterWithMergeRevisions(TestCaseForLogFormatter):
414
376
def test_short_merge_revs_log_with_merges(self):
415
wt = self.make_branch_and_memory_tree('.')
417
self.addCleanup(wt.unlock)
419
wt.commit('rev-1', rev_id='rev-1',
420
timestamp=1132586655, timezone=36000,
421
committer='Joe Foo <joe@foo.com>')
422
wt.commit('rev-merged', rev_id='rev-2a',
423
timestamp=1132586700, timezone=36000,
424
committer='Joe Foo <joe@foo.com>')
425
wt.set_parent_ids(['rev-1', 'rev-2a'])
426
wt.branch.set_last_revision_info(1, 'rev-1')
427
wt.commit('rev-2', rev_id='rev-2b',
428
timestamp=1132586800, timezone=36000,
429
committer='Joe Foo <joe@foo.com>')
430
logfile = self.make_utf8_encoded_stringio()
431
formatter = log.ShortLogFormatter(to_file=logfile, levels=0)
432
log.show_log(wt.branch, formatter)
377
wt = self._prepare_tree_with_merges()
433
378
# Note that the 1.1.1 indenting is in fact correct given that
434
379
# the revision numbers are right justified within 5 characters
435
380
# for mainline revnos and 9 characters for dotted revnos.
436
self.assertEqualDiff("""\
381
self.assertFormatterResult("""\
437
382
2 Joe Foo\t2005-11-22 [merge]
392
wt.branch, log.ShortLogFormatter,
393
formatter_kwargs=dict(levels=0))
449
395
def test_short_merge_revs_log_single_merge_revision(self):
450
wt = self.make_branch_and_memory_tree('.')
452
self.addCleanup(wt.unlock)
454
wt.commit('rev-1', rev_id='rev-1',
455
timestamp=1132586655, timezone=36000,
456
committer='Joe Foo <joe@foo.com>')
457
wt.commit('rev-merged', rev_id='rev-2a',
458
timestamp=1132586700, timezone=36000,
459
committer='Joe Foo <joe@foo.com>')
460
wt.set_parent_ids(['rev-1', 'rev-2a'])
461
wt.branch.set_last_revision_info(1, 'rev-1')
462
wt.commit('rev-2', rev_id='rev-2b',
463
timestamp=1132586800, timezone=36000,
464
committer='Joe Foo <joe@foo.com>')
465
logfile = self.make_utf8_encoded_stringio()
466
formatter = log.ShortLogFormatter(to_file=logfile, levels=0)
396
wt = self._prepare_tree_with_merges()
467
397
revspec = revisionspec.RevisionSpec.from_string('1.1.1')
469
rev = revspec.in_history(wtb)
470
log.show_log(wtb, formatter, start_revision=rev, end_revision=rev)
471
self.assertEqualDiff("""\
398
rev = revspec.in_history(wt.branch)
399
self.assertFormatterResult("""\
472
400
1.1.1 Joe Foo\t2005-11-22
479
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):
481
411
def test_verbose_log(self):
482
412
"""Verbose log includes changed files
486
wt = self.make_branch_and_tree('.')
488
self.build_tree(['a'])
490
# XXX: why does a longer nick show up?
491
b.nick = 'test_verbose_log'
492
wt.commit(message='add a',
493
timestamp=1132711707,
495
committer='Lorem Ipsum <test@example.com>')
496
logfile = file('out.tmp', 'w+')
497
formatter = log.LongLogFormatter(to_file=logfile)
498
log.show_log(b, formatter, verbose=True)
501
log_contents = logfile.read()
502
self.assertEqualDiff('''\
416
wt = self.make_standard_commit('test_verbose_log', authors=[])
417
self.assertFormatterResult('''\
503
418
------------------------------------------------------------
505
420
committer: Lorem Ipsum <test@example.com>
506
421
branch nick: test_verbose_log
507
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))
515
431
def test_merges_are_indented_by_level(self):
516
432
wt = self.make_branch_and_tree('parent')
517
wt.commit('first post')
518
self.run_bzr('branch parent child')
519
self.run_bzr(['commit', '-m', 'branch 1', '--unchanged', 'child'])
520
self.run_bzr('branch child smallerchild')
521
self.run_bzr(['commit', '-m', 'branch 2', '--unchanged',
524
self.run_bzr('merge ../smallerchild')
525
self.run_bzr(['commit', '-m', 'merge branch 2'])
526
os.chdir('../parent')
527
self.run_bzr('merge ../child')
528
wt.commit('merge branch 1')
530
sio = self.make_utf8_encoded_stringio()
531
lf = log.LongLogFormatter(to_file=sio, levels=0)
532
log.show_log(b, lf, verbose=True)
533
the_log = normalize_log(sio.getvalue())
534
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("""\
535
443
------------------------------------------------------------
537
committer: Lorem Ipsum <test@example.com>
445
committer: Joe Foo <joe@foo.com>
538
446
branch nick: parent
447
timestamp: Tue 2005-11-22 00:00:04 +0000
542
450
------------------------------------------------------------
543
451
revno: 1.1.2 [merge]
544
committer: Lorem Ipsum <test@example.com>
452
committer: Joe Foo <joe@foo.com>
545
453
branch nick: child
454
timestamp: Tue 2005-11-22 00:00:03 +0000
549
457
------------------------------------------------------------
551
committer: Lorem Ipsum <test@example.com>
459
committer: Joe Foo <joe@foo.com>
552
460
branch nick: smallerchild
461
timestamp: Tue 2005-11-22 00:00:02 +0000
556
464
------------------------------------------------------------
558
committer: Lorem Ipsum <test@example.com>
466
committer: Joe Foo <joe@foo.com>
559
467
branch nick: child
468
timestamp: Tue 2005-11-22 00:00:01 +0000
563
471
------------------------------------------------------------
565
committer: Lorem Ipsum <test@example.com>
473
committer: Joe Foo <joe@foo.com>
566
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))
573
483
def test_verbose_merge_revisions_contain_deltas(self):
574
484
wt = self.make_branch_and_tree('parent')
575
485
self.build_tree(['parent/f1', 'parent/f2'])
576
486
wt.add(['f1','f2'])
577
wt.commit('first post')
578
self.run_bzr('branch parent child')
487
self.wt_commit(wt, 'first post')
488
child_wt = wt.bzrdir.sprout('child').open_workingtree()
579
489
os.unlink('child/f1')
580
file('child/f2', 'wb').write('hello\n')
581
self.run_bzr(['commit', '-m', 'removed f1 and modified f2',
584
self.run_bzr('merge ../child')
585
wt.commit('merge branch 1')
587
sio = self.make_utf8_encoded_stringio()
588
lf = log.LongLogFormatter(to_file=sio, levels=0)
589
log.show_log(b, lf, verbose=True)
590
the_log = normalize_log(sio.getvalue())
591
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("""\
592
495
------------------------------------------------------------
594
committer: Lorem Ipsum <test@example.com>
497
committer: Joe Foo <joe@foo.com>
595
498
branch nick: parent
499
timestamp: Tue 2005-11-22 00:00:02 +0000
653
554
committer: Joe Foo <joe@foo.com>
654
555
branch nick: test
655
timestamp: Mon 2005-11-21 09:24:15 -0600
556
timestamp: Tue 2005-11-22 00:00:00 +0000
657
558
simple log message
560
b, log.LongLogFormatter)
661
562
def test_author_in_log(self):
662
563
"""Log includes the author name if it's set in
663
564
the revision properties
665
wt = self.make_branch_and_tree('.')
667
self.build_tree(['a'])
669
b.nick = 'test_author_log'
670
wt.commit(message='add a',
671
timestamp=1132711707,
673
committer='Lorem Ipsum <test@example.com>',
674
authors=['John Doe <jdoe@example.com>',
675
'Jane Rey <jrey@example.com>'])
677
formatter = log.LongLogFormatter(to_file=sio)
678
log.show_log(b, formatter)
679
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("""\
680
570
------------------------------------------------------------
682
572
author: John Doe <jdoe@example.com>, Jane Rey <jrey@example.com>
683
573
committer: Lorem Ipsum <test@example.com>
684
574
branch nick: test_author_log
685
timestamp: Wed 2005-11-23 12:08:27 +1000
575
timestamp: Tue 2005-11-22 00:00:00 +0000
579
wt.branch, log.LongLogFormatter)
691
581
def test_properties_in_log(self):
692
582
"""Log includes the custom properties returned by the registered
695
wt = self.make_branch_and_tree('.')
697
self.build_tree(['a'])
699
b.nick = 'test_properties_in_log'
700
wt.commit(message='add a',
701
timestamp=1132711707,
703
committer='Lorem Ipsum <test@example.com>',
704
authors=['John Doe <jdoe@example.com>'])
706
formatter = log.LongLogFormatter(to_file=sio)
708
def trivial_custom_prop_handler(revision):
709
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'}
711
log.properties_handler_registry.register(
712
'trivial_custom_prop_handler',
713
trivial_custom_prop_handler)
714
log.show_log(b, formatter)
716
log.properties_handler_registry.remove(
717
'trivial_custom_prop_handler')
718
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("""\
719
594
------------------------------------------------------------
721
596
test_prop: test_value
722
597
author: John Doe <jdoe@example.com>
723
598
committer: Lorem Ipsum <test@example.com>
724
599
branch nick: test_properties_in_log
725
timestamp: Wed 2005-11-23 12:08:27 +1000
600
timestamp: Tue 2005-11-22 00:00:00 +0000
604
wt.branch, log.LongLogFormatter)
731
606
def test_properties_in_short_log(self):
732
607
"""Log includes the custom properties returned by the registered
735
wt = self.make_branch_and_tree('.')
737
self.build_tree(['a'])
739
b.nick = 'test_properties_in_short_log'
740
wt.commit(message='add a',
741
timestamp=1132711707,
743
committer='Lorem Ipsum <test@example.com>',
744
authors=['John Doe <jdoe@example.com>'])
746
formatter = log.ShortLogFormatter(to_file=sio)
748
def trivial_custom_prop_handler(revision):
749
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'}
751
log.properties_handler_registry.register(
752
'trivial_custom_prop_handler',
753
trivial_custom_prop_handler)
754
log.show_log(b, formatter)
756
log.properties_handler_registry.remove(
757
'trivial_custom_prop_handler')
758
self.assertEqualDiff('''\
759
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
760
619
test_prop: test_value
623
wt.branch, log.ShortLogFormatter)
766
625
def test_error_in_properties_handler(self):
767
626
"""Log includes the custom properties returned by the registered
770
wt = self.make_branch_and_tree('.')
772
self.build_tree(['a'])
774
b.nick = 'test_author_log'
775
wt.commit(message='add a',
776
timestamp=1132711707,
778
committer='Lorem Ipsum <test@example.com>',
779
authors=['John Doe <jdoe@example.com>'],
780
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()
782
632
formatter = log.LongLogFormatter(to_file=sio)
784
def trivial_custom_prop_handler(revision):
785
raise StandardError("a test error")
633
def trivial_custom_prop_handler(revision):
634
raise StandardError("a test error")
787
log.properties_handler_registry.register(
788
'trivial_custom_prop_handler',
789
trivial_custom_prop_handler)
790
self.assertRaises(StandardError, log.show_log, b, formatter,)
792
log.properties_handler_registry.remove(
793
'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,)
795
641
def test_properties_handler_bad_argument(self):
796
wt = self.make_branch_and_tree('.')
798
self.build_tree(['a'])
800
b.nick = 'test_author_log'
801
wt.commit(message='add a',
802
timestamp=1132711707,
804
committer='Lorem Ipsum <test@example.com>',
805
authors=['John Doe <jdoe@example.com>'],
806
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()
808
645
formatter = log.LongLogFormatter(to_file=sio)
810
def bad_argument_prop_handler(revision):
811
return {'custom_prop_name':revision.properties['a_prop']}
813
log.properties_handler_registry.register(
814
'bad_argument_prop_handler',
815
bad_argument_prop_handler)
817
self.assertRaises(AttributeError, formatter.show_properties,
820
revision = b.repository.get_revision(b.last_revision())
821
formatter.show_properties(revision, '')
822
self.assertEqualDiff('''custom_prop_name: test_value\n''',
825
log.properties_handler_registry.remove(
826
'bad_argument_prop_handler')
829
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):
831
664
def test_long_verbose_log(self):
832
665
"""Verbose log includes changed files
836
wt = self.make_branch_and_tree('.')
838
self.build_tree(['a'])
840
# XXX: why does a longer nick show up?
841
b.nick = 'test_verbose_log'
842
wt.commit(message='add a',
843
timestamp=1132711707,
845
committer='Lorem Ipsum <test@example.com>')
846
logfile = file('out.tmp', 'w+')
847
formatter = log.LongLogFormatter(to_file=logfile, levels=1)
848
log.show_log(b, formatter, verbose=True)
851
log_contents = logfile.read()
852
self.assertEqualDiff('''\
669
wt = self.make_standard_commit('test_long_verbose_log', authors=[])
670
self.assertFormatterResult("""\
853
671
------------------------------------------------------------
855
673
committer: Lorem Ipsum <test@example.com>
856
branch nick: test_verbose_log
857
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))
865
685
def test_long_verbose_contain_deltas(self):
866
686
wt = self.make_branch_and_tree('parent')
867
687
self.build_tree(['parent/f1', 'parent/f2'])
868
688
wt.add(['f1','f2'])
869
wt.commit('first post')
870
self.run_bzr('branch parent child')
689
self.wt_commit(wt, 'first post')
690
child_wt = wt.bzrdir.sprout('child').open_workingtree()
871
691
os.unlink('child/f1')
872
file('child/f2', 'wb').write('hello\n')
873
self.run_bzr(['commit', '-m', 'removed f1 and modified f2',
876
self.run_bzr('merge ../child')
877
wt.commit('merge branch 1')
879
sio = self.make_utf8_encoded_stringio()
880
lf = log.LongLogFormatter(to_file=sio, levels=1)
881
log.show_log(b, lf, verbose=True)
882
the_log = normalize_log(sio.getvalue())
883
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("""\
884
697
------------------------------------------------------------
886
committer: Lorem Ipsum <test@example.com>
699
committer: Joe Foo <joe@foo.com>
887
700
branch nick: parent
701
timestamp: Tue 2005-11-22 00:00:02 +0000
934
745
committer: Joe Foo <joe@foo.com>
935
746
branch nick: test
936
timestamp: Mon 2005-11-21 09:24:15 -0600
747
timestamp: Tue 2005-11-22 00:00:00 +0000
938
749
simple log message
751
b, log.LongLogFormatter,
752
formatter_kwargs=dict(levels=1))
942
754
def test_long_author_in_log(self):
943
755
"""Log includes the author name if it's set in
944
756
the revision properties
946
wt = self.make_branch_and_tree('.')
948
self.build_tree(['a'])
950
b.nick = 'test_author_log'
951
wt.commit(message='add a',
952
timestamp=1132711707,
954
committer='Lorem Ipsum <test@example.com>',
955
authors=['John Doe <jdoe@example.com>'])
957
formatter = log.LongLogFormatter(to_file=sio, levels=1)
958
log.show_log(b, formatter)
959
self.assertEqualDiff('''\
758
wt = self.make_standard_commit('test_author_log')
759
self.assertFormatterResult("""\
960
760
------------------------------------------------------------
962
762
author: John Doe <jdoe@example.com>
963
763
committer: Lorem Ipsum <test@example.com>
964
764
branch nick: test_author_log
965
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))
971
772
def test_long_properties_in_log(self):
972
773
"""Log includes the custom properties returned by the registered
975
wt = self.make_branch_and_tree('.')
977
self.build_tree(['a'])
979
b.nick = 'test_properties_in_log'
980
wt.commit(message='add a',
981
timestamp=1132711707,
983
committer='Lorem Ipsum <test@example.com>',
984
authors=['John Doe <jdoe@example.com>'])
986
formatter = log.LongLogFormatter(to_file=sio, levels=1)
988
def trivial_custom_prop_handler(revision):
989
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'}
991
log.properties_handler_registry.register(
992
'trivial_custom_prop_handler',
993
trivial_custom_prop_handler)
994
log.show_log(b, formatter)
996
log.properties_handler_registry.remove(
997
'trivial_custom_prop_handler')
998
self.assertEqualDiff('''\
780
log.properties_handler_registry.register(
781
'trivial_custom_prop_handler',
782
trivial_custom_prop_handler)
783
self.assertFormatterResult("""\
999
784
------------------------------------------------------------
1001
786
test_prop: test_value
1002
787
author: John Doe <jdoe@example.com>
1003
788
committer: Lorem Ipsum <test@example.com>
1004
789
branch nick: test_properties_in_log
1005
timestamp: Wed 2005-11-23 12:08:27 +1000
790
timestamp: Tue 2005-11-22 00:00:00 +0000
1012
class TestLineLogFormatter(tests.TestCaseWithTransport):
794
wt.branch, log.LongLogFormatter,
795
formatter_kwargs=dict(levels=1))
798
class TestLineLogFormatter(TestCaseForLogFormatter):
1014
800
def test_line_log(self):
1015
801
"""Line log should show revno
1019
wt = self.make_branch_and_tree('.')
1021
self.build_tree(['a'])
1023
b.nick = 'test-line-log'
1024
wt.commit(message='add a',
1025
timestamp=1132711707,
1027
committer='Line-Log-Formatter Tester <test@line.log>')
1028
logfile = file('out.tmp', 'w+')
1029
formatter = log.LineLogFormatter(to_file=logfile)
1030
log.show_log(b, formatter)
1033
log_contents = logfile.read()
1034
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)
1037
813
def test_trailing_newlines(self):
1038
814
wt = self.make_branch_and_tree('.')
1039
b = make_commits_with_trailing_newlines(wt)
1040
sio = self.make_utf8_encoded_stringio()
1041
lf = log.LineLogFormatter(to_file=sio)
1043
self.assertEqualDiff("""\
1044
3: Joe Foo 2005-11-21 single line with trailing newline
1045
2: Joe Bar 2005-11-21 multiline
1046
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
1050
def _prepare_tree_with_merges(self, with_tags=False):
1051
wt = self.make_branch_and_memory_tree('.')
1053
self.addCleanup(wt.unlock)
1055
wt.commit('rev-1', rev_id='rev-1',
1056
timestamp=1132586655, timezone=36000,
1057
committer='Joe Foo <joe@foo.com>')
1058
wt.commit('rev-merged', rev_id='rev-2a',
1059
timestamp=1132586700, timezone=36000,
1060
committer='Joe Foo <joe@foo.com>')
1061
wt.set_parent_ids(['rev-1', 'rev-2a'])
1062
wt.branch.set_last_revision_info(1, 'rev-1')
1063
wt.commit('rev-2', rev_id='rev-2b',
1064
timestamp=1132586800, timezone=36000,
1065
committer='Joe Foo <joe@foo.com>')
1068
branch.tags.set_tag('v0.2', 'rev-2b')
1069
wt.commit('rev-3', rev_id='rev-3',
1070
timestamp=1132586900, timezone=36000,
1071
committer='Jane Foo <jane@foo.com>')
1072
branch.tags.set_tag('v1.0rc1', 'rev-3')
1073
branch.tags.set_tag('v1.0', 'rev-3')
821
b, log.LineLogFormatter)
1076
823
def test_line_log_single_merge_revision(self):
1077
824
wt = self._prepare_tree_with_merges()
1078
logfile = self.make_utf8_encoded_stringio()
1079
formatter = log.LineLogFormatter(to_file=logfile)
1080
825
revspec = revisionspec.RevisionSpec.from_string('1.1.1')
1082
rev = revspec.in_history(wtb)
1083
log.show_log(wtb, formatter, start_revision=rev, end_revision=rev)
1084
self.assertEqualDiff("""\
826
rev = revspec.in_history(wt.branch)
827
self.assertFormatterResult("""\
1085
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))
1089
833
def test_line_log_with_tags(self):
1090
834
wt = self._prepare_tree_with_merges(with_tags=True)
1091
logfile = self.make_utf8_encoded_stringio()
1092
formatter = log.LineLogFormatter(to_file=logfile)
1093
log.show_log(wt.branch, formatter)
1094
self.assertEqualDiff("""\
1095
3: Jane Foo 2005-11-22 {v1.0, v1.0rc1} rev-3
835
self.assertFormatterResult("""\
836
3: Joe Foo 2005-11-22 {v1.0, v1.0rc1} rev-3
1096
837
2: Joe Foo 2005-11-22 [merge] {v0.2} rev-2
1097
838
1: Joe Foo 2005-11-22 rev-1
1101
class TestLineLogFormatterWithMergeRevisions(tests.TestCaseWithTransport):
840
wt.branch, log.LineLogFormatter)
843
class TestLineLogFormatterWithMergeRevisions(TestCaseForLogFormatter):
1103
845
def test_line_merge_revs_log(self):
1104
846
"""Line log should show revno
1108
wt = self.make_branch_and_tree('.')
1110
self.build_tree(['a'])
1112
b.nick = 'test-line-log'
1113
wt.commit(message='add a',
1114
timestamp=1132711707,
1116
committer='Line-Log-Formatter Tester <test@line.log>')
1117
logfile = file('out.tmp', 'w+')
1118
formatter = log.LineLogFormatter(to_file=logfile, levels=0)
1119
log.show_log(b, formatter)
1122
log_contents = logfile.read()
1123
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)
1126
858
def test_line_merge_revs_log_single_merge_revision(self):
1127
wt = self.make_branch_and_memory_tree('.')
1129
self.addCleanup(wt.unlock)
1131
wt.commit('rev-1', rev_id='rev-1',
1132
timestamp=1132586655, timezone=36000,
1133
committer='Joe Foo <joe@foo.com>')
1134
wt.commit('rev-merged', rev_id='rev-2a',
1135
timestamp=1132586700, timezone=36000,
1136
committer='Joe Foo <joe@foo.com>')
1137
wt.set_parent_ids(['rev-1', 'rev-2a'])
1138
wt.branch.set_last_revision_info(1, 'rev-1')
1139
wt.commit('rev-2', rev_id='rev-2b',
1140
timestamp=1132586800, timezone=36000,
1141
committer='Joe Foo <joe@foo.com>')
1142
logfile = self.make_utf8_encoded_stringio()
1143
formatter = log.LineLogFormatter(to_file=logfile, levels=0)
859
wt = self._prepare_tree_with_merges()
1144
860
revspec = revisionspec.RevisionSpec.from_string('1.1.1')
1146
rev = revspec.in_history(wtb)
1147
log.show_log(wtb, formatter, start_revision=rev, end_revision=rev)
1148
self.assertEqualDiff("""\
861
rev = revspec.in_history(wt.branch)
862
self.assertFormatterResult("""\
1149
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))
1153
869
def test_line_merge_revs_log_with_merges(self):
1154
wt = self.make_branch_and_memory_tree('.')
1156
self.addCleanup(wt.unlock)
1158
wt.commit('rev-1', rev_id='rev-1',
1159
timestamp=1132586655, timezone=36000,
1160
committer='Joe Foo <joe@foo.com>')
1161
wt.commit('rev-merged', rev_id='rev-2a',
1162
timestamp=1132586700, timezone=36000,
1163
committer='Joe Foo <joe@foo.com>')
1164
wt.set_parent_ids(['rev-1', 'rev-2a'])
1165
wt.branch.set_last_revision_info(1, 'rev-1')
1166
wt.commit('rev-2', rev_id='rev-2b',
1167
timestamp=1132586800, timezone=36000,
1168
committer='Joe Foo <joe@foo.com>')
1169
logfile = self.make_utf8_encoded_stringio()
1170
formatter = log.LineLogFormatter(to_file=logfile, levels=0)
1171
log.show_log(wt.branch, formatter)
1172
self.assertEqualDiff("""\
870
wt = self._prepare_tree_with_merges()
871
self.assertFormatterResult("""\
1173
872
2: Joe Foo 2005-11-22 [merge] rev-2
1174
873
1.1.1: Joe Foo 2005-11-22 rev-merged
1175
874
1: Joe Foo 2005-11-22 rev-1
1179
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)
1181
886
def make_tree_with_commits(self):
1182
887
"""Create a tree with well-known revision ids"""
1183
888
wt = self.make_branch_and_tree('tree1')
1184
wt.commit('commit one', rev_id='1')
1185
wt.commit('commit two', rev_id='2')
1186
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')
1187
892
mainline_revs = [None, '1', '2', '3']
1188
893
rev_nos = {'1': 1, '2': 2, '3': 3}
1189
894
return mainline_revs, rev_nos, wt
1522
1237
class TestLogFormatter(tests.TestCase):
1240
super(TestLogFormatter, self).setUp()
1241
self.rev = revision.Revision('a-id')
1242
self.lf = log.LogFormatter(None)
1524
1244
def test_short_committer(self):
1525
rev = revision.Revision('a-id')
1526
rev.committer = 'John Doe <jdoe@example.com>'
1527
lf = log.LogFormatter(None)
1528
self.assertEqual('John Doe', lf.short_committer(rev))
1529
rev.committer = 'John Smith <jsmith@example.com>'
1530
self.assertEqual('John Smith', lf.short_committer(rev))
1531
rev.committer = 'John Smith'
1532
self.assertEqual('John Smith', lf.short_committer(rev))
1533
rev.committer = 'jsmith@example.com'
1534
self.assertEqual('jsmith@example.com', lf.short_committer(rev))
1535
rev.committer = '<jsmith@example.com>'
1536
self.assertEqual('jsmith@example.com', lf.short_committer(rev))
1537
rev.committer = 'John Smith jsmith@example.com'
1538
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')
1540
1256
def test_short_author(self):
1541
rev = revision.Revision('a-id')
1542
rev.committer = 'John Doe <jdoe@example.com>'
1543
lf = log.LogFormatter(None)
1544
self.assertEqual('John Doe', lf.short_author(rev))
1545
rev.properties['author'] = 'John Smith <jsmith@example.com>'
1546
self.assertEqual('John Smith', lf.short_author(rev))
1547
rev.properties['author'] = 'John Smith'
1548
self.assertEqual('John Smith', lf.short_author(rev))
1549
rev.properties['author'] = 'jsmith@example.com'
1550
self.assertEqual('jsmith@example.com', lf.short_author(rev))
1551
rev.properties['author'] = '<jsmith@example.com>'
1552
self.assertEqual('jsmith@example.com', lf.short_author(rev))
1553
rev.properties['author'] = 'John Smith jsmith@example.com'
1554
self.assertEqual('John Smith', lf.short_author(rev))
1555
del rev.properties['author']
1556
rev.properties['authors'] = ('John Smith <jsmith@example.com>\n'
1557
'Jane Rey <jrey@example.com>')
1558
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))
1561
1277
class TestReverseByDepth(tests.TestCase):
1707
1423
log.show_branch_change(tree.branch, s, 3, '3b')
1708
1424
self.assertContainsRe(s.getvalue(), 'Removed Revisions:')
1709
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')