~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_log.py

  • Committer: INADA Naoki
  • Date: 2011-05-18 06:01:08 UTC
  • mto: This revision was merged to the branch mainline in revision 5894.
  • Revision ID: songofacandy@gmail.com-20110518060108-86t2kffcrzu0nf6i
Update Japanese docs.

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
18
18
from cStringIO import StringIO
19
19
 
20
20
from bzrlib import (
 
21
    branchbuilder,
21
22
    errors,
22
23
    log,
23
24
    registry,
24
25
    revision,
25
26
    revisionspec,
 
27
    symbol_versioning,
26
28
    tests,
27
29
    )
28
30
 
29
31
 
30
 
class TestCaseWithoutPropsHandler(tests.TestCaseWithTransport):
 
32
class TestLogMixin(object):
 
33
 
 
34
    def wt_commit(self, wt, message, **kwargs):
 
35
        """Use some mostly fixed values for commits to simplify tests.
 
36
 
 
37
        Tests can use this function to get some commit attributes. The time
 
38
        stamp is incremented at each commit.
 
39
        """
 
40
        if getattr(self, 'timestamp', None) is None:
 
41
            self.timestamp = 1132617600 # Mon 2005-11-22 00:00:00 +0000
 
42
        else:
 
43
            self.timestamp += 1 # 1 second between each commit
 
44
        kwargs.setdefault('timestamp', self.timestamp)
 
45
        kwargs.setdefault('timezone', 0) # UTC
 
46
        kwargs.setdefault('committer', 'Joe Foo <joe@foo.com>')
 
47
 
 
48
        return wt.commit(message, **kwargs)
 
49
 
 
50
 
 
51
class TestCaseForLogFormatter(tests.TestCaseWithTransport, TestLogMixin):
31
52
 
32
53
    def setUp(self):
33
 
        super(TestCaseWithoutPropsHandler, self).setUp()
 
54
        super(TestCaseForLogFormatter, self).setUp()
34
55
        # keep a reference to the "current" custom prop. handler registry
35
56
        self.properties_handler_registry = log.properties_handler_registry
36
57
        # Use a clean registry for log
40
61
            log.properties_handler_registry = self.properties_handler_registry
41
62
        self.addCleanup(restore)
42
63
 
 
64
    def assertFormatterResult(self, result, branch, formatter_class,
 
65
                              formatter_kwargs=None, show_log_kwargs=None):
 
66
        logfile = self.make_utf8_encoded_stringio()
 
67
        if formatter_kwargs is None:
 
68
            formatter_kwargs = {}
 
69
        formatter = formatter_class(to_file=logfile, **formatter_kwargs)
 
70
        if show_log_kwargs is None:
 
71
            show_log_kwargs = {}
 
72
        log.show_log(branch, formatter, **show_log_kwargs)
 
73
        self.assertEqualDiff(result, logfile.getvalue())
 
74
 
 
75
    def make_standard_commit(self, branch_nick, **kwargs):
 
76
        wt = self.make_branch_and_tree('.')
 
77
        wt.lock_write()
 
78
        self.addCleanup(wt.unlock)
 
79
        self.build_tree(['a'])
 
80
        wt.add(['a'])
 
81
        wt.branch.nick = branch_nick
 
82
        kwargs.setdefault('committer', 'Lorem Ipsum <test@example.com>')
 
83
        kwargs.setdefault('authors', ['John Doe <jdoe@example.com>'])
 
84
        self.wt_commit(wt, 'add a', **kwargs)
 
85
        return wt
 
86
 
 
87
    def make_commits_with_trailing_newlines(self, wt):
 
88
        """Helper method for LogFormatter tests"""
 
89
        b = wt.branch
 
90
        b.nick = 'test'
 
91
        self.build_tree_contents([('a', 'hello moto\n')])
 
92
        self.wt_commit(wt, 'simple log message', rev_id='a1')
 
93
        self.build_tree_contents([('b', 'goodbye\n')])
 
94
        wt.add('b')
 
95
        self.wt_commit(wt, 'multiline\nlog\nmessage\n', rev_id='a2')
 
96
 
 
97
        self.build_tree_contents([('c', 'just another manic monday\n')])
 
98
        wt.add('c')
 
99
        self.wt_commit(wt, 'single line with trailing newline\n', rev_id='a3')
 
100
        return b
 
101
 
 
102
    def _prepare_tree_with_merges(self, with_tags=False):
 
103
        wt = self.make_branch_and_memory_tree('.')
 
104
        wt.lock_write()
 
105
        self.addCleanup(wt.unlock)
 
106
        wt.add('')
 
107
        self.wt_commit(wt, 'rev-1', rev_id='rev-1')
 
108
        self.wt_commit(wt, 'rev-merged', rev_id='rev-2a')
 
109
        wt.set_parent_ids(['rev-1', 'rev-2a'])
 
110
        wt.branch.set_last_revision_info(1, 'rev-1')
 
111
        self.wt_commit(wt, 'rev-2', rev_id='rev-2b')
 
112
        if with_tags:
 
113
            branch = wt.branch
 
114
            branch.tags.set_tag('v0.2', 'rev-2b')
 
115
            self.wt_commit(wt, 'rev-3', rev_id='rev-3')
 
116
            branch.tags.set_tag('v1.0rc1', 'rev-3')
 
117
            branch.tags.set_tag('v1.0', 'rev-3')
 
118
        return wt
 
119
 
43
120
 
44
121
class LogCatcher(log.LogFormatter):
45
122
    """Pull log messages into a list rather than displaying them.
49
126
    being dependent on the formatting.
50
127
    """
51
128
 
 
129
    supports_merge_revisions = True
52
130
    supports_delta = True
 
131
    supports_diff = True
 
132
    preferred_levels = 0
53
133
 
54
 
    def __init__(self):
55
 
        super(LogCatcher, self).__init__(to_file=None)
 
134
    def __init__(self, *args, **kwargs):
 
135
        kwargs.update(dict(to_file=None))
 
136
        super(LogCatcher, self).__init__(*args, **kwargs)
56
137
        self.revisions = []
57
138
 
58
139
    def log_revision(self, revision):
201
282
        self.checkDelta(logentry.delta, added=['file1', 'file2'])
202
283
 
203
284
 
204
 
def make_commits_with_trailing_newlines(wt):
205
 
    """Helper method for LogFormatter tests"""
206
 
    b = wt.branch
207
 
    b.nick='test'
208
 
    open('a', 'wb').write('hello moto\n')
209
 
    wt.add('a')
210
 
    wt.commit('simple log message', rev_id='a1',
211
 
              timestamp=1132586655.459960938, timezone=-6*3600,
212
 
              committer='Joe Foo <joe@foo.com>')
213
 
    open('b', 'wb').write('goodbye\n')
214
 
    wt.add('b')
215
 
    wt.commit('multiline\nlog\nmessage\n', rev_id='a2',
216
 
              timestamp=1132586842.411175966, timezone=-6*3600,
217
 
              committer='Joe Foo <joe@foo.com>',
218
 
              authors=['Joe Bar <joe@bar.com>'])
219
 
 
220
 
    open('c', 'wb').write('just another manic monday\n')
221
 
    wt.add('c')
222
 
    wt.commit('single line with trailing newline\n', rev_id='a3',
223
 
              timestamp=1132587176.835228920, timezone=-6*3600,
224
 
              committer = 'Joe Foo <joe@foo.com>')
225
 
    return b
226
 
 
227
 
 
228
 
def normalize_log(log):
229
 
    """Replaces the variable lines of logs with fixed lines"""
230
 
    author = 'author: Dolor Sit <test@example.com>'
231
 
    committer = 'committer: Lorem Ipsum <test@example.com>'
232
 
    lines = log.splitlines(True)
233
 
    for idx,line in enumerate(lines):
234
 
        stripped_line = line.lstrip()
235
 
        indent = ' ' * (len(line) - len(stripped_line))
236
 
        if stripped_line.startswith('author:'):
237
 
            lines[idx] = indent + author + '\n'
238
 
        elif stripped_line.startswith('committer:'):
239
 
            lines[idx] = indent + committer + '\n'
240
 
        elif stripped_line.startswith('timestamp:'):
241
 
            lines[idx] = indent + 'timestamp: Just now\n'
242
 
    return ''.join(lines)
243
 
 
244
 
 
245
 
class TestShortLogFormatter(tests.TestCaseWithTransport):
 
285
class TestShortLogFormatter(TestCaseForLogFormatter):
246
286
 
247
287
    def test_trailing_newlines(self):
248
288
        wt = self.make_branch_and_tree('.')
249
 
        b = make_commits_with_trailing_newlines(wt)
250
 
        sio = self.make_utf8_encoded_stringio()
251
 
        lf = log.ShortLogFormatter(to_file=sio)
252
 
        log.show_log(b, lf)
253
 
        self.assertEqualDiff("""\
254
 
    3 Joe Foo\t2005-11-21
 
289
        b = self.make_commits_with_trailing_newlines(wt)
 
290
        self.assertFormatterResult("""\
 
291
    3 Joe Foo\t2005-11-22
255
292
      single line with trailing newline
256
293
 
257
 
    2 Joe Bar\t2005-11-21
 
294
    2 Joe Foo\t2005-11-22
258
295
      multiline
259
296
      log
260
297
      message
261
298
 
262
 
    1 Joe Foo\t2005-11-21
 
299
    1 Joe Foo\t2005-11-22
263
300
      simple log message
264
301
 
265
302
""",
266
 
                             sio.getvalue())
267
 
 
268
 
    def _prepare_tree_with_merges(self, with_tags=False):
269
 
        wt = self.make_branch_and_memory_tree('.')
270
 
        wt.lock_write()
271
 
        self.addCleanup(wt.unlock)
272
 
        wt.add('')
273
 
        wt.commit('rev-1', rev_id='rev-1',
274
 
                  timestamp=1132586655, timezone=36000,
275
 
                  committer='Joe Foo <joe@foo.com>')
276
 
        wt.commit('rev-merged', rev_id='rev-2a',
277
 
                  timestamp=1132586700, timezone=36000,
278
 
                  committer='Joe Foo <joe@foo.com>')
279
 
        wt.set_parent_ids(['rev-1', 'rev-2a'])
280
 
        wt.branch.set_last_revision_info(1, 'rev-1')
281
 
        wt.commit('rev-2', rev_id='rev-2b',
282
 
                  timestamp=1132586800, timezone=36000,
283
 
                  committer='Joe Foo <joe@foo.com>')
284
 
        if with_tags:
285
 
            branch = wt.branch
286
 
            branch.tags.set_tag('v0.2', 'rev-2b')
287
 
            wt.commit('rev-3', rev_id='rev-3',
288
 
                      timestamp=1132586900, timezone=36000,
289
 
                      committer='Jane Foo <jane@foo.com>')
290
 
            branch.tags.set_tag('v1.0rc1', 'rev-3')
291
 
            branch.tags.set_tag('v1.0', 'rev-3')
292
 
        return wt
 
303
            b, log.ShortLogFormatter)
293
304
 
294
305
    def test_short_log_with_merges(self):
295
306
        wt = self._prepare_tree_with_merges()
296
 
        logfile = self.make_utf8_encoded_stringio()
297
 
        formatter = log.ShortLogFormatter(to_file=logfile)
298
 
        log.show_log(wt.branch, formatter)
299
 
        self.assertEqualDiff("""\
 
307
        self.assertFormatterResult("""\
300
308
    2 Joe Foo\t2005-11-22 [merge]
301
309
      rev-2
302
310
 
304
312
      rev-1
305
313
 
306
314
""",
307
 
                             logfile.getvalue())
 
315
            wt.branch, log.ShortLogFormatter)
308
316
 
309
317
    def test_short_log_with_merges_and_advice(self):
310
318
        wt = self._prepare_tree_with_merges()
311
 
        logfile = self.make_utf8_encoded_stringio()
312
 
        formatter = log.ShortLogFormatter(to_file=logfile,
313
 
            show_advice=True)
314
 
        log.show_log(wt.branch, formatter)
315
 
        self.assertEqualDiff("""\
 
319
        self.assertFormatterResult("""\
316
320
    2 Joe Foo\t2005-11-22 [merge]
317
321
      rev-2
318
322
 
321
325
 
322
326
Use --include-merges or -n0 to see merged revisions.
323
327
""",
324
 
                             logfile.getvalue())
 
328
            wt.branch, log.ShortLogFormatter,
 
329
            formatter_kwargs=dict(show_advice=True))
325
330
 
326
331
    def test_short_log_with_merges_and_range(self):
327
 
        wt = self.make_branch_and_memory_tree('.')
328
 
        wt.lock_write()
329
 
        self.addCleanup(wt.unlock)
330
 
        wt.add('')
331
 
        wt.commit('rev-1', rev_id='rev-1',
332
 
                  timestamp=1132586655, timezone=36000,
333
 
                  committer='Joe Foo <joe@foo.com>')
334
 
        wt.commit('rev-merged', rev_id='rev-2a',
335
 
                  timestamp=1132586700, timezone=36000,
336
 
                  committer='Joe Foo <joe@foo.com>')
337
 
        wt.branch.set_last_revision_info(1, 'rev-1')
338
 
        wt.set_parent_ids(['rev-1', 'rev-2a'])
339
 
        wt.commit('rev-2b', rev_id='rev-2b',
340
 
                  timestamp=1132586800, timezone=36000,
341
 
                  committer='Joe Foo <joe@foo.com>')
342
 
        wt.commit('rev-3a', rev_id='rev-3a',
343
 
                  timestamp=1132586800, timezone=36000,
344
 
                  committer='Joe Foo <joe@foo.com>')
 
332
        wt = self._prepare_tree_with_merges()
 
333
        self.wt_commit(wt, 'rev-3a', rev_id='rev-3a')
345
334
        wt.branch.set_last_revision_info(2, 'rev-2b')
346
335
        wt.set_parent_ids(['rev-2b', 'rev-3a'])
347
 
        wt.commit('rev-3b', rev_id='rev-3b',
348
 
                  timestamp=1132586800, timezone=36000,
349
 
                  committer='Joe Foo <joe@foo.com>')
350
 
        logfile = self.make_utf8_encoded_stringio()
351
 
        formatter = log.ShortLogFormatter(to_file=logfile)
352
 
        log.show_log(wt.branch, formatter,
353
 
            start_revision=2, end_revision=3)
354
 
        self.assertEqualDiff("""\
 
336
        self.wt_commit(wt, 'rev-3b', rev_id='rev-3b')
 
337
        self.assertFormatterResult("""\
355
338
    3 Joe Foo\t2005-11-22 [merge]
356
339
      rev-3b
357
340
 
358
341
    2 Joe Foo\t2005-11-22 [merge]
359
 
      rev-2b
 
342
      rev-2
360
343
 
361
344
""",
362
 
                             logfile.getvalue())
 
345
            wt.branch, log.ShortLogFormatter,
 
346
            show_log_kwargs=dict(start_revision=2, end_revision=3))
363
347
 
364
348
    def test_short_log_with_tags(self):
365
349
        wt = self._prepare_tree_with_merges(with_tags=True)
366
 
        logfile = self.make_utf8_encoded_stringio()
367
 
        formatter = log.ShortLogFormatter(to_file=logfile)
368
 
        log.show_log(wt.branch, formatter)
369
 
        self.assertEqualDiff("""\
370
 
    3 Jane Foo\t2005-11-22 {v1.0, v1.0rc1}
 
350
        self.assertFormatterResult("""\
 
351
    3 Joe Foo\t2005-11-22 {v1.0, v1.0rc1}
371
352
      rev-3
372
353
 
373
354
    2 Joe Foo\t2005-11-22 {v0.2} [merge]
377
358
      rev-1
378
359
 
379
360
""",
380
 
                             logfile.getvalue())
 
361
            wt.branch, log.ShortLogFormatter)
381
362
 
382
363
    def test_short_log_single_merge_revision(self):
383
 
        wt = self.make_branch_and_memory_tree('.')
384
 
        wt.lock_write()
385
 
        self.addCleanup(wt.unlock)
386
 
        wt.add('')
387
 
        wt.commit('rev-1', rev_id='rev-1',
388
 
                  timestamp=1132586655, timezone=36000,
389
 
                  committer='Joe Foo <joe@foo.com>')
390
 
        wt.commit('rev-merged', rev_id='rev-2a',
391
 
                  timestamp=1132586700, timezone=36000,
392
 
                  committer='Joe Foo <joe@foo.com>')
393
 
        wt.set_parent_ids(['rev-1', 'rev-2a'])
394
 
        wt.branch.set_last_revision_info(1, 'rev-1')
395
 
        wt.commit('rev-2', rev_id='rev-2b',
396
 
                  timestamp=1132586800, timezone=36000,
397
 
                  committer='Joe Foo <joe@foo.com>')
398
 
        logfile = self.make_utf8_encoded_stringio()
399
 
        formatter = log.ShortLogFormatter(to_file=logfile)
 
364
        wt = self._prepare_tree_with_merges()
400
365
        revspec = revisionspec.RevisionSpec.from_string('1.1.1')
401
 
        wtb = wt.branch
402
 
        rev = revspec.in_history(wtb)
403
 
        log.show_log(wtb, formatter, start_revision=rev, end_revision=rev)
404
 
        self.assertEqualDiff("""\
 
366
        rev = revspec.in_history(wt.branch)
 
367
        self.assertFormatterResult("""\
405
368
      1.1.1 Joe Foo\t2005-11-22
406
369
            rev-merged
407
370
 
408
371
""",
409
 
                             logfile.getvalue())
410
 
 
411
 
 
412
 
class TestShortLogFormatterWithMergeRevisions(tests.TestCaseWithTransport):
 
372
            wt.branch, log.ShortLogFormatter,
 
373
            show_log_kwargs=dict(start_revision=rev, end_revision=rev))
 
374
 
 
375
    def test_show_ids(self):
 
376
        wt = self.make_branch_and_tree('parent')
 
377
        self.build_tree(['parent/f1', 'parent/f2'])
 
378
        wt.add(['f1','f2'])
 
379
        self.wt_commit(wt, 'first post', rev_id='a')
 
380
        child_wt = wt.bzrdir.sprout('child').open_workingtree()
 
381
        self.wt_commit(child_wt, 'branch 1 changes', rev_id='b')
 
382
        wt.merge_from_branch(child_wt.branch)
 
383
        self.wt_commit(wt, 'merge branch 1', rev_id='c')
 
384
        self.assertFormatterResult("""\
 
385
    2 Joe Foo\t2005-11-22 [merge]
 
386
      revision-id:c
 
387
      merge branch 1
 
388
 
 
389
          1.1.1 Joe Foo\t2005-11-22
 
390
                revision-id:b
 
391
                branch 1 changes
 
392
 
 
393
    1 Joe Foo\t2005-11-22
 
394
      revision-id:a
 
395
      first post
 
396
 
 
397
""",
 
398
            wt.branch, log.ShortLogFormatter,
 
399
            formatter_kwargs=dict(levels=0,show_ids=True))
 
400
 
 
401
 
 
402
class TestShortLogFormatterWithMergeRevisions(TestCaseForLogFormatter):
413
403
 
414
404
    def test_short_merge_revs_log_with_merges(self):
415
 
        wt = self.make_branch_and_memory_tree('.')
416
 
        wt.lock_write()
417
 
        self.addCleanup(wt.unlock)
418
 
        wt.add('')
419
 
        wt.commit('rev-1', rev_id='rev-1',
420
 
                  timestamp=1132586655, timezone=36000,
421
 
                  committer='Joe Foo <joe@foo.com>')
422
 
        wt.commit('rev-merged', rev_id='rev-2a',
423
 
                  timestamp=1132586700, timezone=36000,
424
 
                  committer='Joe Foo <joe@foo.com>')
425
 
        wt.set_parent_ids(['rev-1', 'rev-2a'])
426
 
        wt.branch.set_last_revision_info(1, 'rev-1')
427
 
        wt.commit('rev-2', rev_id='rev-2b',
428
 
                  timestamp=1132586800, timezone=36000,
429
 
                  committer='Joe Foo <joe@foo.com>')
430
 
        logfile = self.make_utf8_encoded_stringio()
431
 
        formatter = log.ShortLogFormatter(to_file=logfile, levels=0)
432
 
        log.show_log(wt.branch, formatter)
 
405
        wt = self._prepare_tree_with_merges()
433
406
        # Note that the 1.1.1 indenting is in fact correct given that
434
407
        # the revision numbers are right justified within 5 characters
435
408
        # for mainline revnos and 9 characters for dotted revnos.
436
 
        self.assertEqualDiff("""\
 
409
        self.assertFormatterResult("""\
437
410
    2 Joe Foo\t2005-11-22 [merge]
438
411
      rev-2
439
412
 
444
417
      rev-1
445
418
 
446
419
""",
447
 
                             logfile.getvalue())
 
420
            wt.branch, log.ShortLogFormatter,
 
421
            formatter_kwargs=dict(levels=0))
448
422
 
449
423
    def test_short_merge_revs_log_single_merge_revision(self):
450
 
        wt = self.make_branch_and_memory_tree('.')
451
 
        wt.lock_write()
452
 
        self.addCleanup(wt.unlock)
453
 
        wt.add('')
454
 
        wt.commit('rev-1', rev_id='rev-1',
455
 
                  timestamp=1132586655, timezone=36000,
456
 
                  committer='Joe Foo <joe@foo.com>')
457
 
        wt.commit('rev-merged', rev_id='rev-2a',
458
 
                  timestamp=1132586700, timezone=36000,
459
 
                  committer='Joe Foo <joe@foo.com>')
460
 
        wt.set_parent_ids(['rev-1', 'rev-2a'])
461
 
        wt.branch.set_last_revision_info(1, 'rev-1')
462
 
        wt.commit('rev-2', rev_id='rev-2b',
463
 
                  timestamp=1132586800, timezone=36000,
464
 
                  committer='Joe Foo <joe@foo.com>')
465
 
        logfile = self.make_utf8_encoded_stringio()
466
 
        formatter = log.ShortLogFormatter(to_file=logfile, levels=0)
 
424
        wt = self._prepare_tree_with_merges()
467
425
        revspec = revisionspec.RevisionSpec.from_string('1.1.1')
468
 
        wtb = wt.branch
469
 
        rev = revspec.in_history(wtb)
470
 
        log.show_log(wtb, formatter, start_revision=rev, end_revision=rev)
471
 
        self.assertEqualDiff("""\
 
426
        rev = revspec.in_history(wt.branch)
 
427
        self.assertFormatterResult("""\
472
428
      1.1.1 Joe Foo\t2005-11-22
473
429
            rev-merged
474
430
 
475
431
""",
476
 
                             logfile.getvalue())
477
 
 
478
 
 
479
 
class TestLongLogFormatter(TestCaseWithoutPropsHandler):
 
432
            wt.branch, log.ShortLogFormatter,
 
433
            formatter_kwargs=dict(levels=0),
 
434
            show_log_kwargs=dict(start_revision=rev, end_revision=rev))
 
435
 
 
436
 
 
437
class TestLongLogFormatter(TestCaseForLogFormatter):
480
438
 
481
439
    def test_verbose_log(self):
482
440
        """Verbose log includes changed files
483
441
 
484
442
        bug #4676
485
443
        """
486
 
        wt = self.make_branch_and_tree('.')
487
 
        b = wt.branch
488
 
        self.build_tree(['a'])
489
 
        wt.add('a')
490
 
        # XXX: why does a longer nick show up?
491
 
        b.nick = 'test_verbose_log'
492
 
        wt.commit(message='add a',
493
 
                  timestamp=1132711707,
494
 
                  timezone=36000,
495
 
                  committer='Lorem Ipsum <test@example.com>')
496
 
        logfile = file('out.tmp', 'w+')
497
 
        formatter = log.LongLogFormatter(to_file=logfile)
498
 
        log.show_log(b, formatter, verbose=True)
499
 
        logfile.flush()
500
 
        logfile.seek(0)
501
 
        log_contents = logfile.read()
502
 
        self.assertEqualDiff('''\
 
444
        wt = self.make_standard_commit('test_verbose_log', authors=[])
 
445
        self.assertFormatterResult('''\
503
446
------------------------------------------------------------
504
447
revno: 1
505
448
committer: Lorem Ipsum <test@example.com>
506
449
branch nick: test_verbose_log
507
 
timestamp: Wed 2005-11-23 12:08:27 +1000
 
450
timestamp: Tue 2005-11-22 00:00:00 +0000
508
451
message:
509
452
  add a
510
453
added:
511
454
  a
512
455
''',
513
 
                             log_contents)
 
456
            wt.branch, log.LongLogFormatter,
 
457
            show_log_kwargs=dict(verbose=True))
514
458
 
515
459
    def test_merges_are_indented_by_level(self):
516
460
        wt = self.make_branch_and_tree('parent')
517
 
        wt.commit('first post')
518
 
        self.run_bzr('branch parent child')
519
 
        self.run_bzr(['commit', '-m', 'branch 1', '--unchanged', 'child'])
520
 
        self.run_bzr('branch child smallerchild')
521
 
        self.run_bzr(['commit', '-m', 'branch 2', '--unchanged',
522
 
            'smallerchild'])
523
 
        os.chdir('child')
524
 
        self.run_bzr('merge ../smallerchild')
525
 
        self.run_bzr(['commit', '-m', 'merge branch 2'])
526
 
        os.chdir('../parent')
527
 
        self.run_bzr('merge ../child')
528
 
        wt.commit('merge branch 1')
529
 
        b = wt.branch
530
 
        sio = self.make_utf8_encoded_stringio()
531
 
        lf = log.LongLogFormatter(to_file=sio, levels=0)
532
 
        log.show_log(b, lf, verbose=True)
533
 
        the_log = normalize_log(sio.getvalue())
534
 
        self.assertEqualDiff("""\
 
461
        self.wt_commit(wt, 'first post')
 
462
        child_wt = wt.bzrdir.sprout('child').open_workingtree()
 
463
        self.wt_commit(child_wt, 'branch 1')
 
464
        smallerchild_wt = wt.bzrdir.sprout('smallerchild').open_workingtree()
 
465
        self.wt_commit(smallerchild_wt, 'branch 2')
 
466
        child_wt.merge_from_branch(smallerchild_wt.branch)
 
467
        self.wt_commit(child_wt, 'merge branch 2')
 
468
        wt.merge_from_branch(child_wt.branch)
 
469
        self.wt_commit(wt, 'merge branch 1')
 
470
        self.assertFormatterResult("""\
535
471
------------------------------------------------------------
536
472
revno: 2 [merge]
537
 
committer: Lorem Ipsum <test@example.com>
 
473
committer: Joe Foo <joe@foo.com>
538
474
branch nick: parent
539
 
timestamp: Just now
 
475
timestamp: Tue 2005-11-22 00:00:04 +0000
540
476
message:
541
477
  merge branch 1
542
478
    ------------------------------------------------------------
543
479
    revno: 1.1.2 [merge]
544
 
    committer: Lorem Ipsum <test@example.com>
 
480
    committer: Joe Foo <joe@foo.com>
545
481
    branch nick: child
546
 
    timestamp: Just now
 
482
    timestamp: Tue 2005-11-22 00:00:03 +0000
547
483
    message:
548
484
      merge branch 2
549
485
        ------------------------------------------------------------
550
486
        revno: 1.2.1
551
 
        committer: Lorem Ipsum <test@example.com>
 
487
        committer: Joe Foo <joe@foo.com>
552
488
        branch nick: smallerchild
553
 
        timestamp: Just now
 
489
        timestamp: Tue 2005-11-22 00:00:02 +0000
554
490
        message:
555
491
          branch 2
556
492
    ------------------------------------------------------------
557
493
    revno: 1.1.1
558
 
    committer: Lorem Ipsum <test@example.com>
 
494
    committer: Joe Foo <joe@foo.com>
559
495
    branch nick: child
560
 
    timestamp: Just now
 
496
    timestamp: Tue 2005-11-22 00:00:01 +0000
561
497
    message:
562
498
      branch 1
563
499
------------------------------------------------------------
564
500
revno: 1
565
 
committer: Lorem Ipsum <test@example.com>
 
501
committer: Joe Foo <joe@foo.com>
566
502
branch nick: parent
567
 
timestamp: Just now
 
503
timestamp: Tue 2005-11-22 00:00:00 +0000
568
504
message:
569
505
  first post
570
506
""",
571
 
                             the_log)
 
507
            wt.branch, log.LongLogFormatter,
 
508
            formatter_kwargs=dict(levels=0),
 
509
            show_log_kwargs=dict(verbose=True))
572
510
 
573
511
    def test_verbose_merge_revisions_contain_deltas(self):
574
512
        wt = self.make_branch_and_tree('parent')
575
513
        self.build_tree(['parent/f1', 'parent/f2'])
576
514
        wt.add(['f1','f2'])
577
 
        wt.commit('first post')
578
 
        self.run_bzr('branch parent child')
 
515
        self.wt_commit(wt, 'first post')
 
516
        child_wt = wt.bzrdir.sprout('child').open_workingtree()
579
517
        os.unlink('child/f1')
580
 
        file('child/f2', 'wb').write('hello\n')
581
 
        self.run_bzr(['commit', '-m', 'removed f1 and modified f2',
582
 
            'child'])
583
 
        os.chdir('parent')
584
 
        self.run_bzr('merge ../child')
585
 
        wt.commit('merge branch 1')
586
 
        b = wt.branch
587
 
        sio = self.make_utf8_encoded_stringio()
588
 
        lf = log.LongLogFormatter(to_file=sio, levels=0)
589
 
        log.show_log(b, lf, verbose=True)
590
 
        the_log = normalize_log(sio.getvalue())
591
 
        self.assertEqualDiff("""\
 
518
        self.build_tree_contents([('child/f2', 'hello\n')])
 
519
        self.wt_commit(child_wt, 'removed f1 and modified f2')
 
520
        wt.merge_from_branch(child_wt.branch)
 
521
        self.wt_commit(wt, 'merge branch 1')
 
522
        self.assertFormatterResult("""\
592
523
------------------------------------------------------------
593
524
revno: 2 [merge]
594
 
committer: Lorem Ipsum <test@example.com>
 
525
committer: Joe Foo <joe@foo.com>
595
526
branch nick: parent
596
 
timestamp: Just now
 
527
timestamp: Tue 2005-11-22 00:00:02 +0000
597
528
message:
598
529
  merge branch 1
599
530
removed:
602
533
  f2
603
534
    ------------------------------------------------------------
604
535
    revno: 1.1.1
605
 
    committer: Lorem Ipsum <test@example.com>
 
536
    committer: Joe Foo <joe@foo.com>
606
537
    branch nick: child
607
 
    timestamp: Just now
 
538
    timestamp: Tue 2005-11-22 00:00:01 +0000
608
539
    message:
609
540
      removed f1 and modified f2
610
541
    removed:
613
544
      f2
614
545
------------------------------------------------------------
615
546
revno: 1
616
 
committer: Lorem Ipsum <test@example.com>
 
547
committer: Joe Foo <joe@foo.com>
617
548
branch nick: parent
618
 
timestamp: Just now
 
549
timestamp: Tue 2005-11-22 00:00:00 +0000
619
550
message:
620
551
  first post
621
552
added:
622
553
  f1
623
554
  f2
624
555
""",
625
 
                             the_log)
 
556
            wt.branch, log.LongLogFormatter,
 
557
            formatter_kwargs=dict(levels=0),
 
558
            show_log_kwargs=dict(verbose=True))
626
559
 
627
560
    def test_trailing_newlines(self):
628
561
        wt = self.make_branch_and_tree('.')
629
 
        b = make_commits_with_trailing_newlines(wt)
630
 
        sio = self.make_utf8_encoded_stringio()
631
 
        lf = log.LongLogFormatter(to_file=sio)
632
 
        log.show_log(b, lf)
633
 
        self.assertEqualDiff("""\
 
562
        b = self.make_commits_with_trailing_newlines(wt)
 
563
        self.assertFormatterResult("""\
634
564
------------------------------------------------------------
635
565
revno: 3
636
566
committer: Joe Foo <joe@foo.com>
637
567
branch nick: test
638
 
timestamp: Mon 2005-11-21 09:32:56 -0600
 
568
timestamp: Tue 2005-11-22 00:00:02 +0000
639
569
message:
640
570
  single line with trailing newline
641
571
------------------------------------------------------------
642
572
revno: 2
643
 
author: Joe Bar <joe@bar.com>
644
573
committer: Joe Foo <joe@foo.com>
645
574
branch nick: test
646
 
timestamp: Mon 2005-11-21 09:27:22 -0600
 
575
timestamp: Tue 2005-11-22 00:00:01 +0000
647
576
message:
648
577
  multiline
649
578
  log
652
581
revno: 1
653
582
committer: Joe Foo <joe@foo.com>
654
583
branch nick: test
655
 
timestamp: Mon 2005-11-21 09:24:15 -0600
 
584
timestamp: Tue 2005-11-22 00:00:00 +0000
656
585
message:
657
586
  simple log message
658
587
""",
659
 
                             sio.getvalue())
 
588
        b, log.LongLogFormatter)
660
589
 
661
590
    def test_author_in_log(self):
662
591
        """Log includes the author name if it's set in
663
592
        the revision properties
664
593
        """
665
 
        wt = self.make_branch_and_tree('.')
666
 
        b = wt.branch
667
 
        self.build_tree(['a'])
668
 
        wt.add('a')
669
 
        b.nick = 'test_author_log'
670
 
        wt.commit(message='add a',
671
 
                  timestamp=1132711707,
672
 
                  timezone=36000,
673
 
                  committer='Lorem Ipsum <test@example.com>',
674
 
                  authors=['John Doe <jdoe@example.com>',
675
 
                           'Jane Rey <jrey@example.com>'])
676
 
        sio = StringIO()
677
 
        formatter = log.LongLogFormatter(to_file=sio)
678
 
        log.show_log(b, formatter)
679
 
        self.assertEqualDiff('''\
 
594
        wt = self.make_standard_commit('test_author_log',
 
595
            authors=['John Doe <jdoe@example.com>',
 
596
                     'Jane Rey <jrey@example.com>'])
 
597
        self.assertFormatterResult("""\
680
598
------------------------------------------------------------
681
599
revno: 1
682
600
author: John Doe <jdoe@example.com>, Jane Rey <jrey@example.com>
683
601
committer: Lorem Ipsum <test@example.com>
684
602
branch nick: test_author_log
685
 
timestamp: Wed 2005-11-23 12:08:27 +1000
 
603
timestamp: Tue 2005-11-22 00:00:00 +0000
686
604
message:
687
605
  add a
688
 
''',
689
 
                             sio.getvalue())
 
606
""",
 
607
        wt.branch, log.LongLogFormatter)
690
608
 
691
609
    def test_properties_in_log(self):
692
610
        """Log includes the custom properties returned by the registered
693
611
        handlers.
694
612
        """
695
 
        wt = self.make_branch_and_tree('.')
696
 
        b = wt.branch
697
 
        self.build_tree(['a'])
698
 
        wt.add('a')
699
 
        b.nick = 'test_properties_in_log'
700
 
        wt.commit(message='add a',
701
 
                  timestamp=1132711707,
702
 
                  timezone=36000,
703
 
                  committer='Lorem Ipsum <test@example.com>',
704
 
                  authors=['John Doe <jdoe@example.com>'])
705
 
        sio = StringIO()
706
 
        formatter = log.LongLogFormatter(to_file=sio)
707
 
        try:
708
 
            def trivial_custom_prop_handler(revision):
709
 
                return {'test_prop':'test_value'}
 
613
        wt = self.make_standard_commit('test_properties_in_log')
 
614
        def trivial_custom_prop_handler(revision):
 
615
            return {'test_prop':'test_value'}
710
616
 
711
 
            log.properties_handler_registry.register(
712
 
                'trivial_custom_prop_handler',
713
 
                trivial_custom_prop_handler)
714
 
            log.show_log(b, formatter)
715
 
        finally:
716
 
            log.properties_handler_registry.remove(
717
 
                'trivial_custom_prop_handler')
718
 
            self.assertEqualDiff('''\
 
617
        # Cleaned up in setUp()
 
618
        log.properties_handler_registry.register(
 
619
            'trivial_custom_prop_handler',
 
620
            trivial_custom_prop_handler)
 
621
        self.assertFormatterResult("""\
719
622
------------------------------------------------------------
720
623
revno: 1
721
624
test_prop: test_value
722
625
author: John Doe <jdoe@example.com>
723
626
committer: Lorem Ipsum <test@example.com>
724
627
branch nick: test_properties_in_log
725
 
timestamp: Wed 2005-11-23 12:08:27 +1000
 
628
timestamp: Tue 2005-11-22 00:00:00 +0000
726
629
message:
727
630
  add a
728
 
''',
729
 
                                 sio.getvalue())
 
631
""",
 
632
            wt.branch, log.LongLogFormatter)
730
633
 
731
634
    def test_properties_in_short_log(self):
732
635
        """Log includes the custom properties returned by the registered
733
636
        handlers.
734
637
        """
735
 
        wt = self.make_branch_and_tree('.')
736
 
        b = wt.branch
737
 
        self.build_tree(['a'])
738
 
        wt.add('a')
739
 
        b.nick = 'test_properties_in_short_log'
740
 
        wt.commit(message='add a',
741
 
                  timestamp=1132711707,
742
 
                  timezone=36000,
743
 
                  committer='Lorem Ipsum <test@example.com>',
744
 
                  authors=['John Doe <jdoe@example.com>'])
745
 
        sio = StringIO()
746
 
        formatter = log.ShortLogFormatter(to_file=sio)
747
 
        try:
748
 
            def trivial_custom_prop_handler(revision):
749
 
                return {'test_prop':'test_value'}
 
638
        wt = self.make_standard_commit('test_properties_in_short_log')
 
639
        def trivial_custom_prop_handler(revision):
 
640
            return {'test_prop':'test_value'}
750
641
 
751
 
            log.properties_handler_registry.register(
752
 
                'trivial_custom_prop_handler',
753
 
                trivial_custom_prop_handler)
754
 
            log.show_log(b, formatter)
755
 
        finally:
756
 
            log.properties_handler_registry.remove(
757
 
                'trivial_custom_prop_handler')
758
 
            self.assertEqualDiff('''\
759
 
    1 John Doe\t2005-11-23
 
642
        log.properties_handler_registry.register(
 
643
            'trivial_custom_prop_handler',
 
644
            trivial_custom_prop_handler)
 
645
        self.assertFormatterResult("""\
 
646
    1 John Doe\t2005-11-22
760
647
      test_prop: test_value
761
648
      add a
762
649
 
763
 
''',
764
 
                                 sio.getvalue())
 
650
""",
 
651
            wt.branch, log.ShortLogFormatter)
765
652
 
766
653
    def test_error_in_properties_handler(self):
767
654
        """Log includes the custom properties returned by the registered
768
655
        handlers.
769
656
        """
770
 
        wt = self.make_branch_and_tree('.')
771
 
        b = wt.branch
772
 
        self.build_tree(['a'])
773
 
        wt.add('a')
774
 
        b.nick = 'test_author_log'
775
 
        wt.commit(message='add a',
776
 
                  timestamp=1132711707,
777
 
                  timezone=36000,
778
 
                  committer='Lorem Ipsum <test@example.com>',
779
 
                  authors=['John Doe <jdoe@example.com>'],
780
 
                  revprops={'first_prop':'first_value'})
781
 
        sio = StringIO()
 
657
        wt = self.make_standard_commit('error_in_properties_handler',
 
658
            revprops={'first_prop':'first_value'})
 
659
        sio = self.make_utf8_encoded_stringio()
782
660
        formatter = log.LongLogFormatter(to_file=sio)
783
 
        try:
784
 
            def trivial_custom_prop_handler(revision):
785
 
                raise StandardError("a test error")
 
661
        def trivial_custom_prop_handler(revision):
 
662
            raise StandardError("a test error")
786
663
 
787
 
            log.properties_handler_registry.register(
788
 
                'trivial_custom_prop_handler',
789
 
                trivial_custom_prop_handler)
790
 
            self.assertRaises(StandardError, log.show_log, b, formatter,)
791
 
        finally:
792
 
            log.properties_handler_registry.remove(
793
 
                'trivial_custom_prop_handler')
 
664
        log.properties_handler_registry.register(
 
665
            'trivial_custom_prop_handler',
 
666
            trivial_custom_prop_handler)
 
667
        self.assertRaises(StandardError, log.show_log, wt.branch, formatter,)
794
668
 
795
669
    def test_properties_handler_bad_argument(self):
796
 
        wt = self.make_branch_and_tree('.')
797
 
        b = wt.branch
798
 
        self.build_tree(['a'])
799
 
        wt.add('a')
800
 
        b.nick = 'test_author_log'
801
 
        wt.commit(message='add a',
802
 
                  timestamp=1132711707,
803
 
                  timezone=36000,
804
 
                  committer='Lorem Ipsum <test@example.com>',
805
 
                  authors=['John Doe <jdoe@example.com>'],
806
 
                  revprops={'a_prop':'test_value'})
807
 
        sio = StringIO()
 
670
        wt = self.make_standard_commit('bad_argument',
 
671
              revprops={'a_prop':'test_value'})
 
672
        sio = self.make_utf8_encoded_stringio()
808
673
        formatter = log.LongLogFormatter(to_file=sio)
809
 
        try:
810
 
            def bad_argument_prop_handler(revision):
811
 
                return {'custom_prop_name':revision.properties['a_prop']}
812
 
 
813
 
            log.properties_handler_registry.register(
814
 
                'bad_argument_prop_handler',
815
 
                bad_argument_prop_handler)
816
 
 
817
 
            self.assertRaises(AttributeError, formatter.show_properties,
818
 
                              'a revision', '')
819
 
 
820
 
            revision = b.repository.get_revision(b.last_revision())
821
 
            formatter.show_properties(revision, '')
822
 
            self.assertEqualDiff('''custom_prop_name: test_value\n''',
823
 
                                 sio.getvalue())
824
 
        finally:
825
 
            log.properties_handler_registry.remove(
826
 
                'bad_argument_prop_handler')
827
 
 
828
 
 
829
 
class TestLongLogFormatterWithoutMergeRevisions(TestCaseWithoutPropsHandler):
 
674
        def bad_argument_prop_handler(revision):
 
675
            return {'custom_prop_name':revision.properties['a_prop']}
 
676
 
 
677
        log.properties_handler_registry.register(
 
678
            'bad_argument_prop_handler',
 
679
            bad_argument_prop_handler)
 
680
 
 
681
        self.assertRaises(AttributeError, formatter.show_properties,
 
682
                          'a revision', '')
 
683
 
 
684
        revision = wt.branch.repository.get_revision(wt.branch.last_revision())
 
685
        formatter.show_properties(revision, '')
 
686
        self.assertEqualDiff('''custom_prop_name: test_value\n''',
 
687
                             sio.getvalue())
 
688
 
 
689
    def test_show_ids(self):
 
690
        wt = self.make_branch_and_tree('parent')
 
691
        self.build_tree(['parent/f1', 'parent/f2'])
 
692
        wt.add(['f1','f2'])
 
693
        self.wt_commit(wt, 'first post', rev_id='a')
 
694
        child_wt = wt.bzrdir.sprout('child').open_workingtree()
 
695
        self.wt_commit(child_wt, 'branch 1 changes', rev_id='b')
 
696
        wt.merge_from_branch(child_wt.branch)
 
697
        self.wt_commit(wt, 'merge branch 1', rev_id='c')
 
698
        self.assertFormatterResult("""\
 
699
------------------------------------------------------------
 
700
revno: 2 [merge]
 
701
revision-id: c
 
702
parent: a
 
703
parent: b
 
704
committer: Joe Foo <joe@foo.com>
 
705
branch nick: parent
 
706
timestamp: Tue 2005-11-22 00:00:02 +0000
 
707
message:
 
708
  merge branch 1
 
709
    ------------------------------------------------------------
 
710
    revno: 1.1.1
 
711
    revision-id: b
 
712
    parent: a
 
713
    committer: Joe Foo <joe@foo.com>
 
714
    branch nick: child
 
715
    timestamp: Tue 2005-11-22 00:00:01 +0000
 
716
    message:
 
717
      branch 1 changes
 
718
------------------------------------------------------------
 
719
revno: 1
 
720
revision-id: a
 
721
committer: Joe Foo <joe@foo.com>
 
722
branch nick: parent
 
723
timestamp: Tue 2005-11-22 00:00:00 +0000
 
724
message:
 
725
  first post
 
726
""",
 
727
            wt.branch, log.LongLogFormatter,
 
728
            formatter_kwargs=dict(levels=0,show_ids=True))
 
729
 
 
730
 
 
731
class TestLongLogFormatterWithoutMergeRevisions(TestCaseForLogFormatter):
830
732
 
831
733
    def test_long_verbose_log(self):
832
734
        """Verbose log includes changed files
833
735
 
834
736
        bug #4676
835
737
        """
836
 
        wt = self.make_branch_and_tree('.')
837
 
        b = wt.branch
838
 
        self.build_tree(['a'])
839
 
        wt.add('a')
840
 
        # XXX: why does a longer nick show up?
841
 
        b.nick = 'test_verbose_log'
842
 
        wt.commit(message='add a',
843
 
                  timestamp=1132711707,
844
 
                  timezone=36000,
845
 
                  committer='Lorem Ipsum <test@example.com>')
846
 
        logfile = file('out.tmp', 'w+')
847
 
        formatter = log.LongLogFormatter(to_file=logfile, levels=1)
848
 
        log.show_log(b, formatter, verbose=True)
849
 
        logfile.flush()
850
 
        logfile.seek(0)
851
 
        log_contents = logfile.read()
852
 
        self.assertEqualDiff('''\
 
738
        wt = self.make_standard_commit('test_long_verbose_log', authors=[])
 
739
        self.assertFormatterResult("""\
853
740
------------------------------------------------------------
854
741
revno: 1
855
742
committer: Lorem Ipsum <test@example.com>
856
 
branch nick: test_verbose_log
857
 
timestamp: Wed 2005-11-23 12:08:27 +1000
 
743
branch nick: test_long_verbose_log
 
744
timestamp: Tue 2005-11-22 00:00:00 +0000
858
745
message:
859
746
  add a
860
747
added:
861
748
  a
862
 
''',
863
 
                             log_contents)
 
749
""",
 
750
            wt.branch, log.LongLogFormatter,
 
751
            formatter_kwargs=dict(levels=1),
 
752
            show_log_kwargs=dict(verbose=True))
864
753
 
865
754
    def test_long_verbose_contain_deltas(self):
866
755
        wt = self.make_branch_and_tree('parent')
867
756
        self.build_tree(['parent/f1', 'parent/f2'])
868
757
        wt.add(['f1','f2'])
869
 
        wt.commit('first post')
870
 
        self.run_bzr('branch parent child')
 
758
        self.wt_commit(wt, 'first post')
 
759
        child_wt = wt.bzrdir.sprout('child').open_workingtree()
871
760
        os.unlink('child/f1')
872
 
        file('child/f2', 'wb').write('hello\n')
873
 
        self.run_bzr(['commit', '-m', 'removed f1 and modified f2',
874
 
            'child'])
875
 
        os.chdir('parent')
876
 
        self.run_bzr('merge ../child')
877
 
        wt.commit('merge branch 1')
878
 
        b = wt.branch
879
 
        sio = self.make_utf8_encoded_stringio()
880
 
        lf = log.LongLogFormatter(to_file=sio, levels=1)
881
 
        log.show_log(b, lf, verbose=True)
882
 
        the_log = normalize_log(sio.getvalue())
883
 
        self.assertEqualDiff("""\
 
761
        self.build_tree_contents([('child/f2', 'hello\n')])
 
762
        self.wt_commit(child_wt, 'removed f1 and modified f2')
 
763
        wt.merge_from_branch(child_wt.branch)
 
764
        self.wt_commit(wt, 'merge branch 1')
 
765
        self.assertFormatterResult("""\
884
766
------------------------------------------------------------
885
767
revno: 2 [merge]
886
 
committer: Lorem Ipsum <test@example.com>
 
768
committer: Joe Foo <joe@foo.com>
887
769
branch nick: parent
888
 
timestamp: Just now
 
770
timestamp: Tue 2005-11-22 00:00:02 +0000
889
771
message:
890
772
  merge branch 1
891
773
removed:
894
776
  f2
895
777
------------------------------------------------------------
896
778
revno: 1
897
 
committer: Lorem Ipsum <test@example.com>
 
779
committer: Joe Foo <joe@foo.com>
898
780
branch nick: parent
899
 
timestamp: Just now
 
781
timestamp: Tue 2005-11-22 00:00:00 +0000
900
782
message:
901
783
  first post
902
784
added:
903
785
  f1
904
786
  f2
905
787
""",
906
 
                             the_log)
 
788
            wt.branch, log.LongLogFormatter,
 
789
            formatter_kwargs=dict(levels=1),
 
790
            show_log_kwargs=dict(verbose=True))
907
791
 
908
792
    def test_long_trailing_newlines(self):
909
793
        wt = self.make_branch_and_tree('.')
910
 
        b = make_commits_with_trailing_newlines(wt)
911
 
        sio = self.make_utf8_encoded_stringio()
912
 
        lf = log.LongLogFormatter(to_file=sio, levels=1)
913
 
        log.show_log(b, lf)
914
 
        self.assertEqualDiff("""\
 
794
        b = self.make_commits_with_trailing_newlines(wt)
 
795
        self.assertFormatterResult("""\
915
796
------------------------------------------------------------
916
797
revno: 3
917
798
committer: Joe Foo <joe@foo.com>
918
799
branch nick: test
919
 
timestamp: Mon 2005-11-21 09:32:56 -0600
 
800
timestamp: Tue 2005-11-22 00:00:02 +0000
920
801
message:
921
802
  single line with trailing newline
922
803
------------------------------------------------------------
923
804
revno: 2
924
 
author: Joe Bar <joe@bar.com>
925
805
committer: Joe Foo <joe@foo.com>
926
806
branch nick: test
927
 
timestamp: Mon 2005-11-21 09:27:22 -0600
 
807
timestamp: Tue 2005-11-22 00:00:01 +0000
928
808
message:
929
809
  multiline
930
810
  log
933
813
revno: 1
934
814
committer: Joe Foo <joe@foo.com>
935
815
branch nick: test
936
 
timestamp: Mon 2005-11-21 09:24:15 -0600
 
816
timestamp: Tue 2005-11-22 00:00:00 +0000
937
817
message:
938
818
  simple log message
939
819
""",
940
 
                             sio.getvalue())
 
820
        b, log.LongLogFormatter,
 
821
        formatter_kwargs=dict(levels=1))
941
822
 
942
823
    def test_long_author_in_log(self):
943
824
        """Log includes the author name if it's set in
944
825
        the revision properties
945
826
        """
946
 
        wt = self.make_branch_and_tree('.')
947
 
        b = wt.branch
948
 
        self.build_tree(['a'])
949
 
        wt.add('a')
950
 
        b.nick = 'test_author_log'
951
 
        wt.commit(message='add a',
952
 
                  timestamp=1132711707,
953
 
                  timezone=36000,
954
 
                  committer='Lorem Ipsum <test@example.com>',
955
 
                  authors=['John Doe <jdoe@example.com>'])
956
 
        sio = StringIO()
957
 
        formatter = log.LongLogFormatter(to_file=sio, levels=1)
958
 
        log.show_log(b, formatter)
959
 
        self.assertEqualDiff('''\
 
827
        wt = self.make_standard_commit('test_author_log')
 
828
        self.assertFormatterResult("""\
960
829
------------------------------------------------------------
961
830
revno: 1
962
831
author: John Doe <jdoe@example.com>
963
832
committer: Lorem Ipsum <test@example.com>
964
833
branch nick: test_author_log
965
 
timestamp: Wed 2005-11-23 12:08:27 +1000
 
834
timestamp: Tue 2005-11-22 00:00:00 +0000
966
835
message:
967
836
  add a
968
 
''',
969
 
                             sio.getvalue())
 
837
""",
 
838
            wt.branch, log.LongLogFormatter,
 
839
            formatter_kwargs=dict(levels=1))
970
840
 
971
841
    def test_long_properties_in_log(self):
972
842
        """Log includes the custom properties returned by the registered
973
843
        handlers.
974
844
        """
975
 
        wt = self.make_branch_and_tree('.')
976
 
        b = wt.branch
977
 
        self.build_tree(['a'])
978
 
        wt.add('a')
979
 
        b.nick = 'test_properties_in_log'
980
 
        wt.commit(message='add a',
981
 
                  timestamp=1132711707,
982
 
                  timezone=36000,
983
 
                  committer='Lorem Ipsum <test@example.com>',
984
 
                  authors=['John Doe <jdoe@example.com>'])
985
 
        sio = StringIO()
986
 
        formatter = log.LongLogFormatter(to_file=sio, levels=1)
987
 
        try:
988
 
            def trivial_custom_prop_handler(revision):
989
 
                return {'test_prop':'test_value'}
 
845
        wt = self.make_standard_commit('test_properties_in_log')
 
846
        def trivial_custom_prop_handler(revision):
 
847
            return {'test_prop':'test_value'}
990
848
 
991
 
            log.properties_handler_registry.register(
992
 
                'trivial_custom_prop_handler',
993
 
                trivial_custom_prop_handler)
994
 
            log.show_log(b, formatter)
995
 
        finally:
996
 
            log.properties_handler_registry.remove(
997
 
                'trivial_custom_prop_handler')
998
 
            self.assertEqualDiff('''\
 
849
        log.properties_handler_registry.register(
 
850
            'trivial_custom_prop_handler',
 
851
            trivial_custom_prop_handler)
 
852
        self.assertFormatterResult("""\
999
853
------------------------------------------------------------
1000
854
revno: 1
1001
855
test_prop: test_value
1002
856
author: John Doe <jdoe@example.com>
1003
857
committer: Lorem Ipsum <test@example.com>
1004
858
branch nick: test_properties_in_log
1005
 
timestamp: Wed 2005-11-23 12:08:27 +1000
 
859
timestamp: Tue 2005-11-22 00:00:00 +0000
1006
860
message:
1007
861
  add a
1008
 
''',
1009
 
                                 sio.getvalue())
1010
 
 
1011
 
 
1012
 
class TestLineLogFormatter(tests.TestCaseWithTransport):
 
862
""",
 
863
            wt.branch, log.LongLogFormatter,
 
864
            formatter_kwargs=dict(levels=1))
 
865
 
 
866
 
 
867
class TestLineLogFormatter(TestCaseForLogFormatter):
1013
868
 
1014
869
    def test_line_log(self):
1015
870
        """Line log should show revno
1016
871
 
1017
872
        bug #5162
1018
873
        """
1019
 
        wt = self.make_branch_and_tree('.')
1020
 
        b = wt.branch
1021
 
        self.build_tree(['a'])
1022
 
        wt.add('a')
1023
 
        b.nick = 'test-line-log'
1024
 
        wt.commit(message='add a',
1025
 
                  timestamp=1132711707,
1026
 
                  timezone=36000,
1027
 
                  committer='Line-Log-Formatter Tester <test@line.log>')
1028
 
        logfile = file('out.tmp', 'w+')
1029
 
        formatter = log.LineLogFormatter(to_file=logfile)
1030
 
        log.show_log(b, formatter)
1031
 
        logfile.flush()
1032
 
        logfile.seek(0)
1033
 
        log_contents = logfile.read()
1034
 
        self.assertEqualDiff('1: Line-Log-Formatte... 2005-11-23 add a\n',
1035
 
                             log_contents)
 
874
        wt = self.make_standard_commit('test-line-log',
 
875
                committer='Line-Log-Formatter Tester <test@line.log>',
 
876
                authors=[])
 
877
        self.assertFormatterResult("""\
 
878
1: Line-Log-Formatte... 2005-11-22 add a
 
879
""",
 
880
            wt.branch, log.LineLogFormatter)
1036
881
 
1037
882
    def test_trailing_newlines(self):
1038
883
        wt = self.make_branch_and_tree('.')
1039
 
        b = make_commits_with_trailing_newlines(wt)
1040
 
        sio = self.make_utf8_encoded_stringio()
1041
 
        lf = log.LineLogFormatter(to_file=sio)
1042
 
        log.show_log(b, lf)
1043
 
        self.assertEqualDiff("""\
1044
 
3: Joe Foo 2005-11-21 single line with trailing newline
1045
 
2: Joe Bar 2005-11-21 multiline
1046
 
1: Joe Foo 2005-11-21 simple log message
 
884
        b = self.make_commits_with_trailing_newlines(wt)
 
885
        self.assertFormatterResult("""\
 
886
3: Joe Foo 2005-11-22 single line with trailing newline
 
887
2: Joe Foo 2005-11-22 multiline
 
888
1: Joe Foo 2005-11-22 simple log message
1047
889
""",
1048
 
                             sio.getvalue())
1049
 
 
1050
 
    def _prepare_tree_with_merges(self, with_tags=False):
1051
 
        wt = self.make_branch_and_memory_tree('.')
1052
 
        wt.lock_write()
1053
 
        self.addCleanup(wt.unlock)
1054
 
        wt.add('')
1055
 
        wt.commit('rev-1', rev_id='rev-1',
1056
 
                  timestamp=1132586655, timezone=36000,
1057
 
                  committer='Joe Foo <joe@foo.com>')
1058
 
        wt.commit('rev-merged', rev_id='rev-2a',
1059
 
                  timestamp=1132586700, timezone=36000,
1060
 
                  committer='Joe Foo <joe@foo.com>')
1061
 
        wt.set_parent_ids(['rev-1', 'rev-2a'])
1062
 
        wt.branch.set_last_revision_info(1, 'rev-1')
1063
 
        wt.commit('rev-2', rev_id='rev-2b',
1064
 
                  timestamp=1132586800, timezone=36000,
1065
 
                  committer='Joe Foo <joe@foo.com>')
1066
 
        if with_tags:
1067
 
            branch = wt.branch
1068
 
            branch.tags.set_tag('v0.2', 'rev-2b')
1069
 
            wt.commit('rev-3', rev_id='rev-3',
1070
 
                      timestamp=1132586900, timezone=36000,
1071
 
                      committer='Jane Foo <jane@foo.com>')
1072
 
            branch.tags.set_tag('v1.0rc1', 'rev-3')
1073
 
            branch.tags.set_tag('v1.0', 'rev-3')
1074
 
        return wt
 
890
            b, log.LineLogFormatter)
1075
891
 
1076
892
    def test_line_log_single_merge_revision(self):
1077
893
        wt = self._prepare_tree_with_merges()
1078
 
        logfile = self.make_utf8_encoded_stringio()
1079
 
        formatter = log.LineLogFormatter(to_file=logfile)
1080
894
        revspec = revisionspec.RevisionSpec.from_string('1.1.1')
1081
 
        wtb = wt.branch
1082
 
        rev = revspec.in_history(wtb)
1083
 
        log.show_log(wtb, formatter, start_revision=rev, end_revision=rev)
1084
 
        self.assertEqualDiff("""\
 
895
        rev = revspec.in_history(wt.branch)
 
896
        self.assertFormatterResult("""\
1085
897
1.1.1: Joe Foo 2005-11-22 rev-merged
1086
898
""",
1087
 
                             logfile.getvalue())
 
899
            wt.branch, log.LineLogFormatter,
 
900
            show_log_kwargs=dict(start_revision=rev, end_revision=rev))
1088
901
 
1089
902
    def test_line_log_with_tags(self):
1090
903
        wt = self._prepare_tree_with_merges(with_tags=True)
1091
 
        logfile = self.make_utf8_encoded_stringio()
1092
 
        formatter = log.LineLogFormatter(to_file=logfile)
1093
 
        log.show_log(wt.branch, formatter)
1094
 
        self.assertEqualDiff("""\
1095
 
3: Jane Foo 2005-11-22 {v1.0, v1.0rc1} rev-3
 
904
        self.assertFormatterResult("""\
 
905
3: Joe Foo 2005-11-22 {v1.0, v1.0rc1} rev-3
1096
906
2: Joe Foo 2005-11-22 [merge] {v0.2} rev-2
1097
907
1: Joe Foo 2005-11-22 rev-1
1098
908
""",
1099
 
                             logfile.getvalue())
1100
 
 
1101
 
class TestLineLogFormatterWithMergeRevisions(tests.TestCaseWithTransport):
 
909
            wt.branch, log.LineLogFormatter)
 
910
 
 
911
 
 
912
class TestLineLogFormatterWithMergeRevisions(TestCaseForLogFormatter):
1102
913
 
1103
914
    def test_line_merge_revs_log(self):
1104
915
        """Line log should show revno
1105
916
 
1106
917
        bug #5162
1107
918
        """
1108
 
        wt = self.make_branch_and_tree('.')
1109
 
        b = wt.branch
1110
 
        self.build_tree(['a'])
1111
 
        wt.add('a')
1112
 
        b.nick = 'test-line-log'
1113
 
        wt.commit(message='add a',
1114
 
                  timestamp=1132711707,
1115
 
                  timezone=36000,
1116
 
                  committer='Line-Log-Formatter Tester <test@line.log>')
1117
 
        logfile = file('out.tmp', 'w+')
1118
 
        formatter = log.LineLogFormatter(to_file=logfile, levels=0)
1119
 
        log.show_log(b, formatter)
1120
 
        logfile.flush()
1121
 
        logfile.seek(0)
1122
 
        log_contents = logfile.read()
1123
 
        self.assertEqualDiff('1: Line-Log-Formatte... 2005-11-23 add a\n',
1124
 
                             log_contents)
 
919
        wt = self.make_standard_commit('test-line-log',
 
920
                committer='Line-Log-Formatter Tester <test@line.log>',
 
921
                authors=[])
 
922
        self.assertFormatterResult("""\
 
923
1: Line-Log-Formatte... 2005-11-22 add a
 
924
""",
 
925
            wt.branch, log.LineLogFormatter)
1125
926
 
1126
927
    def test_line_merge_revs_log_single_merge_revision(self):
1127
 
        wt = self.make_branch_and_memory_tree('.')
1128
 
        wt.lock_write()
1129
 
        self.addCleanup(wt.unlock)
1130
 
        wt.add('')
1131
 
        wt.commit('rev-1', rev_id='rev-1',
1132
 
                  timestamp=1132586655, timezone=36000,
1133
 
                  committer='Joe Foo <joe@foo.com>')
1134
 
        wt.commit('rev-merged', rev_id='rev-2a',
1135
 
                  timestamp=1132586700, timezone=36000,
1136
 
                  committer='Joe Foo <joe@foo.com>')
1137
 
        wt.set_parent_ids(['rev-1', 'rev-2a'])
1138
 
        wt.branch.set_last_revision_info(1, 'rev-1')
1139
 
        wt.commit('rev-2', rev_id='rev-2b',
1140
 
                  timestamp=1132586800, timezone=36000,
1141
 
                  committer='Joe Foo <joe@foo.com>')
1142
 
        logfile = self.make_utf8_encoded_stringio()
1143
 
        formatter = log.LineLogFormatter(to_file=logfile, levels=0)
 
928
        wt = self._prepare_tree_with_merges()
1144
929
        revspec = revisionspec.RevisionSpec.from_string('1.1.1')
1145
 
        wtb = wt.branch
1146
 
        rev = revspec.in_history(wtb)
1147
 
        log.show_log(wtb, formatter, start_revision=rev, end_revision=rev)
1148
 
        self.assertEqualDiff("""\
 
930
        rev = revspec.in_history(wt.branch)
 
931
        self.assertFormatterResult("""\
1149
932
1.1.1: Joe Foo 2005-11-22 rev-merged
1150
933
""",
1151
 
                             logfile.getvalue())
 
934
            wt.branch, log.LineLogFormatter,
 
935
            formatter_kwargs=dict(levels=0),
 
936
            show_log_kwargs=dict(start_revision=rev, end_revision=rev))
1152
937
 
1153
938
    def test_line_merge_revs_log_with_merges(self):
1154
 
        wt = self.make_branch_and_memory_tree('.')
1155
 
        wt.lock_write()
1156
 
        self.addCleanup(wt.unlock)
1157
 
        wt.add('')
1158
 
        wt.commit('rev-1', rev_id='rev-1',
1159
 
                  timestamp=1132586655, timezone=36000,
1160
 
                  committer='Joe Foo <joe@foo.com>')
1161
 
        wt.commit('rev-merged', rev_id='rev-2a',
1162
 
                  timestamp=1132586700, timezone=36000,
1163
 
                  committer='Joe Foo <joe@foo.com>')
1164
 
        wt.set_parent_ids(['rev-1', 'rev-2a'])
1165
 
        wt.branch.set_last_revision_info(1, 'rev-1')
1166
 
        wt.commit('rev-2', rev_id='rev-2b',
1167
 
                  timestamp=1132586800, timezone=36000,
1168
 
                  committer='Joe Foo <joe@foo.com>')
1169
 
        logfile = self.make_utf8_encoded_stringio()
1170
 
        formatter = log.LineLogFormatter(to_file=logfile, levels=0)
1171
 
        log.show_log(wt.branch, formatter)
1172
 
        self.assertEqualDiff("""\
 
939
        wt = self._prepare_tree_with_merges()
 
940
        self.assertFormatterResult("""\
1173
941
2: Joe Foo 2005-11-22 [merge] rev-2
1174
942
  1.1.1: Joe Foo 2005-11-22 rev-merged
1175
943
1: Joe Foo 2005-11-22 rev-1
1176
944
""",
1177
 
                             logfile.getvalue())
1178
 
 
1179
 
class TestGetViewRevisions(tests.TestCaseWithTransport):
 
945
            wt.branch, log.LineLogFormatter,
 
946
            formatter_kwargs=dict(levels=0))
 
947
 
 
948
 
 
949
class TestGnuChangelogFormatter(TestCaseForLogFormatter):
 
950
 
 
951
    def test_gnu_changelog(self):
 
952
        wt = self.make_standard_commit('nicky', authors=[])
 
953
        self.assertFormatterResult('''\
 
954
2005-11-22  Lorem Ipsum  <test@example.com>
 
955
 
 
956
\tadd a
 
957
 
 
958
''',
 
959
            wt.branch, log.GnuChangelogLogFormatter)
 
960
 
 
961
    def test_with_authors(self):
 
962
        wt = self.make_standard_commit('nicky',
 
963
            authors=['Fooa Fooz <foo@example.com>',
 
964
                     'Bari Baro <bar@example.com>'])
 
965
        self.assertFormatterResult('''\
 
966
2005-11-22  Fooa Fooz  <foo@example.com>
 
967
 
 
968
\tadd a
 
969
 
 
970
''',
 
971
            wt.branch, log.GnuChangelogLogFormatter)
 
972
 
 
973
    def test_verbose(self):
 
974
        wt = self.make_standard_commit('nicky')
 
975
        self.assertFormatterResult('''\
 
976
2005-11-22  John Doe  <jdoe@example.com>
 
977
 
 
978
\t* a:
 
979
 
 
980
\tadd a
 
981
 
 
982
''',
 
983
            wt.branch, log.GnuChangelogLogFormatter,
 
984
            show_log_kwargs=dict(verbose=True))
 
985
 
 
986
class TestGetViewRevisions(tests.TestCaseWithTransport, TestLogMixin):
 
987
 
 
988
    def _get_view_revisions(self, *args, **kwargs):
 
989
        return self.applyDeprecated(symbol_versioning.deprecated_in((2, 2, 0)),
 
990
                                    log.get_view_revisions, *args, **kwargs)
1180
991
 
1181
992
    def make_tree_with_commits(self):
1182
993
        """Create a tree with well-known revision ids"""
1183
994
        wt = self.make_branch_and_tree('tree1')
1184
 
        wt.commit('commit one', rev_id='1')
1185
 
        wt.commit('commit two', rev_id='2')
1186
 
        wt.commit('commit three', rev_id='3')
 
995
        self.wt_commit(wt, 'commit one', rev_id='1')
 
996
        self.wt_commit(wt, 'commit two', rev_id='2')
 
997
        self.wt_commit(wt, 'commit three', rev_id='3')
1187
998
        mainline_revs = [None, '1', '2', '3']
1188
999
        rev_nos = {'1': 1, '2': 2, '3': 3}
1189
1000
        return mainline_revs, rev_nos, wt
1192
1003
        """Create a tree with well-known revision ids and a merge"""
1193
1004
        mainline_revs, rev_nos, wt = self.make_tree_with_commits()
1194
1005
        tree2 = wt.bzrdir.sprout('tree2').open_workingtree()
1195
 
        tree2.commit('four-a', rev_id='4a')
 
1006
        self.wt_commit(tree2, 'four-a', rev_id='4a')
1196
1007
        wt.merge_from_branch(tree2.branch)
1197
 
        wt.commit('four-b', rev_id='4b')
 
1008
        self.wt_commit(wt, 'four-b', rev_id='4b')
1198
1009
        mainline_revs.append('4b')
1199
1010
        rev_nos['4b'] = 4
1200
1011
        # 4a: 3.1.1
1248
1059
        mainline_revs, rev_nos, wt = self.make_tree_with_commits()
1249
1060
        wt.lock_read()
1250
1061
        self.addCleanup(wt.unlock)
1251
 
        revisions = list(log.get_view_revisions(
 
1062
        revisions = list(self._get_view_revisions(
1252
1063
                mainline_revs, rev_nos, wt.branch, 'forward'))
1253
1064
        self.assertEqual([('1', '1', 0), ('2', '2', 0), ('3', '3', 0)],
1254
1065
                         revisions)
1255
 
        revisions2 = list(log.get_view_revisions(
 
1066
        revisions2 = list(self._get_view_revisions(
1256
1067
                mainline_revs, rev_nos, wt.branch, 'forward',
1257
1068
                include_merges=False))
1258
1069
        self.assertEqual(revisions, revisions2)
1262
1073
        mainline_revs, rev_nos, wt = self.make_tree_with_commits()
1263
1074
        wt.lock_read()
1264
1075
        self.addCleanup(wt.unlock)
1265
 
        revisions = list(log.get_view_revisions(
 
1076
        revisions = list(self._get_view_revisions(
1266
1077
                mainline_revs, rev_nos, wt.branch, 'reverse'))
1267
1078
        self.assertEqual([('3', '3', 0), ('2', '2', 0), ('1', '1', 0), ],
1268
1079
                         revisions)
1269
 
        revisions2 = list(log.get_view_revisions(
 
1080
        revisions2 = list(self._get_view_revisions(
1270
1081
                mainline_revs, rev_nos, wt.branch, 'reverse',
1271
1082
                include_merges=False))
1272
1083
        self.assertEqual(revisions, revisions2)
1276
1087
        mainline_revs, rev_nos, wt = self.make_tree_with_merges()
1277
1088
        wt.lock_read()
1278
1089
        self.addCleanup(wt.unlock)
1279
 
        revisions = list(log.get_view_revisions(
 
1090
        revisions = list(self._get_view_revisions(
1280
1091
                mainline_revs, rev_nos, wt.branch, 'forward'))
1281
1092
        self.assertEqual([('1', '1', 0), ('2', '2', 0), ('3', '3', 0),
1282
1093
                          ('4b', '4', 0), ('4a', '3.1.1', 1)],
1283
1094
                         revisions)
1284
 
        revisions = list(log.get_view_revisions(
 
1095
        revisions = list(self._get_view_revisions(
1285
1096
                mainline_revs, rev_nos, wt.branch, 'forward',
1286
1097
                include_merges=False))
1287
1098
        self.assertEqual([('1', '1', 0), ('2', '2', 0), ('3', '3', 0),
1293
1104
        mainline_revs, rev_nos, wt = self.make_tree_with_merges()
1294
1105
        wt.lock_read()
1295
1106
        self.addCleanup(wt.unlock)
1296
 
        revisions = list(log.get_view_revisions(
 
1107
        revisions = list(self._get_view_revisions(
1297
1108
                mainline_revs, rev_nos, wt.branch, 'reverse'))
1298
1109
        self.assertEqual([('4b', '4', 0), ('4a', '3.1.1', 1),
1299
1110
                          ('3', '3', 0), ('2', '2', 0), ('1', '1', 0)],
1300
1111
                         revisions)
1301
 
        revisions = list(log.get_view_revisions(
 
1112
        revisions = list(self._get_view_revisions(
1302
1113
                mainline_revs, rev_nos, wt.branch, 'reverse',
1303
1114
                include_merges=False))
1304
1115
        self.assertEqual([('4b', '4', 0), ('3', '3', 0), ('2', '2', 0),
1310
1121
        mainline_revs, rev_nos, b = self.make_branch_with_many_merges()
1311
1122
        b.lock_read()
1312
1123
        self.addCleanup(b.unlock)
1313
 
        revisions = list(log.get_view_revisions(
 
1124
        revisions = list(self._get_view_revisions(
1314
1125
                mainline_revs, rev_nos, b, 'forward'))
1315
1126
        expected = [('1', '1', 0), ('2', '2', 0), ('3c', '3', 0),
1316
1127
                    ('3b', '2.2.1', 1), ('3a', '2.1.1', 2), ('4b', '4', 0),
1317
1128
                    ('4a', '2.2.2', 1)]
1318
1129
        self.assertEqual(expected, revisions)
1319
 
        revisions = list(log.get_view_revisions(
 
1130
        revisions = list(self._get_view_revisions(
1320
1131
                mainline_revs, rev_nos, b, 'forward',
1321
1132
                include_merges=False))
1322
1133
        self.assertEqual([('1', '1', 0), ('2', '2', 0), ('3c', '3', 0),
1323
1134
                          ('4b', '4', 0)],
1324
1135
                         revisions)
1325
1136
 
1326
 
 
1327
1137
    def test_file_id_for_range(self):
1328
1138
        mainline_revs, rev_nos, b = self.make_branch_with_many_merges()
1329
1139
        b.lock_read()
1334
1144
            return revspec.in_history(branch)
1335
1145
 
1336
1146
        def view_revs(start_rev, end_rev, file_id, direction):
1337
 
            revs = log.calculate_view_revisions(
 
1147
            revs = self.applyDeprecated(
 
1148
                symbol_versioning.deprecated_in((2, 2, 0)),
 
1149
                log.calculate_view_revisions,
1338
1150
                b,
1339
1151
                start_rev, # start_revision
1340
1152
                end_rev, # end_revision
1346
1158
 
1347
1159
        rev_3a = rev_from_rev_id('3a', b)
1348
1160
        rev_4b = rev_from_rev_id('4b', b)
1349
 
        self.assertEqual([('3c', '3', 0), ('3b', '2.2.1', 1), ('3a', '2.1.1', 2)],
 
1161
        self.assertEqual([('3c', '3', 0), ('3b', '2.2.1', 1),
 
1162
                          ('3a', '2.1.1', 2)],
1350
1163
                          view_revs(rev_3a, rev_4b, 'f-id', 'reverse'))
1351
1164
        # Note: 3c still appears before 3a here because of depth-based sorting
1352
 
        self.assertEqual([('3c', '3', 0), ('3b', '2.2.1', 1), ('3a', '2.1.1', 2)],
 
1165
        self.assertEqual([('3c', '3', 0), ('3b', '2.2.1', 1),
 
1166
                          ('3a', '2.1.1', 2)],
1353
1167
                          view_revs(rev_3a, rev_4b, 'f-id', 'forward'))
1354
1168
 
1355
1169
 
1356
1170
class TestGetRevisionsTouchingFileID(tests.TestCaseWithTransport):
1357
1171
 
 
1172
    def get_view_revisions(self, *args):
 
1173
        return self.applyDeprecated(symbol_versioning.deprecated_in((2, 2, 0)),
 
1174
                                    log.get_view_revisions, *args)
 
1175
 
1358
1176
    def create_tree_with_single_merge(self):
1359
1177
        """Create a branch with a moderate layout.
1360
1178
 
1378
1196
        #       use it. Since 'log' only uses the tree in a readonly
1379
1197
        #       fashion, it seems a shame to regenerate an identical
1380
1198
        #       tree for each test.
 
1199
        # TODO: vila 20100122 One way to address the shame above will be to
 
1200
        #       create a memory tree during test parametrization and give a
 
1201
        #       *copy* of this tree to each test. Copying a memory tree ought
 
1202
        #       to be cheap, at least cheaper than creating them with such
 
1203
        #       complex setups.
1381
1204
        tree = self.make_branch_and_tree('tree')
1382
1205
        tree.lock_write()
1383
1206
        self.addCleanup(tree.unlock)
1458
1281
        mainline = tree.branch.revision_history()
1459
1282
        mainline.insert(0, None)
1460
1283
        revnos = dict((rev, idx+1) for idx, rev in enumerate(mainline))
1461
 
        view_revs_iter = log.get_view_revisions(mainline, revnos, tree.branch,
1462
 
                                                'reverse', True)
 
1284
        view_revs_iter = self.get_view_revisions(
 
1285
            mainline, revnos, tree.branch, 'reverse', True)
1463
1286
        actual_revs = log._filter_revisions_touching_file_id(
1464
 
                            tree.branch,
1465
 
                            file_id,
1466
 
                            list(view_revs_iter))
 
1287
            tree.branch, file_id, list(view_revs_iter))
1467
1288
        self.assertEqual(revisions, [r for r, revno, depth in actual_revs])
1468
1289
 
1469
1290
    def test_file_id_f1(self):
1521
1342
 
1522
1343
class TestLogFormatter(tests.TestCase):
1523
1344
 
 
1345
    def setUp(self):
 
1346
        super(TestLogFormatter, self).setUp()
 
1347
        self.rev = revision.Revision('a-id')
 
1348
        self.lf = log.LogFormatter(None)
 
1349
 
1524
1350
    def test_short_committer(self):
1525
 
        rev = revision.Revision('a-id')
1526
 
        rev.committer = 'John Doe <jdoe@example.com>'
1527
 
        lf = log.LogFormatter(None)
1528
 
        self.assertEqual('John Doe', lf.short_committer(rev))
1529
 
        rev.committer = 'John Smith <jsmith@example.com>'
1530
 
        self.assertEqual('John Smith', lf.short_committer(rev))
1531
 
        rev.committer = 'John Smith'
1532
 
        self.assertEqual('John Smith', lf.short_committer(rev))
1533
 
        rev.committer = 'jsmith@example.com'
1534
 
        self.assertEqual('jsmith@example.com', lf.short_committer(rev))
1535
 
        rev.committer = '<jsmith@example.com>'
1536
 
        self.assertEqual('jsmith@example.com', lf.short_committer(rev))
1537
 
        rev.committer = 'John Smith jsmith@example.com'
1538
 
        self.assertEqual('John Smith', lf.short_committer(rev))
 
1351
        def assertCommitter(expected, committer):
 
1352
            self.rev.committer = committer
 
1353
            self.assertEqual(expected, self.lf.short_committer(self.rev))
 
1354
 
 
1355
        assertCommitter('John Doe', 'John Doe <jdoe@example.com>')
 
1356
        assertCommitter('John Smith', 'John Smith <jsmith@example.com>')
 
1357
        assertCommitter('John Smith', 'John Smith')
 
1358
        assertCommitter('jsmith@example.com', 'jsmith@example.com')
 
1359
        assertCommitter('jsmith@example.com', '<jsmith@example.com>')
 
1360
        assertCommitter('John Smith', 'John Smith jsmith@example.com')
1539
1361
 
1540
1362
    def test_short_author(self):
1541
 
        rev = revision.Revision('a-id')
1542
 
        rev.committer = 'John Doe <jdoe@example.com>'
1543
 
        lf = log.LogFormatter(None)
1544
 
        self.assertEqual('John Doe', lf.short_author(rev))
1545
 
        rev.properties['author'] = 'John Smith <jsmith@example.com>'
1546
 
        self.assertEqual('John Smith', lf.short_author(rev))
1547
 
        rev.properties['author'] = 'John Smith'
1548
 
        self.assertEqual('John Smith', lf.short_author(rev))
1549
 
        rev.properties['author'] = 'jsmith@example.com'
1550
 
        self.assertEqual('jsmith@example.com', lf.short_author(rev))
1551
 
        rev.properties['author'] = '<jsmith@example.com>'
1552
 
        self.assertEqual('jsmith@example.com', lf.short_author(rev))
1553
 
        rev.properties['author'] = 'John Smith jsmith@example.com'
1554
 
        self.assertEqual('John Smith', lf.short_author(rev))
1555
 
        del rev.properties['author']
1556
 
        rev.properties['authors'] = ('John Smith <jsmith@example.com>\n'
1557
 
                'Jane Rey <jrey@example.com>')
1558
 
        self.assertEqual('John Smith', lf.short_author(rev))
 
1363
        def assertAuthor(expected, author):
 
1364
            self.rev.properties['author'] = author
 
1365
            self.assertEqual(expected, self.lf.short_author(self.rev))
 
1366
 
 
1367
        assertAuthor('John Smith', 'John Smith <jsmith@example.com>')
 
1368
        assertAuthor('John Smith', 'John Smith')
 
1369
        assertAuthor('jsmith@example.com', 'jsmith@example.com')
 
1370
        assertAuthor('jsmith@example.com', '<jsmith@example.com>')
 
1371
        assertAuthor('John Smith', 'John Smith jsmith@example.com')
 
1372
 
 
1373
    def test_short_author_from_committer(self):
 
1374
        self.rev.committer = 'John Doe <jdoe@example.com>'
 
1375
        self.assertEqual('John Doe', self.lf.short_author(self.rev))
 
1376
 
 
1377
    def test_short_author_from_authors(self):
 
1378
        self.rev.properties['authors'] = ('John Smith <jsmith@example.com>\n'
 
1379
                                          'Jane Rey <jrey@example.com>')
 
1380
        self.assertEqual('John Smith', self.lf.short_author(self.rev))
1559
1381
 
1560
1382
 
1561
1383
class TestReverseByDepth(tests.TestCase):
1707
1529
        log.show_branch_change(tree.branch, s, 3, '3b')
1708
1530
        self.assertContainsRe(s.getvalue(), 'Removed Revisions:')
1709
1531
        self.assertNotContainsRe(s.getvalue(), 'Added Revisions:')
 
1532
 
 
1533
 
 
1534
class TestRevisionNotInBranch(TestCaseForLogFormatter):
 
1535
 
 
1536
    def setup_a_tree(self):
 
1537
        tree = self.make_branch_and_tree('tree')
 
1538
        tree.lock_write()
 
1539
        self.addCleanup(tree.unlock)
 
1540
        kwargs = {
 
1541
            'committer': 'Joe Foo <joe@foo.com>',
 
1542
            'timestamp': 1132617600, # Mon 2005-11-22 00:00:00 +0000
 
1543
            'timezone': 0, # UTC
 
1544
        }
 
1545
        tree.commit('commit 1a', rev_id='1a', **kwargs)
 
1546
        tree.commit('commit 2a', rev_id='2a', **kwargs)
 
1547
        tree.commit('commit 3a', rev_id='3a', **kwargs)
 
1548
        return tree
 
1549
 
 
1550
    def setup_ab_tree(self):
 
1551
        tree = self.setup_a_tree()
 
1552
        tree.set_last_revision('1a')
 
1553
        tree.branch.set_last_revision_info(1, '1a')
 
1554
        kwargs = {
 
1555
            'committer': 'Joe Foo <joe@foo.com>',
 
1556
            'timestamp': 1132617600, # Mon 2005-11-22 00:00:00 +0000
 
1557
            'timezone': 0, # UTC
 
1558
        }
 
1559
        tree.commit('commit 2b', rev_id='2b', **kwargs)
 
1560
        tree.commit('commit 3b', rev_id='3b', **kwargs)
 
1561
        return tree
 
1562
 
 
1563
    def test_one_revision(self):
 
1564
        tree = self.setup_ab_tree()
 
1565
        lf = LogCatcher()
 
1566
        rev = revisionspec.RevisionInfo(tree.branch, None, '3a')
 
1567
        log.show_log(tree.branch, lf, verbose=True, start_revision=rev,
 
1568
                     end_revision=rev)
 
1569
        self.assertEqual(1, len(lf.revisions))
 
1570
        self.assertEqual(None, lf.revisions[0].revno)   # Out-of-branch
 
1571
        self.assertEqual('3a', lf.revisions[0].rev.revision_id)
 
1572
 
 
1573
    def test_many_revisions(self):
 
1574
        tree = self.setup_ab_tree()
 
1575
        lf = LogCatcher()
 
1576
        start_rev = revisionspec.RevisionInfo(tree.branch, None, '1a')
 
1577
        end_rev = revisionspec.RevisionInfo(tree.branch, None, '3a')
 
1578
        log.show_log(tree.branch, lf, verbose=True, start_revision=start_rev,
 
1579
                     end_revision=end_rev)
 
1580
        self.assertEqual(3, len(lf.revisions))
 
1581
        self.assertEqual(None, lf.revisions[0].revno)   # Out-of-branch
 
1582
        self.assertEqual('3a', lf.revisions[0].rev.revision_id)
 
1583
        self.assertEqual(None, lf.revisions[1].revno)   # Out-of-branch
 
1584
        self.assertEqual('2a', lf.revisions[1].rev.revision_id)
 
1585
        self.assertEqual('1', lf.revisions[2].revno)    # In-branch
 
1586
 
 
1587
    def test_long_format(self):
 
1588
        tree = self.setup_ab_tree()
 
1589
        start_rev = revisionspec.RevisionInfo(tree.branch, None, '1a')
 
1590
        end_rev = revisionspec.RevisionInfo(tree.branch, None, '3a')
 
1591
        self.assertFormatterResult("""\
 
1592
------------------------------------------------------------
 
1593
revision-id: 3a
 
1594
committer: Joe Foo <joe@foo.com>
 
1595
branch nick: tree
 
1596
timestamp: Tue 2005-11-22 00:00:00 +0000
 
1597
message:
 
1598
  commit 3a
 
1599
------------------------------------------------------------
 
1600
revision-id: 2a
 
1601
committer: Joe Foo <joe@foo.com>
 
1602
branch nick: tree
 
1603
timestamp: Tue 2005-11-22 00:00:00 +0000
 
1604
message:
 
1605
  commit 2a
 
1606
------------------------------------------------------------
 
1607
revno: 1
 
1608
committer: Joe Foo <joe@foo.com>
 
1609
branch nick: tree
 
1610
timestamp: Tue 2005-11-22 00:00:00 +0000
 
1611
message:
 
1612
  commit 1a
 
1613
""",
 
1614
            tree.branch, log.LongLogFormatter, show_log_kwargs={
 
1615
                'start_revision': start_rev, 'end_revision': end_rev
 
1616
            })
 
1617
 
 
1618
    def test_short_format(self):
 
1619
        tree = self.setup_ab_tree()
 
1620
        start_rev = revisionspec.RevisionInfo(tree.branch, None, '1a')
 
1621
        end_rev = revisionspec.RevisionInfo(tree.branch, None, '3a')
 
1622
        self.assertFormatterResult("""\
 
1623
      Joe Foo\t2005-11-22
 
1624
      revision-id:3a
 
1625
      commit 3a
 
1626
 
 
1627
      Joe Foo\t2005-11-22
 
1628
      revision-id:2a
 
1629
      commit 2a
 
1630
 
 
1631
    1 Joe Foo\t2005-11-22
 
1632
      commit 1a
 
1633
 
 
1634
""",
 
1635
            tree.branch, log.ShortLogFormatter, show_log_kwargs={
 
1636
                'start_revision': start_rev, 'end_revision': end_rev
 
1637
            })
 
1638
 
 
1639
    def test_line_format(self):
 
1640
        tree = self.setup_ab_tree()
 
1641
        start_rev = revisionspec.RevisionInfo(tree.branch, None, '1a')
 
1642
        end_rev = revisionspec.RevisionInfo(tree.branch, None, '3a')
 
1643
        self.assertFormatterResult("""\
 
1644
Joe Foo 2005-11-22 commit 3a
 
1645
Joe Foo 2005-11-22 commit 2a
 
1646
1: Joe Foo 2005-11-22 commit 1a
 
1647
""",
 
1648
            tree.branch, log.LineLogFormatter, show_log_kwargs={
 
1649
                'start_revision': start_rev, 'end_revision': end_rev
 
1650
            })
 
1651
 
 
1652
 
 
1653
class TestLogWithBugs(TestCaseForLogFormatter, TestLogMixin):
 
1654
 
 
1655
    def setUp(self):
 
1656
        TestCaseForLogFormatter.setUp(self)
 
1657
        log.properties_handler_registry.register(
 
1658
            'bugs_properties_handler',
 
1659
            log._bugs_properties_handler)
 
1660
 
 
1661
    def make_commits_with_bugs(self):
 
1662
        """Helper method for LogFormatter tests"""
 
1663
        tree = self.make_branch_and_tree(u'.')
 
1664
        self.build_tree(['a', 'b'])
 
1665
        tree.add('a')
 
1666
        self.wt_commit(tree, 'simple log message', rev_id='a1',
 
1667
                       revprops={'bugs': 'test://bug/id fixed'})
 
1668
        tree.add('b')
 
1669
        self.wt_commit(tree, 'multiline\nlog\nmessage\n', rev_id='a2',
 
1670
                       authors=['Joe Bar <joe@bar.com>'],
 
1671
                       revprops={'bugs': 'test://bug/id fixed\n'
 
1672
                                 'test://bug/2 fixed'})
 
1673
        return tree
 
1674
 
 
1675
 
 
1676
    def test_long_bugs(self):
 
1677
        tree = self.make_commits_with_bugs()
 
1678
        self.assertFormatterResult("""\
 
1679
------------------------------------------------------------
 
1680
revno: 2
 
1681
fixes bug(s): test://bug/id test://bug/2
 
1682
author: Joe Bar <joe@bar.com>
 
1683
committer: Joe Foo <joe@foo.com>
 
1684
branch nick: work
 
1685
timestamp: Tue 2005-11-22 00:00:01 +0000
 
1686
message:
 
1687
  multiline
 
1688
  log
 
1689
  message
 
1690
------------------------------------------------------------
 
1691
revno: 1
 
1692
fixes bug(s): test://bug/id
 
1693
committer: Joe Foo <joe@foo.com>
 
1694
branch nick: work
 
1695
timestamp: Tue 2005-11-22 00:00:00 +0000
 
1696
message:
 
1697
  simple log message
 
1698
""",
 
1699
            tree.branch, log.LongLogFormatter)
 
1700
 
 
1701
    def test_short_bugs(self):
 
1702
        tree = self.make_commits_with_bugs()
 
1703
        self.assertFormatterResult("""\
 
1704
    2 Joe Bar\t2005-11-22
 
1705
      fixes bug(s): test://bug/id test://bug/2
 
1706
      multiline
 
1707
      log
 
1708
      message
 
1709
 
 
1710
    1 Joe Foo\t2005-11-22
 
1711
      fixes bug(s): test://bug/id
 
1712
      simple log message
 
1713
 
 
1714
""",
 
1715
            tree.branch, log.ShortLogFormatter)
 
1716
 
 
1717
    def test_wrong_bugs_property(self):
 
1718
        tree = self.make_branch_and_tree(u'.')
 
1719
        self.build_tree(['foo'])
 
1720
        self.wt_commit(tree, 'simple log message', rev_id='a1',
 
1721
                       revprops={'bugs': 'test://bug/id invalid_value'})
 
1722
        self.assertFormatterResult("""\
 
1723
    1 Joe Foo\t2005-11-22
 
1724
      simple log message
 
1725
 
 
1726
""",
 
1727
            tree.branch, log.ShortLogFormatter)
 
1728
 
 
1729
    def test_bugs_handler_present(self):
 
1730
        self.properties_handler_registry.get('bugs_properties_handler')
 
1731
 
 
1732
 
 
1733
class TestLogForAuthors(TestCaseForLogFormatter):
 
1734
 
 
1735
    def setUp(self):
 
1736
        TestCaseForLogFormatter.setUp(self)
 
1737
        self.wt = self.make_standard_commit('nicky',
 
1738
            authors=['John Doe <jdoe@example.com>',
 
1739
                     'Jane Rey <jrey@example.com>'])
 
1740
 
 
1741
    def assertFormatterResult(self, formatter, who, result):
 
1742
        formatter_kwargs = dict()
 
1743
        if who is not None:
 
1744
            author_list_handler = log.author_list_registry.get(who)
 
1745
            formatter_kwargs['author_list_handler'] = author_list_handler
 
1746
        TestCaseForLogFormatter.assertFormatterResult(self, result,
 
1747
            self.wt.branch, formatter, formatter_kwargs=formatter_kwargs)
 
1748
 
 
1749
    def test_line_default(self):
 
1750
        self.assertFormatterResult(log.LineLogFormatter, None, """\
 
1751
1: John Doe 2005-11-22 add a
 
1752
""")
 
1753
 
 
1754
    def test_line_committer(self):
 
1755
        self.assertFormatterResult(log.LineLogFormatter, 'committer', """\
 
1756
1: Lorem Ipsum 2005-11-22 add a
 
1757
""")
 
1758
 
 
1759
    def test_line_first(self):
 
1760
        self.assertFormatterResult(log.LineLogFormatter, 'first', """\
 
1761
1: John Doe 2005-11-22 add a
 
1762
""")
 
1763
 
 
1764
    def test_line_all(self):
 
1765
        self.assertFormatterResult(log.LineLogFormatter, 'all', """\
 
1766
1: John Doe, Jane Rey 2005-11-22 add a
 
1767
""")
 
1768
 
 
1769
 
 
1770
    def test_short_default(self):
 
1771
        self.assertFormatterResult(log.ShortLogFormatter, None, """\
 
1772
    1 John Doe\t2005-11-22
 
1773
      add a
 
1774
 
 
1775
""")
 
1776
 
 
1777
    def test_short_committer(self):
 
1778
        self.assertFormatterResult(log.ShortLogFormatter, 'committer', """\
 
1779
    1 Lorem Ipsum\t2005-11-22
 
1780
      add a
 
1781
 
 
1782
""")
 
1783
 
 
1784
    def test_short_first(self):
 
1785
        self.assertFormatterResult(log.ShortLogFormatter, 'first', """\
 
1786
    1 John Doe\t2005-11-22
 
1787
      add a
 
1788
 
 
1789
""")
 
1790
 
 
1791
    def test_short_all(self):
 
1792
        self.assertFormatterResult(log.ShortLogFormatter, 'all', """\
 
1793
    1 John Doe, Jane Rey\t2005-11-22
 
1794
      add a
 
1795
 
 
1796
""")
 
1797
 
 
1798
    def test_long_default(self):
 
1799
        self.assertFormatterResult(log.LongLogFormatter, None, """\
 
1800
------------------------------------------------------------
 
1801
revno: 1
 
1802
author: John Doe <jdoe@example.com>, Jane Rey <jrey@example.com>
 
1803
committer: Lorem Ipsum <test@example.com>
 
1804
branch nick: nicky
 
1805
timestamp: Tue 2005-11-22 00:00:00 +0000
 
1806
message:
 
1807
  add a
 
1808
""")
 
1809
 
 
1810
    def test_long_committer(self):
 
1811
        self.assertFormatterResult(log.LongLogFormatter, 'committer', """\
 
1812
------------------------------------------------------------
 
1813
revno: 1
 
1814
committer: Lorem Ipsum <test@example.com>
 
1815
branch nick: nicky
 
1816
timestamp: Tue 2005-11-22 00:00:00 +0000
 
1817
message:
 
1818
  add a
 
1819
""")
 
1820
 
 
1821
    def test_long_first(self):
 
1822
        self.assertFormatterResult(log.LongLogFormatter, 'first', """\
 
1823
------------------------------------------------------------
 
1824
revno: 1
 
1825
author: John Doe <jdoe@example.com>
 
1826
committer: Lorem Ipsum <test@example.com>
 
1827
branch nick: nicky
 
1828
timestamp: Tue 2005-11-22 00:00:00 +0000
 
1829
message:
 
1830
  add a
 
1831
""")
 
1832
 
 
1833
    def test_long_all(self):
 
1834
        self.assertFormatterResult(log.LongLogFormatter, 'all', """\
 
1835
------------------------------------------------------------
 
1836
revno: 1
 
1837
author: John Doe <jdoe@example.com>, Jane Rey <jrey@example.com>
 
1838
committer: Lorem Ipsum <test@example.com>
 
1839
branch nick: nicky
 
1840
timestamp: Tue 2005-11-22 00:00:00 +0000
 
1841
message:
 
1842
  add a
 
1843
""")
 
1844
 
 
1845
    def test_gnu_changelog_default(self):
 
1846
        self.assertFormatterResult(log.GnuChangelogLogFormatter, None, """\
 
1847
2005-11-22  John Doe  <jdoe@example.com>
 
1848
 
 
1849
\tadd a
 
1850
 
 
1851
""")
 
1852
 
 
1853
    def test_gnu_changelog_committer(self):
 
1854
        self.assertFormatterResult(log.GnuChangelogLogFormatter, 'committer', """\
 
1855
2005-11-22  Lorem Ipsum  <test@example.com>
 
1856
 
 
1857
\tadd a
 
1858
 
 
1859
""")
 
1860
 
 
1861
    def test_gnu_changelog_first(self):
 
1862
        self.assertFormatterResult(log.GnuChangelogLogFormatter, 'first', """\
 
1863
2005-11-22  John Doe  <jdoe@example.com>
 
1864
 
 
1865
\tadd a
 
1866
 
 
1867
""")
 
1868
 
 
1869
    def test_gnu_changelog_all(self):
 
1870
        self.assertFormatterResult(log.GnuChangelogLogFormatter, 'all', """\
 
1871
2005-11-22  John Doe  <jdoe@example.com>, Jane Rey  <jrey@example.com>
 
1872
 
 
1873
\tadd a
 
1874
 
 
1875
""")
 
1876
 
 
1877
 
 
1878
class TestLogExcludeAncestry(tests.TestCaseWithTransport):
 
1879
 
 
1880
    def make_branch_with_alternate_ancestries(self, relpath='.'):
 
1881
        # See test_merge_sorted_exclude_ancestry below for the difference with
 
1882
        # bt.per_branch.test_iter_merge_sorted_revision.
 
1883
        # TestIterMergeSortedRevisionsBushyGraph. 
 
1884
        # make_branch_with_alternate_ancestries
 
1885
        # and test_merge_sorted_exclude_ancestry
 
1886
        # See the FIXME in assertLogRevnos too.
 
1887
        builder = branchbuilder.BranchBuilder(self.get_transport(relpath))
 
1888
        # 1
 
1889
        # |\
 
1890
        # 2 \
 
1891
        # |  |
 
1892
        # |  1.1.1
 
1893
        # |  | \
 
1894
        # |  |  1.2.1
 
1895
        # |  | /
 
1896
        # |  1.1.2
 
1897
        # | /
 
1898
        # 3
 
1899
        builder.start_series()
 
1900
        builder.build_snapshot('1', None, [
 
1901
            ('add', ('', 'TREE_ROOT', 'directory', '')),])
 
1902
        builder.build_snapshot('1.1.1', ['1'], [])
 
1903
        builder.build_snapshot('2', ['1'], [])
 
1904
        builder.build_snapshot('1.2.1', ['1.1.1'], [])
 
1905
        builder.build_snapshot('1.1.2', ['1.1.1', '1.2.1'], [])
 
1906
        builder.build_snapshot('3', ['2', '1.1.2'], [])
 
1907
        builder.finish_series()
 
1908
        br = builder.get_branch()
 
1909
        br.lock_read()
 
1910
        self.addCleanup(br.unlock)
 
1911
        return br
 
1912
 
 
1913
    def assertLogRevnos(self, expected_revnos, b, start, end,
 
1914
                        exclude_common_ancestry, generate_merge_revisions=True):
 
1915
        # FIXME: the layering in log makes it hard to test intermediate levels,
 
1916
        # I wish adding filters with their parameters were easier...
 
1917
        # -- vila 20100413
 
1918
        iter_revs = log._calc_view_revisions(
 
1919
            b, start, end, direction='reverse',
 
1920
            generate_merge_revisions=generate_merge_revisions,
 
1921
            exclude_common_ancestry=exclude_common_ancestry)
 
1922
        self.assertEqual(expected_revnos,
 
1923
                         [revid for revid, revno, depth in iter_revs])
 
1924
 
 
1925
    def test_merge_sorted_exclude_ancestry(self):
 
1926
        b = self.make_branch_with_alternate_ancestries()
 
1927
        self.assertLogRevnos(['3', '1.1.2', '1.2.1', '1.1.1', '2', '1'],
 
1928
                             b, '1', '3', exclude_common_ancestry=False)
 
1929
        # '2' is part of the '3' ancestry but not part of '1.1.1' ancestry so
 
1930
        # it should be mentioned even if merge_sort order will make it appear
 
1931
        # after 1.1.1
 
1932
        self.assertLogRevnos(['3', '1.1.2', '1.2.1', '2'],
 
1933
                             b, '1.1.1', '3', exclude_common_ancestry=True)
 
1934
 
 
1935
    def test_merge_sorted_simple_revnos_exclude_ancestry(self):
 
1936
        b = self.make_branch_with_alternate_ancestries()
 
1937
        self.assertLogRevnos(['3', '2'],
 
1938
                             b, '1', '3', exclude_common_ancestry=True,
 
1939
                             generate_merge_revisions=False)
 
1940
        self.assertLogRevnos(['3', '1.1.2', '1.2.1', '1.1.1', '2'],
 
1941
                             b, '1', '3', exclude_common_ancestry=True,
 
1942
                             generate_merge_revisions=True)
 
1943