~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_log.py

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2010-01-14 00:01:32 UTC
  • mfrom: (4957.1.1 jam-integration)
  • Revision ID: pqm@pqm.ubuntu.com-20100114000132-3p3rabnonjw3gzqb
(jam) Merge bzr.stable, bringing in bug fixes #175839, #504390

Show diffs side-by-side

added added

removed removed

Lines of Context:
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
 
        # clean up the registry in log
 
36
        # Use a clean registry for log
37
37
        log.properties_handler_registry = registry.Registry()
38
38
 
39
 
    def _cleanup(self):
40
 
        super(TestCaseWithoutPropsHandler, self)._cleanup()
41
 
        # restore the custom properties handler registry
42
 
        log.properties_handler_registry = self.properties_handler_registry
 
39
        def restore():
 
40
            log.properties_handler_registry = self.properties_handler_registry
 
41
        self.addCleanup(restore)
 
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
        
43
101
 
44
102
 
45
103
class LogCatcher(log.LogFormatter):
46
 
    """Pull log messages into list rather than displaying them.
47
 
 
48
 
    For ease of testing we save log messages here rather than actually
49
 
    formatting them, so that we can precisely check the result without
50
 
    being too dependent on the exact formatting.
51
 
 
52
 
    We should also test the LogFormatter.
 
104
    """Pull log messages into a list rather than displaying them.
 
105
 
 
106
    To simplify testing we save logged revisions here rather than actually
 
107
    formatting anything, so that we can precisely check the result without
 
108
    being dependent on the formatting.
53
109
    """
54
110
 
55
111
    supports_delta = True
56
112
 
57
113
    def __init__(self):
58
114
        super(LogCatcher, self).__init__(to_file=None)
59
 
        self.logs = []
 
115
        self.revisions = []
60
116
 
61
117
    def log_revision(self, revision):
62
 
        self.logs.append(revision)
 
118
        self.revisions.append(revision)
63
119
 
64
120
 
65
121
class TestShowLog(tests.TestCaseWithTransport):
106
162
        lf = LogCatcher()
107
163
        log.show_log(wt.branch, lf)
108
164
        # no entries yet
109
 
        self.assertEqual([], lf.logs)
 
165
        self.assertEqual([], lf.revisions)
110
166
 
111
167
    def test_empty_commit(self):
112
168
        wt = self.make_branch_and_tree('.')
114
170
        wt.commit('empty commit')
115
171
        lf = LogCatcher()
116
172
        log.show_log(wt.branch, lf, verbose=True)
117
 
        self.assertEqual(1, len(lf.logs))
118
 
        self.assertEqual('1', lf.logs[0].revno)
119
 
        self.assertEqual('empty commit', lf.logs[0].rev.message)
120
 
        self.checkDelta(lf.logs[0].delta)
 
173
        revs = lf.revisions
 
174
        self.assertEqual(1, len(revs))
 
175
        self.assertEqual('1', revs[0].revno)
 
176
        self.assertEqual('empty commit', revs[0].rev.message)
 
177
        self.checkDelta(revs[0].delta)
121
178
 
122
179
    def test_simple_commit(self):
123
180
        wt = self.make_branch_and_tree('.')
129
186
                            u'<test@example.com>')
130
187
        lf = LogCatcher()
131
188
        log.show_log(wt.branch, lf, verbose=True)
132
 
        self.assertEqual(2, len(lf.logs))
 
189
        self.assertEqual(2, len(lf.revisions))
133
190
        # first one is most recent
134
 
        log_entry = lf.logs[0]
 
191
        log_entry = lf.revisions[0]
135
192
        self.assertEqual('2', log_entry.revno)
136
193
        self.assertEqual('add one file', log_entry.rev.message)
137
194
        self.checkDelta(log_entry.delta, added=['hello'])
143
200
        wt.commit(msg)
144
201
        lf = LogCatcher()
145
202
        log.show_log(wt.branch, lf, verbose=True)
146
 
        committed_msg = lf.logs[0].rev.message
147
 
        self.assertNotEqual(msg, committed_msg)
148
 
        self.assertTrue(len(committed_msg) > len(msg))
 
203
        committed_msg = lf.revisions[0].rev.message
 
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)
149
209
 
150
210
    def test_commit_message_without_control_chars(self):
151
211
        wt = self.make_branch_and_tree('.')
157
217
        wt.commit(msg)
158
218
        lf = LogCatcher()
159
219
        log.show_log(wt.branch, lf, verbose=True)
160
 
        committed_msg = lf.logs[0].rev.message
 
220
        committed_msg = lf.revisions[0].rev.message
161
221
        self.assertEqual(msg, committed_msg)
162
222
 
163
223
    def test_deltas_in_merge_revisions(self):
181
241
        lf.supports_merge_revisions = True
182
242
        log.show_log(b, lf, verbose=True)
183
243
 
184
 
        self.assertEqual(3, len(lf.logs))
 
244
        revs = lf.revisions
 
245
        self.assertEqual(3, len(revs))
185
246
 
186
 
        logentry = lf.logs[0]
 
247
        logentry = revs[0]
187
248
        self.assertEqual('2', logentry.revno)
188
249
        self.assertEqual('merge child branch', logentry.rev.message)
189
250
        self.checkDelta(logentry.delta, removed=['file1'], modified=['file2'])
190
251
 
191
 
        logentry = lf.logs[1]
 
252
        logentry = revs[1]
192
253
        self.assertEqual('1.1.1', logentry.revno)
193
254
        self.assertEqual('remove file1 and modify file2', logentry.rev.message)
194
255
        self.checkDelta(logentry.delta, removed=['file1'], modified=['file2'])
195
256
 
196
 
        logentry = lf.logs[2]
 
257
        logentry = revs[2]
197
258
        self.assertEqual('1', logentry.revno)
198
259
        self.assertEqual('add file1 and file2', logentry.rev.message)
199
260
        self.checkDelta(logentry.delta, added=['file1', 'file2'])
240
301
    return ''.join(lines)
241
302
 
242
303
 
243
 
class TestShortLogFormatter(tests.TestCaseWithTransport):
 
304
class TestShortLogFormatter(TestCaseForLogFormatter):
244
305
 
245
306
    def test_trailing_newlines(self):
246
307
        wt = self.make_branch_and_tree('.')
247
308
        b = make_commits_with_trailing_newlines(wt)
248
 
        sio = self.make_utf8_encoded_stringio()
249
 
        lf = log.ShortLogFormatter(to_file=sio)
250
 
        log.show_log(b, lf)
251
 
        self.assertEqualDiff("""\
 
309
        self.assertFormatterResult("""\
252
310
    3 Joe Foo\t2005-11-21
253
311
      single line with trailing newline
254
312
 
261
319
      simple log message
262
320
 
263
321
""",
264
 
                             sio.getvalue())
265
 
 
266
 
    def _prepare_tree_with_merges(self, with_tags=False):
267
 
        wt = self.make_branch_and_memory_tree('.')
268
 
        wt.lock_write()
269
 
        self.addCleanup(wt.unlock)
270
 
        wt.add('')
271
 
        wt.commit('rev-1', rev_id='rev-1',
272
 
                  timestamp=1132586655, timezone=36000,
273
 
                  committer='Joe Foo <joe@foo.com>')
274
 
        wt.commit('rev-merged', rev_id='rev-2a',
275
 
                  timestamp=1132586700, timezone=36000,
276
 
                  committer='Joe Foo <joe@foo.com>')
277
 
        wt.set_parent_ids(['rev-1', 'rev-2a'])
278
 
        wt.branch.set_last_revision_info(1, 'rev-1')
279
 
        wt.commit('rev-2', rev_id='rev-2b',
280
 
                  timestamp=1132586800, timezone=36000,
281
 
                  committer='Joe Foo <joe@foo.com>')
282
 
        if with_tags:
283
 
            branch = wt.branch
284
 
            branch.tags.set_tag('v0.2', 'rev-2b')
285
 
            wt.commit('rev-3', rev_id='rev-3',
286
 
                      timestamp=1132586900, timezone=36000,
287
 
                      committer='Jane Foo <jane@foo.com>')
288
 
            branch.tags.set_tag('v1.0rc1', 'rev-3')
289
 
            branch.tags.set_tag('v1.0', 'rev-3')
290
 
        return wt
 
322
            b, log.ShortLogFormatter)
291
323
 
292
324
    def test_short_log_with_merges(self):
293
325
        wt = self._prepare_tree_with_merges()
294
 
        logfile = self.make_utf8_encoded_stringio()
295
 
        formatter = log.ShortLogFormatter(to_file=logfile)
296
 
        log.show_log(wt.branch, formatter)
297
 
        self.assertEqualDiff("""\
 
326
        self.assertFormatterResult("""\
298
327
    2 Joe Foo\t2005-11-22 [merge]
299
328
      rev-2
300
329
 
302
331
      rev-1
303
332
 
304
333
""",
305
 
                             logfile.getvalue())
 
334
            wt.branch, log.ShortLogFormatter)
306
335
 
307
336
    def test_short_log_with_merges_and_advice(self):
308
337
        wt = self._prepare_tree_with_merges()
309
 
        logfile = self.make_utf8_encoded_stringio()
310
 
        formatter = log.ShortLogFormatter(to_file=logfile,
311
 
            show_advice=True)
312
 
        log.show_log(wt.branch, formatter)
313
 
        self.assertEqualDiff("""\
 
338
        self.assertFormatterResult("""\
314
339
    2 Joe Foo\t2005-11-22 [merge]
315
340
      rev-2
316
341
 
319
344
 
320
345
Use --include-merges or -n0 to see merged revisions.
321
346
""",
322
 
                             logfile.getvalue())
 
347
            wt.branch, log.ShortLogFormatter,
 
348
            formatter_kwargs=dict(show_advice=True))
323
349
 
324
350
    def test_short_log_with_merges_and_range(self):
325
351
        wt = self.make_branch_and_memory_tree('.')
345
371
        wt.commit('rev-3b', rev_id='rev-3b',
346
372
                  timestamp=1132586800, timezone=36000,
347
373
                  committer='Joe Foo <joe@foo.com>')
348
 
        logfile = self.make_utf8_encoded_stringio()
349
 
        formatter = log.ShortLogFormatter(to_file=logfile)
350
 
        log.show_log(wt.branch, formatter,
351
 
            start_revision=2, end_revision=3)
352
 
        self.assertEqualDiff("""\
 
374
        self.assertFormatterResult("""\
353
375
    3 Joe Foo\t2005-11-22 [merge]
354
376
      rev-3b
355
377
 
357
379
      rev-2b
358
380
 
359
381
""",
360
 
                             logfile.getvalue())
 
382
            wt.branch, log.ShortLogFormatter,
 
383
            show_log_kwargs=dict(start_revision=2, end_revision=3))
361
384
 
362
385
    def test_short_log_with_tags(self):
363
386
        wt = self._prepare_tree_with_merges(with_tags=True)
364
 
        logfile = self.make_utf8_encoded_stringio()
365
 
        formatter = log.ShortLogFormatter(to_file=logfile)
366
 
        log.show_log(wt.branch, formatter)
367
 
        self.assertEqualDiff("""\
 
387
        self.assertFormatterResult("""\
368
388
    3 Jane Foo\t2005-11-22 {v1.0, v1.0rc1}
369
389
      rev-3
370
390
 
375
395
      rev-1
376
396
 
377
397
""",
378
 
                             logfile.getvalue())
 
398
            wt.branch, log.ShortLogFormatter)
379
399
 
380
400
    def test_short_log_single_merge_revision(self):
381
401
        wt = self.make_branch_and_memory_tree('.')
393
413
        wt.commit('rev-2', rev_id='rev-2b',
394
414
                  timestamp=1132586800, timezone=36000,
395
415
                  committer='Joe Foo <joe@foo.com>')
396
 
        logfile = self.make_utf8_encoded_stringio()
397
 
        formatter = log.ShortLogFormatter(to_file=logfile)
398
416
        revspec = revisionspec.RevisionSpec.from_string('1.1.1')
399
 
        wtb = wt.branch
400
 
        rev = revspec.in_history(wtb)
401
 
        log.show_log(wtb, formatter, start_revision=rev, end_revision=rev)
402
 
        self.assertEqualDiff("""\
 
417
        rev = revspec.in_history(wt.branch)
 
418
        self.assertFormatterResult("""\
403
419
      1.1.1 Joe Foo\t2005-11-22
404
420
            rev-merged
405
421
 
406
422
""",
407
 
                             logfile.getvalue())
408
 
 
409
 
 
410
 
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):
411
428
 
412
429
    def test_short_merge_revs_log_with_merges(self):
413
430
        wt = self.make_branch_and_memory_tree('.')
425
442
        wt.commit('rev-2', rev_id='rev-2b',
426
443
                  timestamp=1132586800, timezone=36000,
427
444
                  committer='Joe Foo <joe@foo.com>')
428
 
        logfile = self.make_utf8_encoded_stringio()
429
 
        formatter = log.ShortLogFormatter(to_file=logfile, levels=0)
430
 
        log.show_log(wt.branch, formatter)
431
445
        # Note that the 1.1.1 indenting is in fact correct given that
432
446
        # the revision numbers are right justified within 5 characters
433
447
        # for mainline revnos and 9 characters for dotted revnos.
434
 
        self.assertEqualDiff("""\
 
448
        self.assertFormatterResult("""\
435
449
    2 Joe Foo\t2005-11-22 [merge]
436
450
      rev-2
437
451
 
442
456
      rev-1
443
457
 
444
458
""",
445
 
                             logfile.getvalue())
 
459
            wt.branch, log.ShortLogFormatter,
 
460
            formatter_kwargs=dict(levels=0))
446
461
 
447
462
    def test_short_merge_revs_log_single_merge_revision(self):
448
463
        wt = self.make_branch_and_memory_tree('.')
460
475
        wt.commit('rev-2', rev_id='rev-2b',
461
476
                  timestamp=1132586800, timezone=36000,
462
477
                  committer='Joe Foo <joe@foo.com>')
463
 
        logfile = self.make_utf8_encoded_stringio()
464
 
        formatter = log.ShortLogFormatter(to_file=logfile, levels=0)
465
478
        revspec = revisionspec.RevisionSpec.from_string('1.1.1')
466
 
        wtb = wt.branch
467
 
        rev = revspec.in_history(wtb)
468
 
        log.show_log(wtb, formatter, start_revision=rev, end_revision=rev)
469
 
        self.assertEqualDiff("""\
 
479
        rev = revspec.in_history(wt.branch)
 
480
        self.assertFormatterResult("""\
470
481
      1.1.1 Joe Foo\t2005-11-22
471
482
            rev-merged
472
483
 
473
484
""",
474
 
                             logfile.getvalue())
475
 
 
476
 
 
477
 
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):
478
491
 
479
492
    def test_verbose_log(self):
480
493
        """Verbose log includes changed files
481
494
 
482
495
        bug #4676
483
496
        """
484
 
        wt = self.make_branch_and_tree('.')
485
 
        b = wt.branch
486
 
        self.build_tree(['a'])
487
 
        wt.add('a')
488
 
        # XXX: why does a longer nick show up?
489
 
        b.nick = 'test_verbose_log'
490
 
        wt.commit(message='add a',
491
 
                  timestamp=1132711707,
492
 
                  timezone=36000,
493
 
                  committer='Lorem Ipsum <test@example.com>')
494
 
        logfile = file('out.tmp', 'w+')
495
 
        formatter = log.LongLogFormatter(to_file=logfile)
496
 
        log.show_log(b, formatter, verbose=True)
497
 
        logfile.flush()
498
 
        logfile.seek(0)
499
 
        log_contents = logfile.read()
500
 
        self.assertEqualDiff('''\
 
497
        wt = self.make_standard_commit('test_verbose_log', authors=[])
 
498
        self.assertFormatterResult('''\
501
499
------------------------------------------------------------
502
500
revno: 1
503
501
committer: Lorem Ipsum <test@example.com>
508
506
added:
509
507
  a
510
508
''',
511
 
                             log_contents)
 
509
            wt.branch, log.LongLogFormatter,
 
510
            show_log_kwargs=dict(verbose=True))
512
511
 
513
512
    def test_merges_are_indented_by_level(self):
514
513
        wt = self.make_branch_and_tree('parent')
524
523
        os.chdir('../parent')
525
524
        self.run_bzr('merge ../child')
526
525
        wt.commit('merge branch 1')
527
 
        b = wt.branch
528
 
        sio = self.make_utf8_encoded_stringio()
529
 
        lf = log.LongLogFormatter(to_file=sio, levels=0)
530
 
        log.show_log(b, lf, verbose=True)
531
 
        the_log = normalize_log(sio.getvalue())
532
 
        self.assertEqualDiff("""\
 
526
        self.assertFormatterResult("""\
533
527
------------------------------------------------------------
534
528
revno: 2 [merge]
535
529
committer: Lorem Ipsum <test@example.com>
566
560
message:
567
561
  first post
568
562
""",
569
 
                             the_log)
 
563
            wt.branch, log.LongLogFormatter,
 
564
            formatter_kwargs=dict(levels=0),
 
565
            show_log_kwargs=dict(verbose=True),
 
566
            normalize=True)
570
567
 
571
568
    def test_verbose_merge_revisions_contain_deltas(self):
572
569
        wt = self.make_branch_and_tree('parent')
581
578
        os.chdir('parent')
582
579
        self.run_bzr('merge ../child')
583
580
        wt.commit('merge branch 1')
584
 
        b = wt.branch
585
 
        sio = self.make_utf8_encoded_stringio()
586
 
        lf = log.LongLogFormatter(to_file=sio, levels=0)
587
 
        log.show_log(b, lf, verbose=True)
588
 
        the_log = normalize_log(sio.getvalue())
589
 
        self.assertEqualDiff("""\
 
581
        self.assertFormatterResult("""\
590
582
------------------------------------------------------------
591
583
revno: 2 [merge]
592
584
committer: Lorem Ipsum <test@example.com>
620
612
  f1
621
613
  f2
622
614
""",
623
 
                             the_log)
 
615
            wt.branch, log.LongLogFormatter,
 
616
            formatter_kwargs=dict(levels=0),
 
617
            show_log_kwargs=dict(verbose=True),
 
618
            normalize=True)
624
619
 
625
620
    def test_trailing_newlines(self):
626
621
        wt = self.make_branch_and_tree('.')
627
622
        b = make_commits_with_trailing_newlines(wt)
628
 
        sio = self.make_utf8_encoded_stringio()
629
 
        lf = log.LongLogFormatter(to_file=sio)
630
 
        log.show_log(b, lf)
631
 
        self.assertEqualDiff("""\
 
623
        self.assertFormatterResult("""\
632
624
------------------------------------------------------------
633
625
revno: 3
634
626
committer: Joe Foo <joe@foo.com>
654
646
message:
655
647
  simple log message
656
648
""",
657
 
                             sio.getvalue())
 
649
        b, log.LongLogFormatter)
658
650
 
659
651
    def test_author_in_log(self):
660
652
        """Log includes the author name if it's set in
661
653
        the revision properties
662
654
        """
663
 
        wt = self.make_branch_and_tree('.')
664
 
        b = wt.branch
665
 
        self.build_tree(['a'])
666
 
        wt.add('a')
667
 
        b.nick = 'test_author_log'
668
 
        wt.commit(message='add a',
669
 
                  timestamp=1132711707,
670
 
                  timezone=36000,
671
 
                  committer='Lorem Ipsum <test@example.com>',
672
 
                  authors=['John Doe <jdoe@example.com>',
673
 
                           'Jane Rey <jrey@example.com>'])
674
 
        sio = StringIO()
675
 
        formatter = log.LongLogFormatter(to_file=sio)
676
 
        log.show_log(b, formatter)
677
 
        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("""\
678
659
------------------------------------------------------------
679
660
revno: 1
680
661
author: John Doe <jdoe@example.com>, Jane Rey <jrey@example.com>
683
664
timestamp: Wed 2005-11-23 12:08:27 +1000
684
665
message:
685
666
  add a
686
 
''',
687
 
                             sio.getvalue())
 
667
""",
 
668
        wt.branch, log.LongLogFormatter)
688
669
 
689
670
    def test_properties_in_log(self):
690
671
        """Log includes the custom properties returned by the registered
691
672
        handlers.
692
673
        """
693
 
        wt = self.make_branch_and_tree('.')
694
 
        b = wt.branch
695
 
        self.build_tree(['a'])
696
 
        wt.add('a')
697
 
        b.nick = 'test_properties_in_log'
698
 
        wt.commit(message='add a',
699
 
                  timestamp=1132711707,
700
 
                  timezone=36000,
701
 
                  committer='Lorem Ipsum <test@example.com>',
702
 
                  authors=['John Doe <jdoe@example.com>'])
703
 
        sio = StringIO()
704
 
        formatter = log.LongLogFormatter(to_file=sio)
705
 
        try:
706
 
            def trivial_custom_prop_handler(revision):
707
 
                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'}
708
677
 
709
 
            log.properties_handler_registry.register(
710
 
                'trivial_custom_prop_handler',
711
 
                trivial_custom_prop_handler)
712
 
            log.show_log(b, formatter)
713
 
        finally:
714
 
            log.properties_handler_registry.remove(
715
 
                'trivial_custom_prop_handler')
716
 
            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("""\
717
683
------------------------------------------------------------
718
684
revno: 1
719
685
test_prop: test_value
723
689
timestamp: Wed 2005-11-23 12:08:27 +1000
724
690
message:
725
691
  add a
726
 
''',
727
 
                                 sio.getvalue())
 
692
""",
 
693
            wt.branch, log.LongLogFormatter)
728
694
 
729
695
    def test_properties_in_short_log(self):
730
696
        """Log includes the custom properties returned by the registered
731
697
        handlers.
732
698
        """
733
 
        wt = self.make_branch_and_tree('.')
734
 
        b = wt.branch
735
 
        self.build_tree(['a'])
736
 
        wt.add('a')
737
 
        b.nick = 'test_properties_in_short_log'
738
 
        wt.commit(message='add a',
739
 
                  timestamp=1132711707,
740
 
                  timezone=36000,
741
 
                  committer='Lorem Ipsum <test@example.com>',
742
 
                  authors=['John Doe <jdoe@example.com>'])
743
 
        sio = StringIO()
744
 
        formatter = log.ShortLogFormatter(to_file=sio)
745
 
        try:
746
 
            def trivial_custom_prop_handler(revision):
747
 
                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'}
748
702
 
749
 
            log.properties_handler_registry.register(
750
 
                'trivial_custom_prop_handler',
751
 
                trivial_custom_prop_handler)
752
 
            log.show_log(b, formatter)
753
 
        finally:
754
 
            log.properties_handler_registry.remove(
755
 
                'trivial_custom_prop_handler')
756
 
            self.assertEqualDiff('''\
 
703
        log.properties_handler_registry.register(
 
704
            'trivial_custom_prop_handler',
 
705
            trivial_custom_prop_handler)
 
706
        self.assertFormatterResult("""\
757
707
    1 John Doe\t2005-11-23
758
708
      test_prop: test_value
759
709
      add a
760
710
 
761
 
''',
762
 
                                 sio.getvalue())
 
711
""",
 
712
            wt.branch, log.ShortLogFormatter)
763
713
 
764
714
    def test_error_in_properties_handler(self):
765
715
        """Log includes the custom properties returned by the registered
766
716
        handlers.
767
717
        """
768
 
        wt = self.make_branch_and_tree('.')
769
 
        b = wt.branch
770
 
        self.build_tree(['a'])
771
 
        wt.add('a')
772
 
        b.nick = 'test_author_log'
773
 
        wt.commit(message='add a',
774
 
                  timestamp=1132711707,
775
 
                  timezone=36000,
776
 
                  committer='Lorem Ipsum <test@example.com>',
777
 
                  authors=['John Doe <jdoe@example.com>'],
778
 
                  revprops={'first_prop':'first_value'})
779
 
        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()
780
721
        formatter = log.LongLogFormatter(to_file=sio)
781
 
        try:
782
 
            def trivial_custom_prop_handler(revision):
783
 
                raise StandardError("a test error")
 
722
        def trivial_custom_prop_handler(revision):
 
723
            raise StandardError("a test error")
784
724
 
785
 
            log.properties_handler_registry.register(
786
 
                'trivial_custom_prop_handler',
787
 
                trivial_custom_prop_handler)
788
 
            self.assertRaises(StandardError, log.show_log, b, formatter,)
789
 
        finally:
790
 
            log.properties_handler_registry.remove(
791
 
                '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,)
792
729
 
793
730
    def test_properties_handler_bad_argument(self):
794
 
        wt = self.make_branch_and_tree('.')
795
 
        b = wt.branch
796
 
        self.build_tree(['a'])
797
 
        wt.add('a')
798
 
        b.nick = 'test_author_log'
799
 
        wt.commit(message='add a',
800
 
                  timestamp=1132711707,
801
 
                  timezone=36000,
802
 
                  committer='Lorem Ipsum <test@example.com>',
803
 
                  authors=['John Doe <jdoe@example.com>'],
804
 
                  revprops={'a_prop':'test_value'})
805
 
        sio = StringIO()
 
731
        wt = self.make_standard_commit('bad_argument',
 
732
              revprops={'a_prop':'test_value'})
 
733
        sio = self.make_utf8_encoded_stringio()
806
734
        formatter = log.LongLogFormatter(to_file=sio)
807
 
        try:
808
 
            def bad_argument_prop_handler(revision):
809
 
                return {'custom_prop_name':revision.properties['a_prop']}
810
 
 
811
 
            log.properties_handler_registry.register(
812
 
                'bad_argument_prop_handler',
813
 
                bad_argument_prop_handler)
814
 
 
815
 
            self.assertRaises(AttributeError, formatter.show_properties,
816
 
                              'a revision', '')
817
 
 
818
 
            revision = b.repository.get_revision(b.last_revision())
819
 
            formatter.show_properties(revision, '')
820
 
            self.assertEqualDiff('''custom_prop_name: test_value\n''',
821
 
                                 sio.getvalue())
822
 
        finally:
823
 
            log.properties_handler_registry.remove(
824
 
                'bad_argument_prop_handler')
825
 
 
826
 
 
827
 
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):
828
752
 
829
753
    def test_long_verbose_log(self):
830
754
        """Verbose log includes changed files
831
755
 
832
756
        bug #4676
833
757
        """
834
 
        wt = self.make_branch_and_tree('.')
835
 
        b = wt.branch
836
 
        self.build_tree(['a'])
837
 
        wt.add('a')
838
 
        # XXX: why does a longer nick show up?
839
 
        b.nick = 'test_verbose_log'
840
 
        wt.commit(message='add a',
841
 
                  timestamp=1132711707,
842
 
                  timezone=36000,
843
 
                  committer='Lorem Ipsum <test@example.com>')
844
 
        logfile = file('out.tmp', 'w+')
845
 
        formatter = log.LongLogFormatter(to_file=logfile, levels=1)
846
 
        log.show_log(b, formatter, verbose=True)
847
 
        logfile.flush()
848
 
        logfile.seek(0)
849
 
        log_contents = logfile.read()
850
 
        self.assertEqualDiff('''\
 
758
        wt = self.make_standard_commit('test_long_verbose_log', authors=[])
 
759
        self.assertFormatterResult("""\
851
760
------------------------------------------------------------
852
761
revno: 1
853
762
committer: Lorem Ipsum <test@example.com>
854
 
branch nick: test_verbose_log
 
763
branch nick: test_long_verbose_log
855
764
timestamp: Wed 2005-11-23 12:08:27 +1000
856
765
message:
857
766
  add a
858
767
added:
859
768
  a
860
 
''',
861
 
                             log_contents)
 
769
""",
 
770
            wt.branch, log.LongLogFormatter,
 
771
            formatter_kwargs=dict(levels=1),
 
772
            show_log_kwargs=dict(verbose=True))
862
773
 
863
774
    def test_long_verbose_contain_deltas(self):
864
775
        wt = self.make_branch_and_tree('parent')
865
776
        self.build_tree(['parent/f1', 'parent/f2'])
866
777
        wt.add(['f1','f2'])
867
778
        wt.commit('first post')
868
 
        self.run_bzr('branch parent child')
 
779
        child_wt = wt.bzrdir.sprout('child').open_workingtree()
869
780
        os.unlink('child/f1')
870
 
        file('child/f2', 'wb').write('hello\n')
871
 
        self.run_bzr(['commit', '-m', 'removed f1 and modified f2',
872
 
            'child'])
873
 
        os.chdir('parent')
874
 
        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)
875
784
        wt.commit('merge branch 1')
876
 
        b = wt.branch
877
 
        sio = self.make_utf8_encoded_stringio()
878
 
        lf = log.LongLogFormatter(to_file=sio, levels=1)
879
 
        log.show_log(b, lf, verbose=True)
880
 
        the_log = normalize_log(sio.getvalue())
881
 
        self.assertEqualDiff("""\
 
785
        self.assertFormatterResult("""\
882
786
------------------------------------------------------------
883
787
revno: 2 [merge]
884
788
committer: Lorem Ipsum <test@example.com>
901
805
  f1
902
806
  f2
903
807
""",
904
 
                             the_log)
 
808
            wt.branch, log.LongLogFormatter,
 
809
            formatter_kwargs=dict(levels=1),
 
810
            show_log_kwargs=dict(verbose=True),
 
811
            normalize=True)
905
812
 
906
813
    def test_long_trailing_newlines(self):
907
814
        wt = self.make_branch_and_tree('.')
908
815
        b = make_commits_with_trailing_newlines(wt)
909
 
        sio = self.make_utf8_encoded_stringio()
910
 
        lf = log.LongLogFormatter(to_file=sio, levels=1)
911
 
        log.show_log(b, lf)
912
 
        self.assertEqualDiff("""\
 
816
        self.assertFormatterResult("""\
913
817
------------------------------------------------------------
914
818
revno: 3
915
819
committer: Joe Foo <joe@foo.com>
935
839
message:
936
840
  simple log message
937
841
""",
938
 
                             sio.getvalue())
 
842
        b, log.LongLogFormatter,
 
843
        formatter_kwargs=dict(levels=1))
939
844
 
940
845
    def test_long_author_in_log(self):
941
846
        """Log includes the author name if it's set in
942
847
        the revision properties
943
848
        """
944
 
        wt = self.make_branch_and_tree('.')
945
 
        b = wt.branch
946
 
        self.build_tree(['a'])
947
 
        wt.add('a')
948
 
        b.nick = 'test_author_log'
949
 
        wt.commit(message='add a',
950
 
                  timestamp=1132711707,
951
 
                  timezone=36000,
952
 
                  committer='Lorem Ipsum <test@example.com>',
953
 
                  authors=['John Doe <jdoe@example.com>'])
954
 
        sio = StringIO()
955
 
        formatter = log.LongLogFormatter(to_file=sio, levels=1)
956
 
        log.show_log(b, formatter)
957
 
        self.assertEqualDiff('''\
 
849
        wt = self.make_standard_commit('test_author_log')
 
850
        self.assertFormatterResult("""\
958
851
------------------------------------------------------------
959
852
revno: 1
960
853
author: John Doe <jdoe@example.com>
963
856
timestamp: Wed 2005-11-23 12:08:27 +1000
964
857
message:
965
858
  add a
966
 
''',
967
 
                             sio.getvalue())
 
859
""",
 
860
            wt.branch, log.LongLogFormatter,
 
861
            formatter_kwargs=dict(levels=1))
968
862
 
969
863
    def test_long_properties_in_log(self):
970
864
        """Log includes the custom properties returned by the registered
971
865
        handlers.
972
866
        """
973
 
        wt = self.make_branch_and_tree('.')
974
 
        b = wt.branch
975
 
        self.build_tree(['a'])
976
 
        wt.add('a')
977
 
        b.nick = 'test_properties_in_log'
978
 
        wt.commit(message='add a',
979
 
                  timestamp=1132711707,
980
 
                  timezone=36000,
981
 
                  committer='Lorem Ipsum <test@example.com>',
982
 
                  authors=['John Doe <jdoe@example.com>'])
983
 
        sio = StringIO()
984
 
        formatter = log.LongLogFormatter(to_file=sio, levels=1)
985
 
        try:
986
 
            def trivial_custom_prop_handler(revision):
987
 
                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'}
988
870
 
989
 
            log.properties_handler_registry.register(
990
 
                'trivial_custom_prop_handler',
991
 
                trivial_custom_prop_handler)
992
 
            log.show_log(b, formatter)
993
 
        finally:
994
 
            log.properties_handler_registry.remove(
995
 
                'trivial_custom_prop_handler')
996
 
            self.assertEqualDiff('''\
 
871
        log.properties_handler_registry.register(
 
872
            'trivial_custom_prop_handler',
 
873
            trivial_custom_prop_handler)
 
874
        self.assertFormatterResult("""\
997
875
------------------------------------------------------------
998
876
revno: 1
999
877
test_prop: test_value
1003
881
timestamp: Wed 2005-11-23 12:08:27 +1000
1004
882
message:
1005
883
  add a
1006
 
''',
1007
 
                                 sio.getvalue())
1008
 
 
1009
 
 
1010
 
class TestLineLogFormatter(tests.TestCaseWithTransport):
 
884
""",
 
885
            wt.branch, log.LongLogFormatter,
 
886
            formatter_kwargs=dict(levels=1))
 
887
 
 
888
 
 
889
class TestLineLogFormatter(TestCaseForLogFormatter):
1011
890
 
1012
891
    def test_line_log(self):
1013
892
        """Line log should show revno
1014
893
 
1015
894
        bug #5162
1016
895
        """
1017
 
        wt = self.make_branch_and_tree('.')
1018
 
        b = wt.branch
1019
 
        self.build_tree(['a'])
1020
 
        wt.add('a')
1021
 
        b.nick = 'test-line-log'
1022
 
        wt.commit(message='add a',
1023
 
                  timestamp=1132711707,
1024
 
                  timezone=36000,
1025
 
                  committer='Line-Log-Formatter Tester <test@line.log>')
1026
 
        logfile = file('out.tmp', 'w+')
1027
 
        formatter = log.LineLogFormatter(to_file=logfile)
1028
 
        log.show_log(b, formatter)
1029
 
        logfile.flush()
1030
 
        logfile.seek(0)
1031
 
        log_contents = logfile.read()
1032
 
        self.assertEqualDiff('1: Line-Log-Formatte... 2005-11-23 add a\n',
1033
 
                             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)
1034
903
 
1035
904
    def test_trailing_newlines(self):
1036
905
        wt = self.make_branch_and_tree('.')
1037
906
        b = make_commits_with_trailing_newlines(wt)
1038
 
        sio = self.make_utf8_encoded_stringio()
1039
 
        lf = log.LineLogFormatter(to_file=sio)
1040
 
        log.show_log(b, lf)
1041
 
        self.assertEqualDiff("""\
 
907
        self.assertFormatterResult("""\
1042
908
3: Joe Foo 2005-11-21 single line with trailing newline
1043
909
2: Joe Bar 2005-11-21 multiline
1044
910
1: Joe Foo 2005-11-21 simple log message
1045
911
""",
1046
 
                             sio.getvalue())
1047
 
 
1048
 
    def _prepare_tree_with_merges(self, with_tags=False):
1049
 
        wt = self.make_branch_and_memory_tree('.')
1050
 
        wt.lock_write()
1051
 
        self.addCleanup(wt.unlock)
1052
 
        wt.add('')
1053
 
        wt.commit('rev-1', rev_id='rev-1',
1054
 
                  timestamp=1132586655, timezone=36000,
1055
 
                  committer='Joe Foo <joe@foo.com>')
1056
 
        wt.commit('rev-merged', rev_id='rev-2a',
1057
 
                  timestamp=1132586700, timezone=36000,
1058
 
                  committer='Joe Foo <joe@foo.com>')
1059
 
        wt.set_parent_ids(['rev-1', 'rev-2a'])
1060
 
        wt.branch.set_last_revision_info(1, 'rev-1')
1061
 
        wt.commit('rev-2', rev_id='rev-2b',
1062
 
                  timestamp=1132586800, timezone=36000,
1063
 
                  committer='Joe Foo <joe@foo.com>')
1064
 
        if with_tags:
1065
 
            branch = wt.branch
1066
 
            branch.tags.set_tag('v0.2', 'rev-2b')
1067
 
            wt.commit('rev-3', rev_id='rev-3',
1068
 
                      timestamp=1132586900, timezone=36000,
1069
 
                      committer='Jane Foo <jane@foo.com>')
1070
 
            branch.tags.set_tag('v1.0rc1', 'rev-3')
1071
 
            branch.tags.set_tag('v1.0', 'rev-3')
1072
 
        return wt
 
912
            b, log.LineLogFormatter)
1073
913
 
1074
914
    def test_line_log_single_merge_revision(self):
1075
915
        wt = self._prepare_tree_with_merges()
1076
 
        logfile = self.make_utf8_encoded_stringio()
1077
 
        formatter = log.LineLogFormatter(to_file=logfile)
1078
916
        revspec = revisionspec.RevisionSpec.from_string('1.1.1')
1079
 
        wtb = wt.branch
1080
 
        rev = revspec.in_history(wtb)
1081
 
        log.show_log(wtb, formatter, start_revision=rev, end_revision=rev)
1082
 
        self.assertEqualDiff("""\
 
917
        rev = revspec.in_history(wt.branch)
 
918
        self.assertFormatterResult("""\
1083
919
1.1.1: Joe Foo 2005-11-22 rev-merged
1084
920
""",
1085
 
                             logfile.getvalue())
 
921
            wt.branch, log.LineLogFormatter,
 
922
            show_log_kwargs=dict(start_revision=rev, end_revision=rev))
1086
923
 
1087
924
    def test_line_log_with_tags(self):
1088
925
        wt = self._prepare_tree_with_merges(with_tags=True)
1089
 
        logfile = self.make_utf8_encoded_stringio()
1090
 
        formatter = log.LineLogFormatter(to_file=logfile)
1091
 
        log.show_log(wt.branch, formatter)
1092
 
        self.assertEqualDiff("""\
 
926
        self.assertFormatterResult("""\
1093
927
3: Jane Foo 2005-11-22 {v1.0, v1.0rc1} rev-3
1094
928
2: Joe Foo 2005-11-22 [merge] {v0.2} rev-2
1095
929
1: Joe Foo 2005-11-22 rev-1
1096
930
""",
1097
 
                             logfile.getvalue())
1098
 
 
1099
 
class TestLineLogFormatterWithMergeRevisions(tests.TestCaseWithTransport):
 
931
            wt.branch, log.LineLogFormatter)
 
932
 
 
933
 
 
934
class TestLineLogFormatterWithMergeRevisions(TestCaseForLogFormatter):
1100
935
 
1101
936
    def test_line_merge_revs_log(self):
1102
937
        """Line log should show revno
1103
938
 
1104
939
        bug #5162
1105
940
        """
1106
 
        wt = self.make_branch_and_tree('.')
1107
 
        b = wt.branch
1108
 
        self.build_tree(['a'])
1109
 
        wt.add('a')
1110
 
        b.nick = 'test-line-log'
1111
 
        wt.commit(message='add a',
1112
 
                  timestamp=1132711707,
1113
 
                  timezone=36000,
1114
 
                  committer='Line-Log-Formatter Tester <test@line.log>')
1115
 
        logfile = file('out.tmp', 'w+')
1116
 
        formatter = log.LineLogFormatter(to_file=logfile, levels=0)
1117
 
        log.show_log(b, formatter)
1118
 
        logfile.flush()
1119
 
        logfile.seek(0)
1120
 
        log_contents = logfile.read()
1121
 
        self.assertEqualDiff('1: Line-Log-Formatte... 2005-11-23 add a\n',
1122
 
                             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)
1123
948
 
1124
949
    def test_line_merge_revs_log_single_merge_revision(self):
1125
950
        wt = self.make_branch_and_memory_tree('.')
1137
962
        wt.commit('rev-2', rev_id='rev-2b',
1138
963
                  timestamp=1132586800, timezone=36000,
1139
964
                  committer='Joe Foo <joe@foo.com>')
1140
 
        logfile = self.make_utf8_encoded_stringio()
1141
 
        formatter = log.LineLogFormatter(to_file=logfile, levels=0)
1142
965
        revspec = revisionspec.RevisionSpec.from_string('1.1.1')
1143
 
        wtb = wt.branch
1144
 
        rev = revspec.in_history(wtb)
1145
 
        log.show_log(wtb, formatter, start_revision=rev, end_revision=rev)
1146
 
        self.assertEqualDiff("""\
 
966
        rev = revspec.in_history(wt.branch)
 
967
        self.assertFormatterResult("""\
1147
968
1.1.1: Joe Foo 2005-11-22 rev-merged
1148
969
""",
1149
 
                             logfile.getvalue())
 
970
            wt.branch, log.LineLogFormatter,
 
971
            formatter_kwargs=dict(levels=0),
 
972
            show_log_kwargs=dict(start_revision=rev, end_revision=rev))
1150
973
 
1151
974
    def test_line_merge_revs_log_with_merges(self):
1152
975
        wt = self.make_branch_and_memory_tree('.')
1164
987
        wt.commit('rev-2', rev_id='rev-2b',
1165
988
                  timestamp=1132586800, timezone=36000,
1166
989
                  committer='Joe Foo <joe@foo.com>')
1167
 
        logfile = self.make_utf8_encoded_stringio()
1168
 
        formatter = log.LineLogFormatter(to_file=logfile, levels=0)
1169
 
        log.show_log(wt.branch, formatter)
1170
 
        self.assertEqualDiff("""\
 
990
        self.assertFormatterResult("""\
1171
991
2: Joe Foo 2005-11-22 [merge] rev-2
1172
992
  1.1.1: Joe Foo 2005-11-22 rev-merged
1173
993
1: Joe Foo 2005-11-22 rev-1
1174
994
""",
1175
 
                             logfile.getvalue())
 
995
            wt.branch, log.LineLogFormatter,
 
996
            formatter_kwargs=dict(levels=0))
 
997
 
1176
998
 
1177
999
class TestGetViewRevisions(tests.TestCaseWithTransport):
1178
1000
 
1198
1020
        # 4a: 3.1.1
1199
1021
        return mainline_revs, rev_nos, wt
1200
1022
 
1201
 
    def make_tree_with_many_merges(self):
 
1023
    def make_branch_with_many_merges(self):
1202
1024
        """Create a tree with well-known revision ids"""
1203
 
        wt = self.make_branch_and_tree('tree1')
1204
 
        self.build_tree_contents([('tree1/f', '1\n')])
1205
 
        wt.add(['f'], ['f-id'])
1206
 
        wt.commit('commit one', rev_id='1')
1207
 
        wt.commit('commit two', rev_id='2')
1208
 
 
1209
 
        tree3 = wt.bzrdir.sprout('tree3').open_workingtree()
1210
 
        self.build_tree_contents([('tree3/f', '1\n2\n3a\n')])
1211
 
        tree3.commit('commit three a', rev_id='3a')
1212
 
 
1213
 
        tree2 = wt.bzrdir.sprout('tree2').open_workingtree()
1214
 
        tree2.merge_from_branch(tree3.branch)
1215
 
        tree2.commit('commit three b', rev_id='3b')
1216
 
 
1217
 
        wt.merge_from_branch(tree2.branch)
1218
 
        wt.commit('commit three c', rev_id='3c')
1219
 
        tree2.commit('four-a', rev_id='4a')
1220
 
 
1221
 
        wt.merge_from_branch(tree2.branch)
1222
 
        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
1223
1052
 
1224
1053
        mainline_revs = [None, '1', '2', '3c', '4b']
1225
1054
        rev_nos = {'1':1, '2':2, '3c': 3, '4b':4}
1232
1061
            '4a': '2.2.2', # second commit tree 2
1233
1062
            '4b': '4', # merges 4a to main
1234
1063
            }
1235
 
        return mainline_revs, rev_nos, wt
 
1064
        return mainline_revs, rev_nos, builder.get_branch()
1236
1065
 
1237
1066
    def test_get_view_revisions_forward(self):
1238
1067
        """Test the get_view_revisions method"""
1298
1127
 
1299
1128
    def test_get_view_revisions_merge2(self):
1300
1129
        """Test get_view_revisions when there are merges"""
1301
 
        mainline_revs, rev_nos, wt = self.make_tree_with_many_merges()
1302
 
        wt.lock_read()
1303
 
        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)
1304
1133
        revisions = list(log.get_view_revisions(
1305
 
                mainline_revs, rev_nos, wt.branch, 'forward'))
 
1134
                mainline_revs, rev_nos, b, 'forward'))
1306
1135
        expected = [('1', '1', 0), ('2', '2', 0), ('3c', '3', 0),
1307
 
                    ('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),
1308
1137
                    ('4a', '2.2.2', 1)]
1309
1138
        self.assertEqual(expected, revisions)
1310
1139
        revisions = list(log.get_view_revisions(
1311
 
                mainline_revs, rev_nos, wt.branch, 'forward',
 
1140
                mainline_revs, rev_nos, b, 'forward',
1312
1141
                include_merges=False))
1313
1142
        self.assertEqual([('1', '1', 0), ('2', '2', 0), ('3c', '3', 0),
1314
1143
                          ('4b', '4', 0)],
1316
1145
 
1317
1146
 
1318
1147
    def test_file_id_for_range(self):
1319
 
        mainline_revs, rev_nos, wt = self.make_tree_with_many_merges()
1320
 
        wt.lock_read()
1321
 
        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)
1322
1151
 
1323
1152
        def rev_from_rev_id(revid, branch):
1324
1153
            revspec = revisionspec.RevisionSpec.from_string('revid:%s' % revid)
1326
1155
 
1327
1156
        def view_revs(start_rev, end_rev, file_id, direction):
1328
1157
            revs = log.calculate_view_revisions(
1329
 
                wt.branch,
 
1158
                b,
1330
1159
                start_rev, # start_revision
1331
1160
                end_rev, # end_revision
1332
1161
                direction, # direction
1335
1164
                )
1336
1165
            return revs
1337
1166
 
1338
 
        rev_3a = rev_from_rev_id('3a', wt.branch)
1339
 
        rev_4b = rev_from_rev_id('4b', wt.branch)
1340
 
        self.assertEqual([('3c', '3', 0), ('3a', '2.1.1', 1)],
 
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)],
1341
1170
                          view_revs(rev_3a, rev_4b, 'f-id', 'reverse'))
1342
1171
        # Note: 3c still appears before 3a here because of depth-based sorting
1343
 
        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)],
1344
1173
                          view_revs(rev_3a, rev_4b, 'f-id', 'forward'))
1345
1174
 
1346
1175
 
1698
1527
        log.show_branch_change(tree.branch, s, 3, '3b')
1699
1528
        self.assertContainsRe(s.getvalue(), 'Removed Revisions:')
1700
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')