~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_log.py

  • Committer: Ian Clatworthy
  • Date: 2010-02-19 03:02:07 UTC
  • mto: (4797.23.1 integration-2.1)
  • mto: This revision was merged to the branch mainline in revision 5055.
  • Revision ID: ian.clatworthy@canonical.com-20100219030207-zpbzx021zavx4sqt
What's New in 2.1 - a summary of changes since 2.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005, 2006, 2007 Canonical Ltd
 
1
# Copyright (C) 2005-2010 Canonical Ltd
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
27
27
    )
28
28
 
29
29
 
30
 
class TestCaseWithoutPropsHandler(tests.TestCaseWithTransport):
 
30
class TestCaseForLogFormatter(tests.TestCaseWithTransport):
31
31
 
32
32
    def setUp(self):
33
 
        super(TestCaseWithoutPropsHandler, self).setUp()
 
33
        super(TestCaseForLogFormatter, self).setUp()
34
34
        # keep a reference to the "current" custom prop. handler registry
35
35
        self.properties_handler_registry = log.properties_handler_registry
36
36
        # Use a clean registry for log
40
40
            log.properties_handler_registry = self.properties_handler_registry
41
41
        self.addCleanup(restore)
42
42
 
 
43
    def assertFormatterResult(self, result, branch, formatter_class,
 
44
                              formatter_kwargs=None, show_log_kwargs=None,
 
45
                              normalize=False):
 
46
        logfile = self.make_utf8_encoded_stringio()
 
47
        if formatter_kwargs is None:
 
48
            formatter_kwargs = {}
 
49
        formatter = formatter_class(to_file=logfile, **formatter_kwargs)
 
50
        if show_log_kwargs is None:
 
51
            show_log_kwargs = {}
 
52
        log.show_log(branch, formatter, **show_log_kwargs)
 
53
        log_content = logfile.getvalue()
 
54
        if normalize:
 
55
            log_content = normalize_log(log_content)
 
56
        self.assertEqualDiff(result, log_content)
 
57
 
 
58
    def make_standard_commit(self, branch_nick, **kwargs):
 
59
        wt = self.make_branch_and_tree('.')
 
60
        wt.lock_write()
 
61
        self.addCleanup(wt.unlock)
 
62
        self.build_tree(['a'])
 
63
        wt.add(['a'])
 
64
        wt.branch.nick = branch_nick
 
65
        kwargs = dict(kwargs)
 
66
        kwargs.setdefault('message', 'add a')
 
67
        kwargs.setdefault('timestamp', 1132711707)
 
68
        kwargs.setdefault('timezone', 36000)
 
69
        kwargs.setdefault('committer', 'Lorem Ipsum <test@example.com>')
 
70
        kwargs.setdefault('authors', ['John Doe <jdoe@example.com>'])
 
71
        wt.commit(**kwargs)
 
72
        return wt
 
73
 
 
74
    def _prepare_tree_with_merges(self, with_tags=False):
 
75
        wt = self.make_branch_and_memory_tree('.')
 
76
        wt.lock_write()
 
77
        self.addCleanup(wt.unlock)
 
78
        wt.add('')
 
79
        wt.commit('rev-1', rev_id='rev-1',
 
80
                  timestamp=1132586655, timezone=36000,
 
81
                  committer='Joe Foo <joe@foo.com>')
 
82
        wt.commit('rev-merged', rev_id='rev-2a',
 
83
                  timestamp=1132586700, timezone=36000,
 
84
                  committer='Joe Foo <joe@foo.com>')
 
85
        wt.set_parent_ids(['rev-1', 'rev-2a'])
 
86
        wt.branch.set_last_revision_info(1, 'rev-1')
 
87
        wt.commit('rev-2', rev_id='rev-2b',
 
88
                  timestamp=1132586800, timezone=36000,
 
89
                  committer='Joe Foo <joe@foo.com>')
 
90
        if with_tags:
 
91
            branch = wt.branch
 
92
            branch.tags.set_tag('v0.2', 'rev-2b')
 
93
            wt.commit('rev-3', rev_id='rev-3',
 
94
                      timestamp=1132586900, timezone=36000,
 
95
                      committer='Jane Foo <jane@foo.com>')
 
96
            branch.tags.set_tag('v1.0rc1', 'rev-3')
 
97
            branch.tags.set_tag('v1.0', 'rev-3')
 
98
        return wt
 
99
 
 
100
        
 
101
 
43
102
 
44
103
class LogCatcher(log.LogFormatter):
45
104
    """Pull log messages into a list rather than displaying them.
142
201
        lf = LogCatcher()
143
202
        log.show_log(wt.branch, lf, verbose=True)
144
203
        committed_msg = lf.revisions[0].rev.message
145
 
        self.assertNotEqual(msg, committed_msg)
146
 
        self.assertTrue(len(committed_msg) > len(msg))
 
204
        if wt.branch.repository._serializer.squashes_xml_invalid_characters:
 
205
            self.assertNotEqual(msg, committed_msg)
 
206
            self.assertTrue(len(committed_msg) > len(msg))
 
207
        else:
 
208
            self.assertEqual(msg, committed_msg)
147
209
 
148
210
    def test_commit_message_without_control_chars(self):
149
211
        wt = self.make_branch_and_tree('.')
239
301
    return ''.join(lines)
240
302
 
241
303
 
242
 
class TestShortLogFormatter(tests.TestCaseWithTransport):
 
304
class TestShortLogFormatter(TestCaseForLogFormatter):
243
305
 
244
306
    def test_trailing_newlines(self):
245
307
        wt = self.make_branch_and_tree('.')
246
308
        b = make_commits_with_trailing_newlines(wt)
247
 
        sio = self.make_utf8_encoded_stringio()
248
 
        lf = log.ShortLogFormatter(to_file=sio)
249
 
        log.show_log(b, lf)
250
 
        self.assertEqualDiff("""\
 
309
        self.assertFormatterResult("""\
251
310
    3 Joe Foo\t2005-11-21
252
311
      single line with trailing newline
253
312
 
260
319
      simple log message
261
320
 
262
321
""",
263
 
                             sio.getvalue())
264
 
 
265
 
    def _prepare_tree_with_merges(self, with_tags=False):
266
 
        wt = self.make_branch_and_memory_tree('.')
267
 
        wt.lock_write()
268
 
        self.addCleanup(wt.unlock)
269
 
        wt.add('')
270
 
        wt.commit('rev-1', rev_id='rev-1',
271
 
                  timestamp=1132586655, timezone=36000,
272
 
                  committer='Joe Foo <joe@foo.com>')
273
 
        wt.commit('rev-merged', rev_id='rev-2a',
274
 
                  timestamp=1132586700, timezone=36000,
275
 
                  committer='Joe Foo <joe@foo.com>')
276
 
        wt.set_parent_ids(['rev-1', 'rev-2a'])
277
 
        wt.branch.set_last_revision_info(1, 'rev-1')
278
 
        wt.commit('rev-2', rev_id='rev-2b',
279
 
                  timestamp=1132586800, timezone=36000,
280
 
                  committer='Joe Foo <joe@foo.com>')
281
 
        if with_tags:
282
 
            branch = wt.branch
283
 
            branch.tags.set_tag('v0.2', 'rev-2b')
284
 
            wt.commit('rev-3', rev_id='rev-3',
285
 
                      timestamp=1132586900, timezone=36000,
286
 
                      committer='Jane Foo <jane@foo.com>')
287
 
            branch.tags.set_tag('v1.0rc1', 'rev-3')
288
 
            branch.tags.set_tag('v1.0', 'rev-3')
289
 
        return wt
 
322
            b, log.ShortLogFormatter)
290
323
 
291
324
    def test_short_log_with_merges(self):
292
325
        wt = self._prepare_tree_with_merges()
293
 
        logfile = self.make_utf8_encoded_stringio()
294
 
        formatter = log.ShortLogFormatter(to_file=logfile)
295
 
        log.show_log(wt.branch, formatter)
296
 
        self.assertEqualDiff("""\
 
326
        self.assertFormatterResult("""\
297
327
    2 Joe Foo\t2005-11-22 [merge]
298
328
      rev-2
299
329
 
301
331
      rev-1
302
332
 
303
333
""",
304
 
                             logfile.getvalue())
 
334
            wt.branch, log.ShortLogFormatter)
305
335
 
306
336
    def test_short_log_with_merges_and_advice(self):
307
337
        wt = self._prepare_tree_with_merges()
308
 
        logfile = self.make_utf8_encoded_stringio()
309
 
        formatter = log.ShortLogFormatter(to_file=logfile,
310
 
            show_advice=True)
311
 
        log.show_log(wt.branch, formatter)
312
 
        self.assertEqualDiff("""\
 
338
        self.assertFormatterResult("""\
313
339
    2 Joe Foo\t2005-11-22 [merge]
314
340
      rev-2
315
341
 
318
344
 
319
345
Use --include-merges or -n0 to see merged revisions.
320
346
""",
321
 
                             logfile.getvalue())
 
347
            wt.branch, log.ShortLogFormatter,
 
348
            formatter_kwargs=dict(show_advice=True))
322
349
 
323
350
    def test_short_log_with_merges_and_range(self):
324
351
        wt = self.make_branch_and_memory_tree('.')
344
371
        wt.commit('rev-3b', rev_id='rev-3b',
345
372
                  timestamp=1132586800, timezone=36000,
346
373
                  committer='Joe Foo <joe@foo.com>')
347
 
        logfile = self.make_utf8_encoded_stringio()
348
 
        formatter = log.ShortLogFormatter(to_file=logfile)
349
 
        log.show_log(wt.branch, formatter,
350
 
            start_revision=2, end_revision=3)
351
 
        self.assertEqualDiff("""\
 
374
        self.assertFormatterResult("""\
352
375
    3 Joe Foo\t2005-11-22 [merge]
353
376
      rev-3b
354
377
 
356
379
      rev-2b
357
380
 
358
381
""",
359
 
                             logfile.getvalue())
 
382
            wt.branch, log.ShortLogFormatter,
 
383
            show_log_kwargs=dict(start_revision=2, end_revision=3))
360
384
 
361
385
    def test_short_log_with_tags(self):
362
386
        wt = self._prepare_tree_with_merges(with_tags=True)
363
 
        logfile = self.make_utf8_encoded_stringio()
364
 
        formatter = log.ShortLogFormatter(to_file=logfile)
365
 
        log.show_log(wt.branch, formatter)
366
 
        self.assertEqualDiff("""\
 
387
        self.assertFormatterResult("""\
367
388
    3 Jane Foo\t2005-11-22 {v1.0, v1.0rc1}
368
389
      rev-3
369
390
 
374
395
      rev-1
375
396
 
376
397
""",
377
 
                             logfile.getvalue())
 
398
            wt.branch, log.ShortLogFormatter)
378
399
 
379
400
    def test_short_log_single_merge_revision(self):
380
401
        wt = self.make_branch_and_memory_tree('.')
392
413
        wt.commit('rev-2', rev_id='rev-2b',
393
414
                  timestamp=1132586800, timezone=36000,
394
415
                  committer='Joe Foo <joe@foo.com>')
395
 
        logfile = self.make_utf8_encoded_stringio()
396
 
        formatter = log.ShortLogFormatter(to_file=logfile)
397
416
        revspec = revisionspec.RevisionSpec.from_string('1.1.1')
398
 
        wtb = wt.branch
399
 
        rev = revspec.in_history(wtb)
400
 
        log.show_log(wtb, formatter, start_revision=rev, end_revision=rev)
401
 
        self.assertEqualDiff("""\
 
417
        rev = revspec.in_history(wt.branch)
 
418
        self.assertFormatterResult("""\
402
419
      1.1.1 Joe Foo\t2005-11-22
403
420
            rev-merged
404
421
 
405
422
""",
406
 
                             logfile.getvalue())
407
 
 
408
 
 
409
 
class TestShortLogFormatterWithMergeRevisions(tests.TestCaseWithTransport):
 
423
            wt.branch, log.ShortLogFormatter,
 
424
            show_log_kwargs=dict(start_revision=rev, end_revision=rev))
 
425
 
 
426
 
 
427
class TestShortLogFormatterWithMergeRevisions(TestCaseForLogFormatter):
410
428
 
411
429
    def test_short_merge_revs_log_with_merges(self):
412
430
        wt = self.make_branch_and_memory_tree('.')
424
442
        wt.commit('rev-2', rev_id='rev-2b',
425
443
                  timestamp=1132586800, timezone=36000,
426
444
                  committer='Joe Foo <joe@foo.com>')
427
 
        logfile = self.make_utf8_encoded_stringio()
428
 
        formatter = log.ShortLogFormatter(to_file=logfile, levels=0)
429
 
        log.show_log(wt.branch, formatter)
430
445
        # Note that the 1.1.1 indenting is in fact correct given that
431
446
        # the revision numbers are right justified within 5 characters
432
447
        # for mainline revnos and 9 characters for dotted revnos.
433
 
        self.assertEqualDiff("""\
 
448
        self.assertFormatterResult("""\
434
449
    2 Joe Foo\t2005-11-22 [merge]
435
450
      rev-2
436
451
 
441
456
      rev-1
442
457
 
443
458
""",
444
 
                             logfile.getvalue())
 
459
            wt.branch, log.ShortLogFormatter,
 
460
            formatter_kwargs=dict(levels=0))
445
461
 
446
462
    def test_short_merge_revs_log_single_merge_revision(self):
447
463
        wt = self.make_branch_and_memory_tree('.')
459
475
        wt.commit('rev-2', rev_id='rev-2b',
460
476
                  timestamp=1132586800, timezone=36000,
461
477
                  committer='Joe Foo <joe@foo.com>')
462
 
        logfile = self.make_utf8_encoded_stringio()
463
 
        formatter = log.ShortLogFormatter(to_file=logfile, levels=0)
464
478
        revspec = revisionspec.RevisionSpec.from_string('1.1.1')
465
 
        wtb = wt.branch
466
 
        rev = revspec.in_history(wtb)
467
 
        log.show_log(wtb, formatter, start_revision=rev, end_revision=rev)
468
 
        self.assertEqualDiff("""\
 
479
        rev = revspec.in_history(wt.branch)
 
480
        self.assertFormatterResult("""\
469
481
      1.1.1 Joe Foo\t2005-11-22
470
482
            rev-merged
471
483
 
472
484
""",
473
 
                             logfile.getvalue())
474
 
 
475
 
 
476
 
class TestLongLogFormatter(TestCaseWithoutPropsHandler):
 
485
            wt.branch, log.ShortLogFormatter,
 
486
            formatter_kwargs=dict(levels=0),
 
487
            show_log_kwargs=dict(start_revision=rev, end_revision=rev))
 
488
 
 
489
 
 
490
class TestLongLogFormatter(TestCaseForLogFormatter):
477
491
 
478
492
    def test_verbose_log(self):
479
493
        """Verbose log includes changed files
480
494
 
481
495
        bug #4676
482
496
        """
483
 
        wt = self.make_branch_and_tree('.')
484
 
        b = wt.branch
485
 
        self.build_tree(['a'])
486
 
        wt.add('a')
487
 
        # XXX: why does a longer nick show up?
488
 
        b.nick = 'test_verbose_log'
489
 
        wt.commit(message='add a',
490
 
                  timestamp=1132711707,
491
 
                  timezone=36000,
492
 
                  committer='Lorem Ipsum <test@example.com>')
493
 
        logfile = file('out.tmp', 'w+')
494
 
        formatter = log.LongLogFormatter(to_file=logfile)
495
 
        log.show_log(b, formatter, verbose=True)
496
 
        logfile.flush()
497
 
        logfile.seek(0)
498
 
        log_contents = logfile.read()
499
 
        self.assertEqualDiff('''\
 
497
        wt = self.make_standard_commit('test_verbose_log', authors=[])
 
498
        self.assertFormatterResult('''\
500
499
------------------------------------------------------------
501
500
revno: 1
502
501
committer: Lorem Ipsum <test@example.com>
507
506
added:
508
507
  a
509
508
''',
510
 
                             log_contents)
 
509
            wt.branch, log.LongLogFormatter,
 
510
            show_log_kwargs=dict(verbose=True))
511
511
 
512
512
    def test_merges_are_indented_by_level(self):
513
513
        wt = self.make_branch_and_tree('parent')
523
523
        os.chdir('../parent')
524
524
        self.run_bzr('merge ../child')
525
525
        wt.commit('merge branch 1')
526
 
        b = wt.branch
527
 
        sio = self.make_utf8_encoded_stringio()
528
 
        lf = log.LongLogFormatter(to_file=sio, levels=0)
529
 
        log.show_log(b, lf, verbose=True)
530
 
        the_log = normalize_log(sio.getvalue())
531
 
        self.assertEqualDiff("""\
 
526
        self.assertFormatterResult("""\
532
527
------------------------------------------------------------
533
528
revno: 2 [merge]
534
529
committer: Lorem Ipsum <test@example.com>
565
560
message:
566
561
  first post
567
562
""",
568
 
                             the_log)
 
563
            wt.branch, log.LongLogFormatter,
 
564
            formatter_kwargs=dict(levels=0),
 
565
            show_log_kwargs=dict(verbose=True),
 
566
            normalize=True)
569
567
 
570
568
    def test_verbose_merge_revisions_contain_deltas(self):
571
569
        wt = self.make_branch_and_tree('parent')
580
578
        os.chdir('parent')
581
579
        self.run_bzr('merge ../child')
582
580
        wt.commit('merge branch 1')
583
 
        b = wt.branch
584
 
        sio = self.make_utf8_encoded_stringio()
585
 
        lf = log.LongLogFormatter(to_file=sio, levels=0)
586
 
        log.show_log(b, lf, verbose=True)
587
 
        the_log = normalize_log(sio.getvalue())
588
 
        self.assertEqualDiff("""\
 
581
        self.assertFormatterResult("""\
589
582
------------------------------------------------------------
590
583
revno: 2 [merge]
591
584
committer: Lorem Ipsum <test@example.com>
619
612
  f1
620
613
  f2
621
614
""",
622
 
                             the_log)
 
615
            wt.branch, log.LongLogFormatter,
 
616
            formatter_kwargs=dict(levels=0),
 
617
            show_log_kwargs=dict(verbose=True),
 
618
            normalize=True)
623
619
 
624
620
    def test_trailing_newlines(self):
625
621
        wt = self.make_branch_and_tree('.')
626
622
        b = make_commits_with_trailing_newlines(wt)
627
 
        sio = self.make_utf8_encoded_stringio()
628
 
        lf = log.LongLogFormatter(to_file=sio)
629
 
        log.show_log(b, lf)
630
 
        self.assertEqualDiff("""\
 
623
        self.assertFormatterResult("""\
631
624
------------------------------------------------------------
632
625
revno: 3
633
626
committer: Joe Foo <joe@foo.com>
653
646
message:
654
647
  simple log message
655
648
""",
656
 
                             sio.getvalue())
 
649
        b, log.LongLogFormatter)
657
650
 
658
651
    def test_author_in_log(self):
659
652
        """Log includes the author name if it's set in
660
653
        the revision properties
661
654
        """
662
 
        wt = self.make_branch_and_tree('.')
663
 
        b = wt.branch
664
 
        self.build_tree(['a'])
665
 
        wt.add('a')
666
 
        b.nick = 'test_author_log'
667
 
        wt.commit(message='add a',
668
 
                  timestamp=1132711707,
669
 
                  timezone=36000,
670
 
                  committer='Lorem Ipsum <test@example.com>',
671
 
                  authors=['John Doe <jdoe@example.com>',
672
 
                           'Jane Rey <jrey@example.com>'])
673
 
        sio = StringIO()
674
 
        formatter = log.LongLogFormatter(to_file=sio)
675
 
        log.show_log(b, formatter)
676
 
        self.assertEqualDiff('''\
 
655
        wt = self.make_standard_commit('test_author_log',
 
656
            authors=['John Doe <jdoe@example.com>',
 
657
                     'Jane Rey <jrey@example.com>'])
 
658
        self.assertFormatterResult("""\
677
659
------------------------------------------------------------
678
660
revno: 1
679
661
author: John Doe <jdoe@example.com>, Jane Rey <jrey@example.com>
682
664
timestamp: Wed 2005-11-23 12:08:27 +1000
683
665
message:
684
666
  add a
685
 
''',
686
 
                             sio.getvalue())
 
667
""",
 
668
        wt.branch, log.LongLogFormatter)
687
669
 
688
670
    def test_properties_in_log(self):
689
671
        """Log includes the custom properties returned by the registered
690
672
        handlers.
691
673
        """
692
 
        wt = self.make_branch_and_tree('.')
693
 
        b = wt.branch
694
 
        self.build_tree(['a'])
695
 
        wt.add('a')
696
 
        b.nick = 'test_properties_in_log'
697
 
        wt.commit(message='add a',
698
 
                  timestamp=1132711707,
699
 
                  timezone=36000,
700
 
                  committer='Lorem Ipsum <test@example.com>',
701
 
                  authors=['John Doe <jdoe@example.com>'])
702
 
        sio = StringIO()
703
 
        formatter = log.LongLogFormatter(to_file=sio)
704
 
        try:
705
 
            def trivial_custom_prop_handler(revision):
706
 
                return {'test_prop':'test_value'}
 
674
        wt = self.make_standard_commit('test_properties_in_log')
 
675
        def trivial_custom_prop_handler(revision):
 
676
            return {'test_prop':'test_value'}
707
677
 
708
 
            log.properties_handler_registry.register(
709
 
                'trivial_custom_prop_handler',
710
 
                trivial_custom_prop_handler)
711
 
            log.show_log(b, formatter)
712
 
        finally:
713
 
            log.properties_handler_registry.remove(
714
 
                'trivial_custom_prop_handler')
715
 
            self.assertEqualDiff('''\
 
678
        # Cleaned up in setUp()
 
679
        log.properties_handler_registry.register(
 
680
            'trivial_custom_prop_handler',
 
681
            trivial_custom_prop_handler)
 
682
        self.assertFormatterResult("""\
716
683
------------------------------------------------------------
717
684
revno: 1
718
685
test_prop: test_value
722
689
timestamp: Wed 2005-11-23 12:08:27 +1000
723
690
message:
724
691
  add a
725
 
''',
726
 
                                 sio.getvalue())
 
692
""",
 
693
            wt.branch, log.LongLogFormatter)
727
694
 
728
695
    def test_properties_in_short_log(self):
729
696
        """Log includes the custom properties returned by the registered
730
697
        handlers.
731
698
        """
732
 
        wt = self.make_branch_and_tree('.')
733
 
        b = wt.branch
734
 
        self.build_tree(['a'])
735
 
        wt.add('a')
736
 
        b.nick = 'test_properties_in_short_log'
737
 
        wt.commit(message='add a',
738
 
                  timestamp=1132711707,
739
 
                  timezone=36000,
740
 
                  committer='Lorem Ipsum <test@example.com>',
741
 
                  authors=['John Doe <jdoe@example.com>'])
742
 
        sio = StringIO()
743
 
        formatter = log.ShortLogFormatter(to_file=sio)
744
 
        try:
745
 
            def trivial_custom_prop_handler(revision):
746
 
                return {'test_prop':'test_value'}
 
699
        wt = self.make_standard_commit('test_properties_in_short_log')
 
700
        def trivial_custom_prop_handler(revision):
 
701
            return {'test_prop':'test_value'}
747
702
 
748
 
            log.properties_handler_registry.register(
749
 
                'trivial_custom_prop_handler',
750
 
                trivial_custom_prop_handler)
751
 
            log.show_log(b, formatter)
752
 
        finally:
753
 
            log.properties_handler_registry.remove(
754
 
                'trivial_custom_prop_handler')
755
 
            self.assertEqualDiff('''\
 
703
        log.properties_handler_registry.register(
 
704
            'trivial_custom_prop_handler',
 
705
            trivial_custom_prop_handler)
 
706
        self.assertFormatterResult("""\
756
707
    1 John Doe\t2005-11-23
757
708
      test_prop: test_value
758
709
      add a
759
710
 
760
 
''',
761
 
                                 sio.getvalue())
 
711
""",
 
712
            wt.branch, log.ShortLogFormatter)
762
713
 
763
714
    def test_error_in_properties_handler(self):
764
715
        """Log includes the custom properties returned by the registered
765
716
        handlers.
766
717
        """
767
 
        wt = self.make_branch_and_tree('.')
768
 
        b = wt.branch
769
 
        self.build_tree(['a'])
770
 
        wt.add('a')
771
 
        b.nick = 'test_author_log'
772
 
        wt.commit(message='add a',
773
 
                  timestamp=1132711707,
774
 
                  timezone=36000,
775
 
                  committer='Lorem Ipsum <test@example.com>',
776
 
                  authors=['John Doe <jdoe@example.com>'],
777
 
                  revprops={'first_prop':'first_value'})
778
 
        sio = StringIO()
 
718
        wt = self.make_standard_commit('error_in_properties_handler',
 
719
            revprops={'first_prop':'first_value'})
 
720
        sio = self.make_utf8_encoded_stringio()
779
721
        formatter = log.LongLogFormatter(to_file=sio)
780
 
        try:
781
 
            def trivial_custom_prop_handler(revision):
782
 
                raise StandardError("a test error")
 
722
        def trivial_custom_prop_handler(revision):
 
723
            raise StandardError("a test error")
783
724
 
784
 
            log.properties_handler_registry.register(
785
 
                'trivial_custom_prop_handler',
786
 
                trivial_custom_prop_handler)
787
 
            self.assertRaises(StandardError, log.show_log, b, formatter,)
788
 
        finally:
789
 
            log.properties_handler_registry.remove(
790
 
                'trivial_custom_prop_handler')
 
725
        log.properties_handler_registry.register(
 
726
            'trivial_custom_prop_handler',
 
727
            trivial_custom_prop_handler)
 
728
        self.assertRaises(StandardError, log.show_log, wt.branch, formatter,)
791
729
 
792
730
    def test_properties_handler_bad_argument(self):
793
 
        wt = self.make_branch_and_tree('.')
794
 
        b = wt.branch
795
 
        self.build_tree(['a'])
796
 
        wt.add('a')
797
 
        b.nick = 'test_author_log'
798
 
        wt.commit(message='add a',
799
 
                  timestamp=1132711707,
800
 
                  timezone=36000,
801
 
                  committer='Lorem Ipsum <test@example.com>',
802
 
                  authors=['John Doe <jdoe@example.com>'],
803
 
                  revprops={'a_prop':'test_value'})
804
 
        sio = StringIO()
 
731
        wt = self.make_standard_commit('bad_argument',
 
732
              revprops={'a_prop':'test_value'})
 
733
        sio = self.make_utf8_encoded_stringio()
805
734
        formatter = log.LongLogFormatter(to_file=sio)
806
 
        try:
807
 
            def bad_argument_prop_handler(revision):
808
 
                return {'custom_prop_name':revision.properties['a_prop']}
809
 
 
810
 
            log.properties_handler_registry.register(
811
 
                'bad_argument_prop_handler',
812
 
                bad_argument_prop_handler)
813
 
 
814
 
            self.assertRaises(AttributeError, formatter.show_properties,
815
 
                              'a revision', '')
816
 
 
817
 
            revision = b.repository.get_revision(b.last_revision())
818
 
            formatter.show_properties(revision, '')
819
 
            self.assertEqualDiff('''custom_prop_name: test_value\n''',
820
 
                                 sio.getvalue())
821
 
        finally:
822
 
            log.properties_handler_registry.remove(
823
 
                'bad_argument_prop_handler')
824
 
 
825
 
 
826
 
class TestLongLogFormatterWithoutMergeRevisions(TestCaseWithoutPropsHandler):
 
735
        def bad_argument_prop_handler(revision):
 
736
            return {'custom_prop_name':revision.properties['a_prop']}
 
737
 
 
738
        log.properties_handler_registry.register(
 
739
            'bad_argument_prop_handler',
 
740
            bad_argument_prop_handler)
 
741
 
 
742
        self.assertRaises(AttributeError, formatter.show_properties,
 
743
                          'a revision', '')
 
744
 
 
745
        revision = wt.branch.repository.get_revision(wt.branch.last_revision())
 
746
        formatter.show_properties(revision, '')
 
747
        self.assertEqualDiff('''custom_prop_name: test_value\n''',
 
748
                             sio.getvalue())
 
749
 
 
750
 
 
751
class TestLongLogFormatterWithoutMergeRevisions(TestCaseForLogFormatter):
827
752
 
828
753
    def test_long_verbose_log(self):
829
754
        """Verbose log includes changed files
830
755
 
831
756
        bug #4676
832
757
        """
833
 
        wt = self.make_branch_and_tree('.')
834
 
        b = wt.branch
835
 
        self.build_tree(['a'])
836
 
        wt.add('a')
837
 
        # XXX: why does a longer nick show up?
838
 
        b.nick = 'test_verbose_log'
839
 
        wt.commit(message='add a',
840
 
                  timestamp=1132711707,
841
 
                  timezone=36000,
842
 
                  committer='Lorem Ipsum <test@example.com>')
843
 
        logfile = file('out.tmp', 'w+')
844
 
        formatter = log.LongLogFormatter(to_file=logfile, levels=1)
845
 
        log.show_log(b, formatter, verbose=True)
846
 
        logfile.flush()
847
 
        logfile.seek(0)
848
 
        log_contents = logfile.read()
849
 
        self.assertEqualDiff('''\
 
758
        wt = self.make_standard_commit('test_long_verbose_log', authors=[])
 
759
        self.assertFormatterResult("""\
850
760
------------------------------------------------------------
851
761
revno: 1
852
762
committer: Lorem Ipsum <test@example.com>
853
 
branch nick: test_verbose_log
 
763
branch nick: test_long_verbose_log
854
764
timestamp: Wed 2005-11-23 12:08:27 +1000
855
765
message:
856
766
  add a
857
767
added:
858
768
  a
859
 
''',
860
 
                             log_contents)
 
769
""",
 
770
            wt.branch, log.LongLogFormatter,
 
771
            formatter_kwargs=dict(levels=1),
 
772
            show_log_kwargs=dict(verbose=True))
861
773
 
862
774
    def test_long_verbose_contain_deltas(self):
863
775
        wt = self.make_branch_and_tree('parent')
864
776
        self.build_tree(['parent/f1', 'parent/f2'])
865
777
        wt.add(['f1','f2'])
866
778
        wt.commit('first post')
867
 
        self.run_bzr('branch parent child')
 
779
        child_wt = wt.bzrdir.sprout('child').open_workingtree()
868
780
        os.unlink('child/f1')
869
 
        file('child/f2', 'wb').write('hello\n')
870
 
        self.run_bzr(['commit', '-m', 'removed f1 and modified f2',
871
 
            'child'])
872
 
        os.chdir('parent')
873
 
        self.run_bzr('merge ../child')
 
781
        self.build_tree_contents([('child/f2', 'hello\n')])
 
782
        child_wt.commit('removed f1 and modified f2')
 
783
        wt.merge_from_branch(child_wt.branch)
874
784
        wt.commit('merge branch 1')
875
 
        b = wt.branch
876
 
        sio = self.make_utf8_encoded_stringio()
877
 
        lf = log.LongLogFormatter(to_file=sio, levels=1)
878
 
        log.show_log(b, lf, verbose=True)
879
 
        the_log = normalize_log(sio.getvalue())
880
 
        self.assertEqualDiff("""\
 
785
        self.assertFormatterResult("""\
881
786
------------------------------------------------------------
882
787
revno: 2 [merge]
883
788
committer: Lorem Ipsum <test@example.com>
900
805
  f1
901
806
  f2
902
807
""",
903
 
                             the_log)
 
808
            wt.branch, log.LongLogFormatter,
 
809
            formatter_kwargs=dict(levels=1),
 
810
            show_log_kwargs=dict(verbose=True),
 
811
            normalize=True)
904
812
 
905
813
    def test_long_trailing_newlines(self):
906
814
        wt = self.make_branch_and_tree('.')
907
815
        b = make_commits_with_trailing_newlines(wt)
908
 
        sio = self.make_utf8_encoded_stringio()
909
 
        lf = log.LongLogFormatter(to_file=sio, levels=1)
910
 
        log.show_log(b, lf)
911
 
        self.assertEqualDiff("""\
 
816
        self.assertFormatterResult("""\
912
817
------------------------------------------------------------
913
818
revno: 3
914
819
committer: Joe Foo <joe@foo.com>
934
839
message:
935
840
  simple log message
936
841
""",
937
 
                             sio.getvalue())
 
842
        b, log.LongLogFormatter,
 
843
        formatter_kwargs=dict(levels=1))
938
844
 
939
845
    def test_long_author_in_log(self):
940
846
        """Log includes the author name if it's set in
941
847
        the revision properties
942
848
        """
943
 
        wt = self.make_branch_and_tree('.')
944
 
        b = wt.branch
945
 
        self.build_tree(['a'])
946
 
        wt.add('a')
947
 
        b.nick = 'test_author_log'
948
 
        wt.commit(message='add a',
949
 
                  timestamp=1132711707,
950
 
                  timezone=36000,
951
 
                  committer='Lorem Ipsum <test@example.com>',
952
 
                  authors=['John Doe <jdoe@example.com>'])
953
 
        sio = StringIO()
954
 
        formatter = log.LongLogFormatter(to_file=sio, levels=1)
955
 
        log.show_log(b, formatter)
956
 
        self.assertEqualDiff('''\
 
849
        wt = self.make_standard_commit('test_author_log')
 
850
        self.assertFormatterResult("""\
957
851
------------------------------------------------------------
958
852
revno: 1
959
853
author: John Doe <jdoe@example.com>
962
856
timestamp: Wed 2005-11-23 12:08:27 +1000
963
857
message:
964
858
  add a
965
 
''',
966
 
                             sio.getvalue())
 
859
""",
 
860
            wt.branch, log.LongLogFormatter,
 
861
            formatter_kwargs=dict(levels=1))
967
862
 
968
863
    def test_long_properties_in_log(self):
969
864
        """Log includes the custom properties returned by the registered
970
865
        handlers.
971
866
        """
972
 
        wt = self.make_branch_and_tree('.')
973
 
        b = wt.branch
974
 
        self.build_tree(['a'])
975
 
        wt.add('a')
976
 
        b.nick = 'test_properties_in_log'
977
 
        wt.commit(message='add a',
978
 
                  timestamp=1132711707,
979
 
                  timezone=36000,
980
 
                  committer='Lorem Ipsum <test@example.com>',
981
 
                  authors=['John Doe <jdoe@example.com>'])
982
 
        sio = StringIO()
983
 
        formatter = log.LongLogFormatter(to_file=sio, levels=1)
984
 
        try:
985
 
            def trivial_custom_prop_handler(revision):
986
 
                return {'test_prop':'test_value'}
 
867
        wt = self.make_standard_commit('test_properties_in_log')
 
868
        def trivial_custom_prop_handler(revision):
 
869
            return {'test_prop':'test_value'}
987
870
 
988
 
            log.properties_handler_registry.register(
989
 
                'trivial_custom_prop_handler',
990
 
                trivial_custom_prop_handler)
991
 
            log.show_log(b, formatter)
992
 
        finally:
993
 
            log.properties_handler_registry.remove(
994
 
                'trivial_custom_prop_handler')
995
 
            self.assertEqualDiff('''\
 
871
        log.properties_handler_registry.register(
 
872
            'trivial_custom_prop_handler',
 
873
            trivial_custom_prop_handler)
 
874
        self.assertFormatterResult("""\
996
875
------------------------------------------------------------
997
876
revno: 1
998
877
test_prop: test_value
1002
881
timestamp: Wed 2005-11-23 12:08:27 +1000
1003
882
message:
1004
883
  add a
1005
 
''',
1006
 
                                 sio.getvalue())
1007
 
 
1008
 
 
1009
 
class TestLineLogFormatter(tests.TestCaseWithTransport):
 
884
""",
 
885
            wt.branch, log.LongLogFormatter,
 
886
            formatter_kwargs=dict(levels=1))
 
887
 
 
888
 
 
889
class TestLineLogFormatter(TestCaseForLogFormatter):
1010
890
 
1011
891
    def test_line_log(self):
1012
892
        """Line log should show revno
1013
893
 
1014
894
        bug #5162
1015
895
        """
1016
 
        wt = self.make_branch_and_tree('.')
1017
 
        b = wt.branch
1018
 
        self.build_tree(['a'])
1019
 
        wt.add('a')
1020
 
        b.nick = 'test-line-log'
1021
 
        wt.commit(message='add a',
1022
 
                  timestamp=1132711707,
1023
 
                  timezone=36000,
1024
 
                  committer='Line-Log-Formatter Tester <test@line.log>')
1025
 
        logfile = file('out.tmp', 'w+')
1026
 
        formatter = log.LineLogFormatter(to_file=logfile)
1027
 
        log.show_log(b, formatter)
1028
 
        logfile.flush()
1029
 
        logfile.seek(0)
1030
 
        log_contents = logfile.read()
1031
 
        self.assertEqualDiff('1: Line-Log-Formatte... 2005-11-23 add a\n',
1032
 
                             log_contents)
 
896
        wt = self.make_standard_commit('test-line-log',
 
897
                committer='Line-Log-Formatter Tester <test@line.log>',
 
898
                authors=[])
 
899
        self.assertFormatterResult("""\
 
900
1: Line-Log-Formatte... 2005-11-23 add a
 
901
""",
 
902
            wt.branch, log.LineLogFormatter)
1033
903
 
1034
904
    def test_trailing_newlines(self):
1035
905
        wt = self.make_branch_and_tree('.')
1036
906
        b = make_commits_with_trailing_newlines(wt)
1037
 
        sio = self.make_utf8_encoded_stringio()
1038
 
        lf = log.LineLogFormatter(to_file=sio)
1039
 
        log.show_log(b, lf)
1040
 
        self.assertEqualDiff("""\
 
907
        self.assertFormatterResult("""\
1041
908
3: Joe Foo 2005-11-21 single line with trailing newline
1042
909
2: Joe Bar 2005-11-21 multiline
1043
910
1: Joe Foo 2005-11-21 simple log message
1044
911
""",
1045
 
                             sio.getvalue())
1046
 
 
1047
 
    def _prepare_tree_with_merges(self, with_tags=False):
1048
 
        wt = self.make_branch_and_memory_tree('.')
1049
 
        wt.lock_write()
1050
 
        self.addCleanup(wt.unlock)
1051
 
        wt.add('')
1052
 
        wt.commit('rev-1', rev_id='rev-1',
1053
 
                  timestamp=1132586655, timezone=36000,
1054
 
                  committer='Joe Foo <joe@foo.com>')
1055
 
        wt.commit('rev-merged', rev_id='rev-2a',
1056
 
                  timestamp=1132586700, timezone=36000,
1057
 
                  committer='Joe Foo <joe@foo.com>')
1058
 
        wt.set_parent_ids(['rev-1', 'rev-2a'])
1059
 
        wt.branch.set_last_revision_info(1, 'rev-1')
1060
 
        wt.commit('rev-2', rev_id='rev-2b',
1061
 
                  timestamp=1132586800, timezone=36000,
1062
 
                  committer='Joe Foo <joe@foo.com>')
1063
 
        if with_tags:
1064
 
            branch = wt.branch
1065
 
            branch.tags.set_tag('v0.2', 'rev-2b')
1066
 
            wt.commit('rev-3', rev_id='rev-3',
1067
 
                      timestamp=1132586900, timezone=36000,
1068
 
                      committer='Jane Foo <jane@foo.com>')
1069
 
            branch.tags.set_tag('v1.0rc1', 'rev-3')
1070
 
            branch.tags.set_tag('v1.0', 'rev-3')
1071
 
        return wt
 
912
            b, log.LineLogFormatter)
1072
913
 
1073
914
    def test_line_log_single_merge_revision(self):
1074
915
        wt = self._prepare_tree_with_merges()
1075
 
        logfile = self.make_utf8_encoded_stringio()
1076
 
        formatter = log.LineLogFormatter(to_file=logfile)
1077
916
        revspec = revisionspec.RevisionSpec.from_string('1.1.1')
1078
 
        wtb = wt.branch
1079
 
        rev = revspec.in_history(wtb)
1080
 
        log.show_log(wtb, formatter, start_revision=rev, end_revision=rev)
1081
 
        self.assertEqualDiff("""\
 
917
        rev = revspec.in_history(wt.branch)
 
918
        self.assertFormatterResult("""\
1082
919
1.1.1: Joe Foo 2005-11-22 rev-merged
1083
920
""",
1084
 
                             logfile.getvalue())
 
921
            wt.branch, log.LineLogFormatter,
 
922
            show_log_kwargs=dict(start_revision=rev, end_revision=rev))
1085
923
 
1086
924
    def test_line_log_with_tags(self):
1087
925
        wt = self._prepare_tree_with_merges(with_tags=True)
1088
 
        logfile = self.make_utf8_encoded_stringio()
1089
 
        formatter = log.LineLogFormatter(to_file=logfile)
1090
 
        log.show_log(wt.branch, formatter)
1091
 
        self.assertEqualDiff("""\
 
926
        self.assertFormatterResult("""\
1092
927
3: Jane Foo 2005-11-22 {v1.0, v1.0rc1} rev-3
1093
928
2: Joe Foo 2005-11-22 [merge] {v0.2} rev-2
1094
929
1: Joe Foo 2005-11-22 rev-1
1095
930
""",
1096
 
                             logfile.getvalue())
1097
 
 
1098
 
class TestLineLogFormatterWithMergeRevisions(tests.TestCaseWithTransport):
 
931
            wt.branch, log.LineLogFormatter)
 
932
 
 
933
 
 
934
class TestLineLogFormatterWithMergeRevisions(TestCaseForLogFormatter):
1099
935
 
1100
936
    def test_line_merge_revs_log(self):
1101
937
        """Line log should show revno
1102
938
 
1103
939
        bug #5162
1104
940
        """
1105
 
        wt = self.make_branch_and_tree('.')
1106
 
        b = wt.branch
1107
 
        self.build_tree(['a'])
1108
 
        wt.add('a')
1109
 
        b.nick = 'test-line-log'
1110
 
        wt.commit(message='add a',
1111
 
                  timestamp=1132711707,
1112
 
                  timezone=36000,
1113
 
                  committer='Line-Log-Formatter Tester <test@line.log>')
1114
 
        logfile = file('out.tmp', 'w+')
1115
 
        formatter = log.LineLogFormatter(to_file=logfile, levels=0)
1116
 
        log.show_log(b, formatter)
1117
 
        logfile.flush()
1118
 
        logfile.seek(0)
1119
 
        log_contents = logfile.read()
1120
 
        self.assertEqualDiff('1: Line-Log-Formatte... 2005-11-23 add a\n',
1121
 
                             log_contents)
 
941
        wt = self.make_standard_commit('test-line-log',
 
942
                committer='Line-Log-Formatter Tester <test@line.log>',
 
943
                authors=[])
 
944
        self.assertFormatterResult("""\
 
945
1: Line-Log-Formatte... 2005-11-23 add a
 
946
""",
 
947
            wt.branch, log.LineLogFormatter)
1122
948
 
1123
949
    def test_line_merge_revs_log_single_merge_revision(self):
1124
950
        wt = self.make_branch_and_memory_tree('.')
1136
962
        wt.commit('rev-2', rev_id='rev-2b',
1137
963
                  timestamp=1132586800, timezone=36000,
1138
964
                  committer='Joe Foo <joe@foo.com>')
1139
 
        logfile = self.make_utf8_encoded_stringio()
1140
 
        formatter = log.LineLogFormatter(to_file=logfile, levels=0)
1141
965
        revspec = revisionspec.RevisionSpec.from_string('1.1.1')
1142
 
        wtb = wt.branch
1143
 
        rev = revspec.in_history(wtb)
1144
 
        log.show_log(wtb, formatter, start_revision=rev, end_revision=rev)
1145
 
        self.assertEqualDiff("""\
 
966
        rev = revspec.in_history(wt.branch)
 
967
        self.assertFormatterResult("""\
1146
968
1.1.1: Joe Foo 2005-11-22 rev-merged
1147
969
""",
1148
 
                             logfile.getvalue())
 
970
            wt.branch, log.LineLogFormatter,
 
971
            formatter_kwargs=dict(levels=0),
 
972
            show_log_kwargs=dict(start_revision=rev, end_revision=rev))
1149
973
 
1150
974
    def test_line_merge_revs_log_with_merges(self):
1151
975
        wt = self.make_branch_and_memory_tree('.')
1163
987
        wt.commit('rev-2', rev_id='rev-2b',
1164
988
                  timestamp=1132586800, timezone=36000,
1165
989
                  committer='Joe Foo <joe@foo.com>')
1166
 
        logfile = self.make_utf8_encoded_stringio()
1167
 
        formatter = log.LineLogFormatter(to_file=logfile, levels=0)
1168
 
        log.show_log(wt.branch, formatter)
1169
 
        self.assertEqualDiff("""\
 
990
        self.assertFormatterResult("""\
1170
991
2: Joe Foo 2005-11-22 [merge] rev-2
1171
992
  1.1.1: Joe Foo 2005-11-22 rev-merged
1172
993
1: Joe Foo 2005-11-22 rev-1
1173
994
""",
1174
 
                             logfile.getvalue())
 
995
            wt.branch, log.LineLogFormatter,
 
996
            formatter_kwargs=dict(levels=0))
 
997
 
1175
998
 
1176
999
class TestGetViewRevisions(tests.TestCaseWithTransport):
1177
1000
 
1197
1020
        # 4a: 3.1.1
1198
1021
        return mainline_revs, rev_nos, wt
1199
1022
 
1200
 
    def make_tree_with_many_merges(self):
 
1023
    def make_branch_with_many_merges(self):
1201
1024
        """Create a tree with well-known revision ids"""
1202
 
        wt = self.make_branch_and_tree('tree1')
1203
 
        self.build_tree_contents([('tree1/f', '1\n')])
1204
 
        wt.add(['f'], ['f-id'])
1205
 
        wt.commit('commit one', rev_id='1')
1206
 
        wt.commit('commit two', rev_id='2')
1207
 
 
1208
 
        tree3 = wt.bzrdir.sprout('tree3').open_workingtree()
1209
 
        self.build_tree_contents([('tree3/f', '1\n2\n3a\n')])
1210
 
        tree3.commit('commit three a', rev_id='3a')
1211
 
 
1212
 
        tree2 = wt.bzrdir.sprout('tree2').open_workingtree()
1213
 
        tree2.merge_from_branch(tree3.branch)
1214
 
        tree2.commit('commit three b', rev_id='3b')
1215
 
 
1216
 
        wt.merge_from_branch(tree2.branch)
1217
 
        wt.commit('commit three c', rev_id='3c')
1218
 
        tree2.commit('four-a', rev_id='4a')
1219
 
 
1220
 
        wt.merge_from_branch(tree2.branch)
1221
 
        wt.commit('four-b', rev_id='4b')
 
1025
        builder = self.make_branch_builder('tree1')
 
1026
        builder.start_series()
 
1027
        builder.build_snapshot('1', None, [
 
1028
            ('add', ('', 'TREE_ROOT', 'directory', '')),
 
1029
            ('add', ('f', 'f-id', 'file', '1\n'))])
 
1030
        builder.build_snapshot('2', ['1'], [])
 
1031
        builder.build_snapshot('3a', ['2'], [
 
1032
            ('modify', ('f-id', '1\n2\n3a\n'))])
 
1033
        builder.build_snapshot('3b', ['2', '3a'], [
 
1034
            ('modify', ('f-id', '1\n2\n3a\n'))])
 
1035
        builder.build_snapshot('3c', ['2', '3b'], [
 
1036
            ('modify', ('f-id', '1\n2\n3a\n'))])
 
1037
        builder.build_snapshot('4a', ['3b'], [])
 
1038
        builder.build_snapshot('4b', ['3c', '4a'], [])
 
1039
        builder.finish_series()
 
1040
 
 
1041
        # 1
 
1042
        # |
 
1043
        # 2-.
 
1044
        # |\ \
 
1045
        # | | 3a
 
1046
        # | |/
 
1047
        # | 3b
 
1048
        # |/|
 
1049
        # 3c4a
 
1050
        # |/
 
1051
        # 4b
1222
1052
 
1223
1053
        mainline_revs = [None, '1', '2', '3c', '4b']
1224
1054
        rev_nos = {'1':1, '2':2, '3c': 3, '4b':4}
1231
1061
            '4a': '2.2.2', # second commit tree 2
1232
1062
            '4b': '4', # merges 4a to main
1233
1063
            }
1234
 
        return mainline_revs, rev_nos, wt
 
1064
        return mainline_revs, rev_nos, builder.get_branch()
1235
1065
 
1236
1066
    def test_get_view_revisions_forward(self):
1237
1067
        """Test the get_view_revisions method"""
1297
1127
 
1298
1128
    def test_get_view_revisions_merge2(self):
1299
1129
        """Test get_view_revisions when there are merges"""
1300
 
        mainline_revs, rev_nos, wt = self.make_tree_with_many_merges()
1301
 
        wt.lock_read()
1302
 
        self.addCleanup(wt.unlock)
 
1130
        mainline_revs, rev_nos, b = self.make_branch_with_many_merges()
 
1131
        b.lock_read()
 
1132
        self.addCleanup(b.unlock)
1303
1133
        revisions = list(log.get_view_revisions(
1304
 
                mainline_revs, rev_nos, wt.branch, 'forward'))
 
1134
                mainline_revs, rev_nos, b, 'forward'))
1305
1135
        expected = [('1', '1', 0), ('2', '2', 0), ('3c', '3', 0),
1306
 
                    ('3a', '2.1.1', 1), ('3b', '2.2.1', 1), ('4b', '4', 0),
 
1136
                    ('3b', '2.2.1', 1), ('3a', '2.1.1', 2), ('4b', '4', 0),
1307
1137
                    ('4a', '2.2.2', 1)]
1308
1138
        self.assertEqual(expected, revisions)
1309
1139
        revisions = list(log.get_view_revisions(
1310
 
                mainline_revs, rev_nos, wt.branch, 'forward',
 
1140
                mainline_revs, rev_nos, b, 'forward',
1311
1141
                include_merges=False))
1312
1142
        self.assertEqual([('1', '1', 0), ('2', '2', 0), ('3c', '3', 0),
1313
1143
                          ('4b', '4', 0)],
1315
1145
 
1316
1146
 
1317
1147
    def test_file_id_for_range(self):
1318
 
        mainline_revs, rev_nos, wt = self.make_tree_with_many_merges()
1319
 
        wt.lock_read()
1320
 
        self.addCleanup(wt.unlock)
 
1148
        mainline_revs, rev_nos, b = self.make_branch_with_many_merges()
 
1149
        b.lock_read()
 
1150
        self.addCleanup(b.unlock)
1321
1151
 
1322
1152
        def rev_from_rev_id(revid, branch):
1323
1153
            revspec = revisionspec.RevisionSpec.from_string('revid:%s' % revid)
1325
1155
 
1326
1156
        def view_revs(start_rev, end_rev, file_id, direction):
1327
1157
            revs = log.calculate_view_revisions(
1328
 
                wt.branch,
 
1158
                b,
1329
1159
                start_rev, # start_revision
1330
1160
                end_rev, # end_revision
1331
1161
                direction, # direction
1334
1164
                )
1335
1165
            return revs
1336
1166
 
1337
 
        rev_3a = rev_from_rev_id('3a', wt.branch)
1338
 
        rev_4b = rev_from_rev_id('4b', wt.branch)
1339
 
        self.assertEqual([('3c', '3', 0), ('3a', '2.1.1', 1)],
 
1167
        rev_3a = rev_from_rev_id('3a', b)
 
1168
        rev_4b = rev_from_rev_id('4b', b)
 
1169
        self.assertEqual([('3c', '3', 0), ('3b', '2.2.1', 1), ('3a', '2.1.1', 2)],
1340
1170
                          view_revs(rev_3a, rev_4b, 'f-id', 'reverse'))
1341
1171
        # Note: 3c still appears before 3a here because of depth-based sorting
1342
 
        self.assertEqual([('3c', '3', 0), ('3a', '2.1.1', 1)],
 
1172
        self.assertEqual([('3c', '3', 0), ('3b', '2.2.1', 1), ('3a', '2.1.1', 2)],
1343
1173
                          view_revs(rev_3a, rev_4b, 'f-id', 'forward'))
1344
1174
 
1345
1175
 
1697
1527
        log.show_branch_change(tree.branch, s, 3, '3b')
1698
1528
        self.assertContainsRe(s.getvalue(), 'Removed Revisions:')
1699
1529
        self.assertNotContainsRe(s.getvalue(), 'Added Revisions:')
 
1530
 
 
1531
 
 
1532
 
 
1533
class TestLogWithBugs(TestCaseForLogFormatter):
 
1534
 
 
1535
    def setUp(self):
 
1536
        TestCaseForLogFormatter.setUp(self)
 
1537
        log.properties_handler_registry.register(
 
1538
            'bugs_properties_handler',
 
1539
            log._bugs_properties_handler)
 
1540
 
 
1541
    def make_commits_with_bugs(self):
 
1542
        """Helper method for LogFormatter tests"""
 
1543
        tree = self.make_branch_and_tree(u'.')
 
1544
        self.build_tree(['a', 'b'])
 
1545
        tree.add('a')
 
1546
        tree.commit('simple log message', rev_id='a1',
 
1547
                    timestamp=1132586655.459960938, timezone=-6*3600,
 
1548
                    committer='Joe Foo <joe@foo.com>',
 
1549
                    revprops={'bugs': 'test://bug/id fixed'})
 
1550
        tree.add('b')
 
1551
        tree.commit('multiline\nlog\nmessage\n', rev_id='a2',
 
1552
                    timestamp=1132586842.411175966, timezone=-6*3600,
 
1553
                    committer='Joe Foo <joe@foo.com>',
 
1554
                    authors=['Joe Bar <joe@bar.com>'],
 
1555
                    revprops={'bugs': 'test://bug/id fixed\n'
 
1556
                                      'test://bug/2 fixed'})
 
1557
        return tree
 
1558
 
 
1559
 
 
1560
    def test_long_bugs(self):
 
1561
        tree = self.make_commits_with_bugs()
 
1562
        self.assertFormatterResult("""\
 
1563
------------------------------------------------------------
 
1564
revno: 2
 
1565
fixes bug(s): test://bug/id test://bug/2
 
1566
author: Joe Bar <joe@bar.com>
 
1567
committer: Joe Foo <joe@foo.com>
 
1568
branch nick: work
 
1569
timestamp: Mon 2005-11-21 09:27:22 -0600
 
1570
message:
 
1571
  multiline
 
1572
  log
 
1573
  message
 
1574
------------------------------------------------------------
 
1575
revno: 1
 
1576
fixes bug(s): test://bug/id
 
1577
committer: Joe Foo <joe@foo.com>
 
1578
branch nick: work
 
1579
timestamp: Mon 2005-11-21 09:24:15 -0600
 
1580
message:
 
1581
  simple log message
 
1582
""",
 
1583
            tree.branch, log.LongLogFormatter)
 
1584
 
 
1585
    def test_short_bugs(self):
 
1586
        tree = self.make_commits_with_bugs()
 
1587
        self.assertFormatterResult("""\
 
1588
    2 Joe Bar\t2005-11-21
 
1589
      fixes bug(s): test://bug/id test://bug/2
 
1590
      multiline
 
1591
      log
 
1592
      message
 
1593
 
 
1594
    1 Joe Foo\t2005-11-21
 
1595
      fixes bug(s): test://bug/id
 
1596
      simple log message
 
1597
 
 
1598
""",
 
1599
            tree.branch, log.ShortLogFormatter)
 
1600
 
 
1601
    def test_wrong_bugs_property(self):
 
1602
        tree = self.make_branch_and_tree(u'.')
 
1603
        self.build_tree(['foo'])
 
1604
        tree.commit('simple log message', rev_id='a1',
 
1605
              timestamp=1132586655.459960938, timezone=-6*3600,
 
1606
              committer='Joe Foo <joe@foo.com>',
 
1607
              revprops={'bugs': 'test://bug/id invalid_value'})
 
1608
        self.assertFormatterResult("""\
 
1609
    1 Joe Foo\t2005-11-21
 
1610
      simple log message
 
1611
 
 
1612
""",
 
1613
            tree.branch, log.ShortLogFormatter)
 
1614
 
 
1615
    def test_bugs_handler_present(self):
 
1616
        self.properties_handler_registry.get('bugs_properties_handler')