~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: 2009-06-10 10:33:31 UTC
  • mfrom: (4426.1.1 integration)
  • Revision ID: pqm@pqm.ubuntu.com-20090610103331-ht76b0l92gj1gn9d
(bialix) Start Russian translation

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005-2010 Canonical Ltd
 
1
# Copyright (C) 2005, 2006, 2007 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
23
23
    registry,
24
24
    revision,
25
25
    revisionspec,
26
 
    symbol_versioning,
27
26
    tests,
28
27
    )
29
28
 
30
29
 
31
 
class TestLogMixin(object):
32
 
 
33
 
    def wt_commit(self, wt, message, **kwargs):
34
 
        """Use some mostly fixed values for commits to simplify tests.
35
 
 
36
 
        Tests can use this function to get some commit attributes. The time
37
 
        stamp is incremented at each commit.
38
 
        """
39
 
        if getattr(self, 'timestamp', None) is None:
40
 
            self.timestamp = 1132617600 # Mon 2005-11-22 00:00:00 +0000
41
 
        else:
42
 
            self.timestamp += 1 # 1 second between each commit
43
 
        kwargs.setdefault('timestamp', self.timestamp)
44
 
        kwargs.setdefault('timezone', 0) # UTC
45
 
        kwargs.setdefault('committer', 'Joe Foo <joe@foo.com>')
46
 
 
47
 
        return wt.commit(message, **kwargs)
48
 
 
49
 
 
50
 
class TestCaseForLogFormatter(tests.TestCaseWithTransport, TestLogMixin):
 
30
class TestCaseWithoutPropsHandler(tests.TestCaseWithTransport):
51
31
 
52
32
    def setUp(self):
53
 
        super(TestCaseForLogFormatter, self).setUp()
 
33
        super(TestCaseWithoutPropsHandler, self).setUp()
54
34
        # keep a reference to the "current" custom prop. handler registry
55
35
        self.properties_handler_registry = log.properties_handler_registry
56
36
        # Use a clean registry for log
60
40
            log.properties_handler_registry = self.properties_handler_registry
61
41
        self.addCleanup(restore)
62
42
 
63
 
    def assertFormatterResult(self, result, branch, formatter_class,
64
 
                              formatter_kwargs=None, show_log_kwargs=None):
65
 
        logfile = self.make_utf8_encoded_stringio()
66
 
        if formatter_kwargs is None:
67
 
            formatter_kwargs = {}
68
 
        formatter = formatter_class(to_file=logfile, **formatter_kwargs)
69
 
        if show_log_kwargs is None:
70
 
            show_log_kwargs = {}
71
 
        log.show_log(branch, formatter, **show_log_kwargs)
72
 
        self.assertEqualDiff(result, logfile.getvalue())
73
 
 
74
 
    def make_standard_commit(self, branch_nick, **kwargs):
75
 
        wt = self.make_branch_and_tree('.')
76
 
        wt.lock_write()
77
 
        self.addCleanup(wt.unlock)
78
 
        self.build_tree(['a'])
79
 
        wt.add(['a'])
80
 
        wt.branch.nick = branch_nick
81
 
        kwargs.setdefault('committer', 'Lorem Ipsum <test@example.com>')
82
 
        kwargs.setdefault('authors', ['John Doe <jdoe@example.com>'])
83
 
        self.wt_commit(wt, 'add a', **kwargs)
84
 
        return wt
85
 
 
86
 
    def make_commits_with_trailing_newlines(self, wt):
87
 
        """Helper method for LogFormatter tests"""
88
 
        b = wt.branch
89
 
        b.nick = 'test'
90
 
        self.build_tree_contents([('a', 'hello moto\n')])
91
 
        self.wt_commit(wt, 'simple log message', rev_id='a1')
92
 
        self.build_tree_contents([('b', 'goodbye\n')])
93
 
        wt.add('b')
94
 
        self.wt_commit(wt, 'multiline\nlog\nmessage\n', rev_id='a2')
95
 
 
96
 
        self.build_tree_contents([('c', 'just another manic monday\n')])
97
 
        wt.add('c')
98
 
        self.wt_commit(wt, 'single line with trailing newline\n', rev_id='a3')
99
 
        return b
100
 
 
101
 
    def _prepare_tree_with_merges(self, with_tags=False):
102
 
        wt = self.make_branch_and_memory_tree('.')
103
 
        wt.lock_write()
104
 
        self.addCleanup(wt.unlock)
105
 
        wt.add('')
106
 
        self.wt_commit(wt, 'rev-1', rev_id='rev-1')
107
 
        self.wt_commit(wt, 'rev-merged', rev_id='rev-2a')
108
 
        wt.set_parent_ids(['rev-1', 'rev-2a'])
109
 
        wt.branch.set_last_revision_info(1, 'rev-1')
110
 
        self.wt_commit(wt, 'rev-2', rev_id='rev-2b')
111
 
        if with_tags:
112
 
            branch = wt.branch
113
 
            branch.tags.set_tag('v0.2', 'rev-2b')
114
 
            self.wt_commit(wt, 'rev-3', rev_id='rev-3')
115
 
            branch.tags.set_tag('v1.0rc1', 'rev-3')
116
 
            branch.tags.set_tag('v1.0', 'rev-3')
117
 
        return wt
118
43
 
119
44
class LogCatcher(log.LogFormatter):
120
45
    """Pull log messages into a list rather than displaying them.
124
49
    being dependent on the formatting.
125
50
    """
126
51
 
127
 
    supports_merge_revisions = True
128
52
    supports_delta = True
129
 
    supports_diff = True
130
 
    preferred_levels = 0
131
53
 
132
 
    def __init__(self, *args, **kwargs):
133
 
        kwargs.update(dict(to_file=None))
134
 
        super(LogCatcher, self).__init__(*args, **kwargs)
 
54
    def __init__(self):
 
55
        super(LogCatcher, self).__init__(to_file=None)
135
56
        self.revisions = []
136
57
 
137
58
    def log_revision(self, revision):
221
142
        lf = LogCatcher()
222
143
        log.show_log(wt.branch, lf, verbose=True)
223
144
        committed_msg = lf.revisions[0].rev.message
224
 
        if wt.branch.repository._serializer.squashes_xml_invalid_characters:
225
 
            self.assertNotEqual(msg, committed_msg)
226
 
            self.assertTrue(len(committed_msg) > len(msg))
227
 
        else:
228
 
            self.assertEqual(msg, committed_msg)
 
145
        self.assertNotEqual(msg, committed_msg)
 
146
        self.assertTrue(len(committed_msg) > len(msg))
229
147
 
230
148
    def test_commit_message_without_control_chars(self):
231
149
        wt = self.make_branch_and_tree('.')
280
198
        self.checkDelta(logentry.delta, added=['file1', 'file2'])
281
199
 
282
200
 
283
 
class TestShortLogFormatter(TestCaseForLogFormatter):
 
201
def make_commits_with_trailing_newlines(wt):
 
202
    """Helper method for LogFormatter tests"""
 
203
    b = wt.branch
 
204
    b.nick='test'
 
205
    open('a', 'wb').write('hello moto\n')
 
206
    wt.add('a')
 
207
    wt.commit('simple log message', rev_id='a1',
 
208
              timestamp=1132586655.459960938, timezone=-6*3600,
 
209
              committer='Joe Foo <joe@foo.com>')
 
210
    open('b', 'wb').write('goodbye\n')
 
211
    wt.add('b')
 
212
    wt.commit('multiline\nlog\nmessage\n', rev_id='a2',
 
213
              timestamp=1132586842.411175966, timezone=-6*3600,
 
214
              committer='Joe Foo <joe@foo.com>',
 
215
              authors=['Joe Bar <joe@bar.com>'])
 
216
 
 
217
    open('c', 'wb').write('just another manic monday\n')
 
218
    wt.add('c')
 
219
    wt.commit('single line with trailing newline\n', rev_id='a3',
 
220
              timestamp=1132587176.835228920, timezone=-6*3600,
 
221
              committer = 'Joe Foo <joe@foo.com>')
 
222
    return b
 
223
 
 
224
 
 
225
def normalize_log(log):
 
226
    """Replaces the variable lines of logs with fixed lines"""
 
227
    author = 'author: Dolor Sit <test@example.com>'
 
228
    committer = 'committer: Lorem Ipsum <test@example.com>'
 
229
    lines = log.splitlines(True)
 
230
    for idx,line in enumerate(lines):
 
231
        stripped_line = line.lstrip()
 
232
        indent = ' ' * (len(line) - len(stripped_line))
 
233
        if stripped_line.startswith('author:'):
 
234
            lines[idx] = indent + author + '\n'
 
235
        elif stripped_line.startswith('committer:'):
 
236
            lines[idx] = indent + committer + '\n'
 
237
        elif stripped_line.startswith('timestamp:'):
 
238
            lines[idx] = indent + 'timestamp: Just now\n'
 
239
    return ''.join(lines)
 
240
 
 
241
 
 
242
class TestShortLogFormatter(tests.TestCaseWithTransport):
284
243
 
285
244
    def test_trailing_newlines(self):
286
245
        wt = self.make_branch_and_tree('.')
287
 
        b = self.make_commits_with_trailing_newlines(wt)
288
 
        self.assertFormatterResult("""\
289
 
    3 Joe Foo\t2005-11-22
 
246
        b = make_commits_with_trailing_newlines(wt)
 
247
        sio = self.make_utf8_encoded_stringio()
 
248
        lf = log.ShortLogFormatter(to_file=sio)
 
249
        log.show_log(b, lf)
 
250
        self.assertEqualDiff("""\
 
251
    3 Joe Foo\t2005-11-21
290
252
      single line with trailing newline
291
253
 
292
 
    2 Joe Foo\t2005-11-22
 
254
    2 Joe Bar\t2005-11-21
293
255
      multiline
294
256
      log
295
257
      message
296
258
 
297
 
    1 Joe Foo\t2005-11-22
 
259
    1 Joe Foo\t2005-11-21
298
260
      simple log message
299
261
 
300
262
""",
301
 
            b, log.ShortLogFormatter)
 
263
                             sio.getvalue())
 
264
 
 
265
    def _prepare_tree_with_merges(self, with_tags=False):
 
266
        wt = self.make_branch_and_memory_tree('.')
 
267
        wt.lock_write()
 
268
        self.addCleanup(wt.unlock)
 
269
        wt.add('')
 
270
        wt.commit('rev-1', rev_id='rev-1',
 
271
                  timestamp=1132586655, timezone=36000,
 
272
                  committer='Joe Foo <joe@foo.com>')
 
273
        wt.commit('rev-merged', rev_id='rev-2a',
 
274
                  timestamp=1132586700, timezone=36000,
 
275
                  committer='Joe Foo <joe@foo.com>')
 
276
        wt.set_parent_ids(['rev-1', 'rev-2a'])
 
277
        wt.branch.set_last_revision_info(1, 'rev-1')
 
278
        wt.commit('rev-2', rev_id='rev-2b',
 
279
                  timestamp=1132586800, timezone=36000,
 
280
                  committer='Joe Foo <joe@foo.com>')
 
281
        if with_tags:
 
282
            branch = wt.branch
 
283
            branch.tags.set_tag('v0.2', 'rev-2b')
 
284
            wt.commit('rev-3', rev_id='rev-3',
 
285
                      timestamp=1132586900, timezone=36000,
 
286
                      committer='Jane Foo <jane@foo.com>')
 
287
            branch.tags.set_tag('v1.0rc1', 'rev-3')
 
288
            branch.tags.set_tag('v1.0', 'rev-3')
 
289
        return wt
302
290
 
303
291
    def test_short_log_with_merges(self):
304
292
        wt = self._prepare_tree_with_merges()
305
 
        self.assertFormatterResult("""\
 
293
        logfile = self.make_utf8_encoded_stringio()
 
294
        formatter = log.ShortLogFormatter(to_file=logfile)
 
295
        log.show_log(wt.branch, formatter)
 
296
        self.assertEqualDiff("""\
306
297
    2 Joe Foo\t2005-11-22 [merge]
307
298
      rev-2
308
299
 
310
301
      rev-1
311
302
 
312
303
""",
313
 
            wt.branch, log.ShortLogFormatter)
 
304
                             logfile.getvalue())
314
305
 
315
306
    def test_short_log_with_merges_and_advice(self):
316
307
        wt = self._prepare_tree_with_merges()
317
 
        self.assertFormatterResult("""\
 
308
        logfile = self.make_utf8_encoded_stringio()
 
309
        formatter = log.ShortLogFormatter(to_file=logfile,
 
310
            show_advice=True)
 
311
        log.show_log(wt.branch, formatter)
 
312
        self.assertEqualDiff("""\
318
313
    2 Joe Foo\t2005-11-22 [merge]
319
314
      rev-2
320
315
 
323
318
 
324
319
Use --include-merges or -n0 to see merged revisions.
325
320
""",
326
 
            wt.branch, log.ShortLogFormatter,
327
 
            formatter_kwargs=dict(show_advice=True))
 
321
                             logfile.getvalue())
328
322
 
329
323
    def test_short_log_with_merges_and_range(self):
330
 
        wt = self._prepare_tree_with_merges()
331
 
        self.wt_commit(wt, 'rev-3a', rev_id='rev-3a')
 
324
        wt = self.make_branch_and_memory_tree('.')
 
325
        wt.lock_write()
 
326
        self.addCleanup(wt.unlock)
 
327
        wt.add('')
 
328
        wt.commit('rev-1', rev_id='rev-1',
 
329
                  timestamp=1132586655, timezone=36000,
 
330
                  committer='Joe Foo <joe@foo.com>')
 
331
        wt.commit('rev-merged', rev_id='rev-2a',
 
332
                  timestamp=1132586700, timezone=36000,
 
333
                  committer='Joe Foo <joe@foo.com>')
 
334
        wt.branch.set_last_revision_info(1, 'rev-1')
 
335
        wt.set_parent_ids(['rev-1', 'rev-2a'])
 
336
        wt.commit('rev-2b', rev_id='rev-2b',
 
337
                  timestamp=1132586800, timezone=36000,
 
338
                  committer='Joe Foo <joe@foo.com>')
 
339
        wt.commit('rev-3a', rev_id='rev-3a',
 
340
                  timestamp=1132586800, timezone=36000,
 
341
                  committer='Joe Foo <joe@foo.com>')
332
342
        wt.branch.set_last_revision_info(2, 'rev-2b')
333
343
        wt.set_parent_ids(['rev-2b', 'rev-3a'])
334
 
        self.wt_commit(wt, 'rev-3b', rev_id='rev-3b')
335
 
        self.assertFormatterResult("""\
 
344
        wt.commit('rev-3b', rev_id='rev-3b',
 
345
                  timestamp=1132586800, timezone=36000,
 
346
                  committer='Joe Foo <joe@foo.com>')
 
347
        logfile = self.make_utf8_encoded_stringio()
 
348
        formatter = log.ShortLogFormatter(to_file=logfile)
 
349
        log.show_log(wt.branch, formatter,
 
350
            start_revision=2, end_revision=3)
 
351
        self.assertEqualDiff("""\
336
352
    3 Joe Foo\t2005-11-22 [merge]
337
353
      rev-3b
338
354
 
339
355
    2 Joe Foo\t2005-11-22 [merge]
340
 
      rev-2
 
356
      rev-2b
341
357
 
342
358
""",
343
 
            wt.branch, log.ShortLogFormatter,
344
 
            show_log_kwargs=dict(start_revision=2, end_revision=3))
 
359
                             logfile.getvalue())
345
360
 
346
361
    def test_short_log_with_tags(self):
347
362
        wt = self._prepare_tree_with_merges(with_tags=True)
348
 
        self.assertFormatterResult("""\
349
 
    3 Joe Foo\t2005-11-22 {v1.0, v1.0rc1}
 
363
        logfile = self.make_utf8_encoded_stringio()
 
364
        formatter = log.ShortLogFormatter(to_file=logfile)
 
365
        log.show_log(wt.branch, formatter)
 
366
        self.assertEqualDiff("""\
 
367
    3 Jane Foo\t2005-11-22 {v1.0, v1.0rc1}
350
368
      rev-3
351
369
 
352
370
    2 Joe Foo\t2005-11-22 {v0.2} [merge]
356
374
      rev-1
357
375
 
358
376
""",
359
 
            wt.branch, log.ShortLogFormatter)
 
377
                             logfile.getvalue())
360
378
 
361
379
    def test_short_log_single_merge_revision(self):
362
 
        wt = self._prepare_tree_with_merges()
 
380
        wt = self.make_branch_and_memory_tree('.')
 
381
        wt.lock_write()
 
382
        self.addCleanup(wt.unlock)
 
383
        wt.add('')
 
384
        wt.commit('rev-1', rev_id='rev-1',
 
385
                  timestamp=1132586655, timezone=36000,
 
386
                  committer='Joe Foo <joe@foo.com>')
 
387
        wt.commit('rev-merged', rev_id='rev-2a',
 
388
                  timestamp=1132586700, timezone=36000,
 
389
                  committer='Joe Foo <joe@foo.com>')
 
390
        wt.set_parent_ids(['rev-1', 'rev-2a'])
 
391
        wt.branch.set_last_revision_info(1, 'rev-1')
 
392
        wt.commit('rev-2', rev_id='rev-2b',
 
393
                  timestamp=1132586800, timezone=36000,
 
394
                  committer='Joe Foo <joe@foo.com>')
 
395
        logfile = self.make_utf8_encoded_stringio()
 
396
        formatter = log.ShortLogFormatter(to_file=logfile)
363
397
        revspec = revisionspec.RevisionSpec.from_string('1.1.1')
364
 
        rev = revspec.in_history(wt.branch)
365
 
        self.assertFormatterResult("""\
 
398
        wtb = wt.branch
 
399
        rev = revspec.in_history(wtb)
 
400
        log.show_log(wtb, formatter, start_revision=rev, end_revision=rev)
 
401
        self.assertEqualDiff("""\
366
402
      1.1.1 Joe Foo\t2005-11-22
367
403
            rev-merged
368
404
 
369
405
""",
370
 
            wt.branch, log.ShortLogFormatter,
371
 
            show_log_kwargs=dict(start_revision=rev, end_revision=rev))
372
 
 
373
 
 
374
 
class TestShortLogFormatterWithMergeRevisions(TestCaseForLogFormatter):
 
406
                             logfile.getvalue())
 
407
 
 
408
 
 
409
class TestShortLogFormatterWithMergeRevisions(tests.TestCaseWithTransport):
375
410
 
376
411
    def test_short_merge_revs_log_with_merges(self):
377
 
        wt = self._prepare_tree_with_merges()
 
412
        wt = self.make_branch_and_memory_tree('.')
 
413
        wt.lock_write()
 
414
        self.addCleanup(wt.unlock)
 
415
        wt.add('')
 
416
        wt.commit('rev-1', rev_id='rev-1',
 
417
                  timestamp=1132586655, timezone=36000,
 
418
                  committer='Joe Foo <joe@foo.com>')
 
419
        wt.commit('rev-merged', rev_id='rev-2a',
 
420
                  timestamp=1132586700, timezone=36000,
 
421
                  committer='Joe Foo <joe@foo.com>')
 
422
        wt.set_parent_ids(['rev-1', 'rev-2a'])
 
423
        wt.branch.set_last_revision_info(1, 'rev-1')
 
424
        wt.commit('rev-2', rev_id='rev-2b',
 
425
                  timestamp=1132586800, timezone=36000,
 
426
                  committer='Joe Foo <joe@foo.com>')
 
427
        logfile = self.make_utf8_encoded_stringio()
 
428
        formatter = log.ShortLogFormatter(to_file=logfile, levels=0)
 
429
        log.show_log(wt.branch, formatter)
378
430
        # Note that the 1.1.1 indenting is in fact correct given that
379
431
        # the revision numbers are right justified within 5 characters
380
432
        # for mainline revnos and 9 characters for dotted revnos.
381
 
        self.assertFormatterResult("""\
 
433
        self.assertEqualDiff("""\
382
434
    2 Joe Foo\t2005-11-22 [merge]
383
435
      rev-2
384
436
 
389
441
      rev-1
390
442
 
391
443
""",
392
 
            wt.branch, log.ShortLogFormatter,
393
 
            formatter_kwargs=dict(levels=0))
 
444
                             logfile.getvalue())
394
445
 
395
446
    def test_short_merge_revs_log_single_merge_revision(self):
396
 
        wt = self._prepare_tree_with_merges()
 
447
        wt = self.make_branch_and_memory_tree('.')
 
448
        wt.lock_write()
 
449
        self.addCleanup(wt.unlock)
 
450
        wt.add('')
 
451
        wt.commit('rev-1', rev_id='rev-1',
 
452
                  timestamp=1132586655, timezone=36000,
 
453
                  committer='Joe Foo <joe@foo.com>')
 
454
        wt.commit('rev-merged', rev_id='rev-2a',
 
455
                  timestamp=1132586700, timezone=36000,
 
456
                  committer='Joe Foo <joe@foo.com>')
 
457
        wt.set_parent_ids(['rev-1', 'rev-2a'])
 
458
        wt.branch.set_last_revision_info(1, 'rev-1')
 
459
        wt.commit('rev-2', rev_id='rev-2b',
 
460
                  timestamp=1132586800, timezone=36000,
 
461
                  committer='Joe Foo <joe@foo.com>')
 
462
        logfile = self.make_utf8_encoded_stringio()
 
463
        formatter = log.ShortLogFormatter(to_file=logfile, levels=0)
397
464
        revspec = revisionspec.RevisionSpec.from_string('1.1.1')
398
 
        rev = revspec.in_history(wt.branch)
399
 
        self.assertFormatterResult("""\
 
465
        wtb = wt.branch
 
466
        rev = revspec.in_history(wtb)
 
467
        log.show_log(wtb, formatter, start_revision=rev, end_revision=rev)
 
468
        self.assertEqualDiff("""\
400
469
      1.1.1 Joe Foo\t2005-11-22
401
470
            rev-merged
402
471
 
403
472
""",
404
 
            wt.branch, log.ShortLogFormatter,
405
 
            formatter_kwargs=dict(levels=0),
406
 
            show_log_kwargs=dict(start_revision=rev, end_revision=rev))
407
 
 
408
 
 
409
 
class TestLongLogFormatter(TestCaseForLogFormatter):
 
473
                             logfile.getvalue())
 
474
 
 
475
 
 
476
class TestLongLogFormatter(TestCaseWithoutPropsHandler):
410
477
 
411
478
    def test_verbose_log(self):
412
479
        """Verbose log includes changed files
413
480
 
414
481
        bug #4676
415
482
        """
416
 
        wt = self.make_standard_commit('test_verbose_log', authors=[])
417
 
        self.assertFormatterResult('''\
 
483
        wt = self.make_branch_and_tree('.')
 
484
        b = wt.branch
 
485
        self.build_tree(['a'])
 
486
        wt.add('a')
 
487
        # XXX: why does a longer nick show up?
 
488
        b.nick = 'test_verbose_log'
 
489
        wt.commit(message='add a',
 
490
                  timestamp=1132711707,
 
491
                  timezone=36000,
 
492
                  committer='Lorem Ipsum <test@example.com>')
 
493
        logfile = file('out.tmp', 'w+')
 
494
        formatter = log.LongLogFormatter(to_file=logfile)
 
495
        log.show_log(b, formatter, verbose=True)
 
496
        logfile.flush()
 
497
        logfile.seek(0)
 
498
        log_contents = logfile.read()
 
499
        self.assertEqualDiff('''\
418
500
------------------------------------------------------------
419
501
revno: 1
420
502
committer: Lorem Ipsum <test@example.com>
421
503
branch nick: test_verbose_log
422
 
timestamp: Tue 2005-11-22 00:00:00 +0000
 
504
timestamp: Wed 2005-11-23 12:08:27 +1000
423
505
message:
424
506
  add a
425
507
added:
426
508
  a
427
509
''',
428
 
            wt.branch, log.LongLogFormatter,
429
 
            show_log_kwargs=dict(verbose=True))
 
510
                             log_contents)
430
511
 
431
512
    def test_merges_are_indented_by_level(self):
432
513
        wt = self.make_branch_and_tree('parent')
433
 
        self.wt_commit(wt, 'first post')
434
 
        child_wt = wt.bzrdir.sprout('child').open_workingtree()
435
 
        self.wt_commit(child_wt, 'branch 1')
436
 
        smallerchild_wt = wt.bzrdir.sprout('smallerchild').open_workingtree()
437
 
        self.wt_commit(smallerchild_wt, 'branch 2')
438
 
        child_wt.merge_from_branch(smallerchild_wt.branch)
439
 
        self.wt_commit(child_wt, 'merge branch 2')
440
 
        wt.merge_from_branch(child_wt.branch)
441
 
        self.wt_commit(wt, 'merge branch 1')
442
 
        self.assertFormatterResult("""\
 
514
        wt.commit('first post')
 
515
        self.run_bzr('branch parent child')
 
516
        self.run_bzr(['commit', '-m', 'branch 1', '--unchanged', 'child'])
 
517
        self.run_bzr('branch child smallerchild')
 
518
        self.run_bzr(['commit', '-m', 'branch 2', '--unchanged',
 
519
            'smallerchild'])
 
520
        os.chdir('child')
 
521
        self.run_bzr('merge ../smallerchild')
 
522
        self.run_bzr(['commit', '-m', 'merge branch 2'])
 
523
        os.chdir('../parent')
 
524
        self.run_bzr('merge ../child')
 
525
        wt.commit('merge branch 1')
 
526
        b = wt.branch
 
527
        sio = self.make_utf8_encoded_stringio()
 
528
        lf = log.LongLogFormatter(to_file=sio, levels=0)
 
529
        log.show_log(b, lf, verbose=True)
 
530
        the_log = normalize_log(sio.getvalue())
 
531
        self.assertEqualDiff("""\
443
532
------------------------------------------------------------
444
533
revno: 2 [merge]
445
 
committer: Joe Foo <joe@foo.com>
 
534
committer: Lorem Ipsum <test@example.com>
446
535
branch nick: parent
447
 
timestamp: Tue 2005-11-22 00:00:04 +0000
 
536
timestamp: Just now
448
537
message:
449
538
  merge branch 1
450
539
    ------------------------------------------------------------
451
540
    revno: 1.1.2 [merge]
452
 
    committer: Joe Foo <joe@foo.com>
 
541
    committer: Lorem Ipsum <test@example.com>
453
542
    branch nick: child
454
 
    timestamp: Tue 2005-11-22 00:00:03 +0000
 
543
    timestamp: Just now
455
544
    message:
456
545
      merge branch 2
457
546
        ------------------------------------------------------------
458
547
        revno: 1.2.1
459
 
        committer: Joe Foo <joe@foo.com>
 
548
        committer: Lorem Ipsum <test@example.com>
460
549
        branch nick: smallerchild
461
 
        timestamp: Tue 2005-11-22 00:00:02 +0000
 
550
        timestamp: Just now
462
551
        message:
463
552
          branch 2
464
553
    ------------------------------------------------------------
465
554
    revno: 1.1.1
466
 
    committer: Joe Foo <joe@foo.com>
 
555
    committer: Lorem Ipsum <test@example.com>
467
556
    branch nick: child
468
 
    timestamp: Tue 2005-11-22 00:00:01 +0000
 
557
    timestamp: Just now
469
558
    message:
470
559
      branch 1
471
560
------------------------------------------------------------
472
561
revno: 1
473
 
committer: Joe Foo <joe@foo.com>
 
562
committer: Lorem Ipsum <test@example.com>
474
563
branch nick: parent
475
 
timestamp: Tue 2005-11-22 00:00:00 +0000
 
564
timestamp: Just now
476
565
message:
477
566
  first post
478
567
""",
479
 
            wt.branch, log.LongLogFormatter,
480
 
            formatter_kwargs=dict(levels=0),
481
 
            show_log_kwargs=dict(verbose=True))
 
568
                             the_log)
482
569
 
483
570
    def test_verbose_merge_revisions_contain_deltas(self):
484
571
        wt = self.make_branch_and_tree('parent')
485
572
        self.build_tree(['parent/f1', 'parent/f2'])
486
573
        wt.add(['f1','f2'])
487
 
        self.wt_commit(wt, 'first post')
488
 
        child_wt = wt.bzrdir.sprout('child').open_workingtree()
 
574
        wt.commit('first post')
 
575
        self.run_bzr('branch parent child')
489
576
        os.unlink('child/f1')
490
 
        self.build_tree_contents([('child/f2', 'hello\n')])
491
 
        self.wt_commit(child_wt, 'removed f1 and modified f2')
492
 
        wt.merge_from_branch(child_wt.branch)
493
 
        self.wt_commit(wt, 'merge branch 1')
494
 
        self.assertFormatterResult("""\
 
577
        file('child/f2', 'wb').write('hello\n')
 
578
        self.run_bzr(['commit', '-m', 'removed f1 and modified f2',
 
579
            'child'])
 
580
        os.chdir('parent')
 
581
        self.run_bzr('merge ../child')
 
582
        wt.commit('merge branch 1')
 
583
        b = wt.branch
 
584
        sio = self.make_utf8_encoded_stringio()
 
585
        lf = log.LongLogFormatter(to_file=sio, levels=0)
 
586
        log.show_log(b, lf, verbose=True)
 
587
        the_log = normalize_log(sio.getvalue())
 
588
        self.assertEqualDiff("""\
495
589
------------------------------------------------------------
496
590
revno: 2 [merge]
497
 
committer: Joe Foo <joe@foo.com>
 
591
committer: Lorem Ipsum <test@example.com>
498
592
branch nick: parent
499
 
timestamp: Tue 2005-11-22 00:00:02 +0000
 
593
timestamp: Just now
500
594
message:
501
595
  merge branch 1
502
596
removed:
505
599
  f2
506
600
    ------------------------------------------------------------
507
601
    revno: 1.1.1
508
 
    committer: Joe Foo <joe@foo.com>
 
602
    committer: Lorem Ipsum <test@example.com>
509
603
    branch nick: child
510
 
    timestamp: Tue 2005-11-22 00:00:01 +0000
 
604
    timestamp: Just now
511
605
    message:
512
606
      removed f1 and modified f2
513
607
    removed:
516
610
      f2
517
611
------------------------------------------------------------
518
612
revno: 1
519
 
committer: Joe Foo <joe@foo.com>
 
613
committer: Lorem Ipsum <test@example.com>
520
614
branch nick: parent
521
 
timestamp: Tue 2005-11-22 00:00:00 +0000
 
615
timestamp: Just now
522
616
message:
523
617
  first post
524
618
added:
525
619
  f1
526
620
  f2
527
621
""",
528
 
            wt.branch, log.LongLogFormatter,
529
 
            formatter_kwargs=dict(levels=0),
530
 
            show_log_kwargs=dict(verbose=True))
 
622
                             the_log)
531
623
 
532
624
    def test_trailing_newlines(self):
533
625
        wt = self.make_branch_and_tree('.')
534
 
        b = self.make_commits_with_trailing_newlines(wt)
535
 
        self.assertFormatterResult("""\
 
626
        b = make_commits_with_trailing_newlines(wt)
 
627
        sio = self.make_utf8_encoded_stringio()
 
628
        lf = log.LongLogFormatter(to_file=sio)
 
629
        log.show_log(b, lf)
 
630
        self.assertEqualDiff("""\
536
631
------------------------------------------------------------
537
632
revno: 3
538
633
committer: Joe Foo <joe@foo.com>
539
634
branch nick: test
540
 
timestamp: Tue 2005-11-22 00:00:02 +0000
 
635
timestamp: Mon 2005-11-21 09:32:56 -0600
541
636
message:
542
637
  single line with trailing newline
543
638
------------------------------------------------------------
544
639
revno: 2
 
640
author: Joe Bar <joe@bar.com>
545
641
committer: Joe Foo <joe@foo.com>
546
642
branch nick: test
547
 
timestamp: Tue 2005-11-22 00:00:01 +0000
 
643
timestamp: Mon 2005-11-21 09:27:22 -0600
548
644
message:
549
645
  multiline
550
646
  log
553
649
revno: 1
554
650
committer: Joe Foo <joe@foo.com>
555
651
branch nick: test
556
 
timestamp: Tue 2005-11-22 00:00:00 +0000
 
652
timestamp: Mon 2005-11-21 09:24:15 -0600
557
653
message:
558
654
  simple log message
559
655
""",
560
 
        b, log.LongLogFormatter)
 
656
                             sio.getvalue())
561
657
 
562
658
    def test_author_in_log(self):
563
659
        """Log includes the author name if it's set in
564
660
        the revision properties
565
661
        """
566
 
        wt = self.make_standard_commit('test_author_log',
567
 
            authors=['John Doe <jdoe@example.com>',
568
 
                     'Jane Rey <jrey@example.com>'])
569
 
        self.assertFormatterResult("""\
 
662
        wt = self.make_branch_and_tree('.')
 
663
        b = wt.branch
 
664
        self.build_tree(['a'])
 
665
        wt.add('a')
 
666
        b.nick = 'test_author_log'
 
667
        wt.commit(message='add a',
 
668
                  timestamp=1132711707,
 
669
                  timezone=36000,
 
670
                  committer='Lorem Ipsum <test@example.com>',
 
671
                  authors=['John Doe <jdoe@example.com>',
 
672
                           'Jane Rey <jrey@example.com>'])
 
673
        sio = StringIO()
 
674
        formatter = log.LongLogFormatter(to_file=sio)
 
675
        log.show_log(b, formatter)
 
676
        self.assertEqualDiff('''\
570
677
------------------------------------------------------------
571
678
revno: 1
572
679
author: John Doe <jdoe@example.com>, Jane Rey <jrey@example.com>
573
680
committer: Lorem Ipsum <test@example.com>
574
681
branch nick: test_author_log
575
 
timestamp: Tue 2005-11-22 00:00:00 +0000
 
682
timestamp: Wed 2005-11-23 12:08:27 +1000
576
683
message:
577
684
  add a
578
 
""",
579
 
        wt.branch, log.LongLogFormatter)
 
685
''',
 
686
                             sio.getvalue())
580
687
 
581
688
    def test_properties_in_log(self):
582
689
        """Log includes the custom properties returned by the registered
583
690
        handlers.
584
691
        """
585
 
        wt = self.make_standard_commit('test_properties_in_log')
586
 
        def trivial_custom_prop_handler(revision):
587
 
            return {'test_prop':'test_value'}
 
692
        wt = self.make_branch_and_tree('.')
 
693
        b = wt.branch
 
694
        self.build_tree(['a'])
 
695
        wt.add('a')
 
696
        b.nick = 'test_properties_in_log'
 
697
        wt.commit(message='add a',
 
698
                  timestamp=1132711707,
 
699
                  timezone=36000,
 
700
                  committer='Lorem Ipsum <test@example.com>',
 
701
                  authors=['John Doe <jdoe@example.com>'])
 
702
        sio = StringIO()
 
703
        formatter = log.LongLogFormatter(to_file=sio)
 
704
        try:
 
705
            def trivial_custom_prop_handler(revision):
 
706
                return {'test_prop':'test_value'}
588
707
 
589
 
        # Cleaned up in setUp()
590
 
        log.properties_handler_registry.register(
591
 
            'trivial_custom_prop_handler',
592
 
            trivial_custom_prop_handler)
593
 
        self.assertFormatterResult("""\
 
708
            log.properties_handler_registry.register(
 
709
                'trivial_custom_prop_handler',
 
710
                trivial_custom_prop_handler)
 
711
            log.show_log(b, formatter)
 
712
        finally:
 
713
            log.properties_handler_registry.remove(
 
714
                'trivial_custom_prop_handler')
 
715
            self.assertEqualDiff('''\
594
716
------------------------------------------------------------
595
717
revno: 1
596
718
test_prop: test_value
597
719
author: John Doe <jdoe@example.com>
598
720
committer: Lorem Ipsum <test@example.com>
599
721
branch nick: test_properties_in_log
600
 
timestamp: Tue 2005-11-22 00:00:00 +0000
 
722
timestamp: Wed 2005-11-23 12:08:27 +1000
601
723
message:
602
724
  add a
603
 
""",
604
 
            wt.branch, log.LongLogFormatter)
 
725
''',
 
726
                                 sio.getvalue())
605
727
 
606
728
    def test_properties_in_short_log(self):
607
729
        """Log includes the custom properties returned by the registered
608
730
        handlers.
609
731
        """
610
 
        wt = self.make_standard_commit('test_properties_in_short_log')
611
 
        def trivial_custom_prop_handler(revision):
612
 
            return {'test_prop':'test_value'}
 
732
        wt = self.make_branch_and_tree('.')
 
733
        b = wt.branch
 
734
        self.build_tree(['a'])
 
735
        wt.add('a')
 
736
        b.nick = 'test_properties_in_short_log'
 
737
        wt.commit(message='add a',
 
738
                  timestamp=1132711707,
 
739
                  timezone=36000,
 
740
                  committer='Lorem Ipsum <test@example.com>',
 
741
                  authors=['John Doe <jdoe@example.com>'])
 
742
        sio = StringIO()
 
743
        formatter = log.ShortLogFormatter(to_file=sio)
 
744
        try:
 
745
            def trivial_custom_prop_handler(revision):
 
746
                return {'test_prop':'test_value'}
613
747
 
614
 
        log.properties_handler_registry.register(
615
 
            'trivial_custom_prop_handler',
616
 
            trivial_custom_prop_handler)
617
 
        self.assertFormatterResult("""\
618
 
    1 John Doe\t2005-11-22
 
748
            log.properties_handler_registry.register(
 
749
                'trivial_custom_prop_handler',
 
750
                trivial_custom_prop_handler)
 
751
            log.show_log(b, formatter)
 
752
        finally:
 
753
            log.properties_handler_registry.remove(
 
754
                'trivial_custom_prop_handler')
 
755
            self.assertEqualDiff('''\
 
756
    1 John Doe\t2005-11-23
619
757
      test_prop: test_value
620
758
      add a
621
759
 
622
 
""",
623
 
            wt.branch, log.ShortLogFormatter)
 
760
''',
 
761
                                 sio.getvalue())
624
762
 
625
763
    def test_error_in_properties_handler(self):
626
764
        """Log includes the custom properties returned by the registered
627
765
        handlers.
628
766
        """
629
 
        wt = self.make_standard_commit('error_in_properties_handler',
630
 
            revprops={'first_prop':'first_value'})
631
 
        sio = self.make_utf8_encoded_stringio()
 
767
        wt = self.make_branch_and_tree('.')
 
768
        b = wt.branch
 
769
        self.build_tree(['a'])
 
770
        wt.add('a')
 
771
        b.nick = 'test_author_log'
 
772
        wt.commit(message='add a',
 
773
                  timestamp=1132711707,
 
774
                  timezone=36000,
 
775
                  committer='Lorem Ipsum <test@example.com>',
 
776
                  authors=['John Doe <jdoe@example.com>'],
 
777
                  revprops={'first_prop':'first_value'})
 
778
        sio = StringIO()
632
779
        formatter = log.LongLogFormatter(to_file=sio)
633
 
        def trivial_custom_prop_handler(revision):
634
 
            raise StandardError("a test error")
 
780
        try:
 
781
            def trivial_custom_prop_handler(revision):
 
782
                raise StandardError("a test error")
635
783
 
636
 
        log.properties_handler_registry.register(
637
 
            'trivial_custom_prop_handler',
638
 
            trivial_custom_prop_handler)
639
 
        self.assertRaises(StandardError, log.show_log, wt.branch, formatter,)
 
784
            log.properties_handler_registry.register(
 
785
                'trivial_custom_prop_handler',
 
786
                trivial_custom_prop_handler)
 
787
            self.assertRaises(StandardError, log.show_log, b, formatter,)
 
788
        finally:
 
789
            log.properties_handler_registry.remove(
 
790
                'trivial_custom_prop_handler')
640
791
 
641
792
    def test_properties_handler_bad_argument(self):
642
 
        wt = self.make_standard_commit('bad_argument',
643
 
              revprops={'a_prop':'test_value'})
644
 
        sio = self.make_utf8_encoded_stringio()
 
793
        wt = self.make_branch_and_tree('.')
 
794
        b = wt.branch
 
795
        self.build_tree(['a'])
 
796
        wt.add('a')
 
797
        b.nick = 'test_author_log'
 
798
        wt.commit(message='add a',
 
799
                  timestamp=1132711707,
 
800
                  timezone=36000,
 
801
                  committer='Lorem Ipsum <test@example.com>',
 
802
                  authors=['John Doe <jdoe@example.com>'],
 
803
                  revprops={'a_prop':'test_value'})
 
804
        sio = StringIO()
645
805
        formatter = log.LongLogFormatter(to_file=sio)
646
 
        def bad_argument_prop_handler(revision):
647
 
            return {'custom_prop_name':revision.properties['a_prop']}
648
 
 
649
 
        log.properties_handler_registry.register(
650
 
            'bad_argument_prop_handler',
651
 
            bad_argument_prop_handler)
652
 
 
653
 
        self.assertRaises(AttributeError, formatter.show_properties,
654
 
                          'a revision', '')
655
 
 
656
 
        revision = wt.branch.repository.get_revision(wt.branch.last_revision())
657
 
        formatter.show_properties(revision, '')
658
 
        self.assertEqualDiff('''custom_prop_name: test_value\n''',
659
 
                             sio.getvalue())
660
 
 
661
 
 
662
 
class TestLongLogFormatterWithoutMergeRevisions(TestCaseForLogFormatter):
 
806
        try:
 
807
            def bad_argument_prop_handler(revision):
 
808
                return {'custom_prop_name':revision.properties['a_prop']}
 
809
 
 
810
            log.properties_handler_registry.register(
 
811
                'bad_argument_prop_handler',
 
812
                bad_argument_prop_handler)
 
813
 
 
814
            self.assertRaises(AttributeError, formatter.show_properties,
 
815
                              'a revision', '')
 
816
 
 
817
            revision = b.repository.get_revision(b.last_revision())
 
818
            formatter.show_properties(revision, '')
 
819
            self.assertEqualDiff('''custom_prop_name: test_value\n''',
 
820
                                 sio.getvalue())
 
821
        finally:
 
822
            log.properties_handler_registry.remove(
 
823
                'bad_argument_prop_handler')
 
824
 
 
825
 
 
826
class TestLongLogFormatterWithoutMergeRevisions(TestCaseWithoutPropsHandler):
663
827
 
664
828
    def test_long_verbose_log(self):
665
829
        """Verbose log includes changed files
666
830
 
667
831
        bug #4676
668
832
        """
669
 
        wt = self.make_standard_commit('test_long_verbose_log', authors=[])
670
 
        self.assertFormatterResult("""\
 
833
        wt = self.make_branch_and_tree('.')
 
834
        b = wt.branch
 
835
        self.build_tree(['a'])
 
836
        wt.add('a')
 
837
        # XXX: why does a longer nick show up?
 
838
        b.nick = 'test_verbose_log'
 
839
        wt.commit(message='add a',
 
840
                  timestamp=1132711707,
 
841
                  timezone=36000,
 
842
                  committer='Lorem Ipsum <test@example.com>')
 
843
        logfile = file('out.tmp', 'w+')
 
844
        formatter = log.LongLogFormatter(to_file=logfile, levels=1)
 
845
        log.show_log(b, formatter, verbose=True)
 
846
        logfile.flush()
 
847
        logfile.seek(0)
 
848
        log_contents = logfile.read()
 
849
        self.assertEqualDiff('''\
671
850
------------------------------------------------------------
672
851
revno: 1
673
852
committer: Lorem Ipsum <test@example.com>
674
 
branch nick: test_long_verbose_log
675
 
timestamp: Tue 2005-11-22 00:00:00 +0000
 
853
branch nick: test_verbose_log
 
854
timestamp: Wed 2005-11-23 12:08:27 +1000
676
855
message:
677
856
  add a
678
857
added:
679
858
  a
680
 
""",
681
 
            wt.branch, log.LongLogFormatter,
682
 
            formatter_kwargs=dict(levels=1),
683
 
            show_log_kwargs=dict(verbose=True))
 
859
''',
 
860
                             log_contents)
684
861
 
685
862
    def test_long_verbose_contain_deltas(self):
686
863
        wt = self.make_branch_and_tree('parent')
687
864
        self.build_tree(['parent/f1', 'parent/f2'])
688
865
        wt.add(['f1','f2'])
689
 
        self.wt_commit(wt, 'first post')
690
 
        child_wt = wt.bzrdir.sprout('child').open_workingtree()
 
866
        wt.commit('first post')
 
867
        self.run_bzr('branch parent child')
691
868
        os.unlink('child/f1')
692
 
        self.build_tree_contents([('child/f2', 'hello\n')])
693
 
        self.wt_commit(child_wt, 'removed f1 and modified f2')
694
 
        wt.merge_from_branch(child_wt.branch)
695
 
        self.wt_commit(wt, 'merge branch 1')
696
 
        self.assertFormatterResult("""\
 
869
        file('child/f2', 'wb').write('hello\n')
 
870
        self.run_bzr(['commit', '-m', 'removed f1 and modified f2',
 
871
            'child'])
 
872
        os.chdir('parent')
 
873
        self.run_bzr('merge ../child')
 
874
        wt.commit('merge branch 1')
 
875
        b = wt.branch
 
876
        sio = self.make_utf8_encoded_stringio()
 
877
        lf = log.LongLogFormatter(to_file=sio, levels=1)
 
878
        log.show_log(b, lf, verbose=True)
 
879
        the_log = normalize_log(sio.getvalue())
 
880
        self.assertEqualDiff("""\
697
881
------------------------------------------------------------
698
882
revno: 2 [merge]
699
 
committer: Joe Foo <joe@foo.com>
 
883
committer: Lorem Ipsum <test@example.com>
700
884
branch nick: parent
701
 
timestamp: Tue 2005-11-22 00:00:02 +0000
 
885
timestamp: Just now
702
886
message:
703
887
  merge branch 1
704
888
removed:
707
891
  f2
708
892
------------------------------------------------------------
709
893
revno: 1
710
 
committer: Joe Foo <joe@foo.com>
 
894
committer: Lorem Ipsum <test@example.com>
711
895
branch nick: parent
712
 
timestamp: Tue 2005-11-22 00:00:00 +0000
 
896
timestamp: Just now
713
897
message:
714
898
  first post
715
899
added:
716
900
  f1
717
901
  f2
718
902
""",
719
 
            wt.branch, log.LongLogFormatter,
720
 
            formatter_kwargs=dict(levels=1),
721
 
            show_log_kwargs=dict(verbose=True))
 
903
                             the_log)
722
904
 
723
905
    def test_long_trailing_newlines(self):
724
906
        wt = self.make_branch_and_tree('.')
725
 
        b = self.make_commits_with_trailing_newlines(wt)
726
 
        self.assertFormatterResult("""\
 
907
        b = make_commits_with_trailing_newlines(wt)
 
908
        sio = self.make_utf8_encoded_stringio()
 
909
        lf = log.LongLogFormatter(to_file=sio, levels=1)
 
910
        log.show_log(b, lf)
 
911
        self.assertEqualDiff("""\
727
912
------------------------------------------------------------
728
913
revno: 3
729
914
committer: Joe Foo <joe@foo.com>
730
915
branch nick: test
731
 
timestamp: Tue 2005-11-22 00:00:02 +0000
 
916
timestamp: Mon 2005-11-21 09:32:56 -0600
732
917
message:
733
918
  single line with trailing newline
734
919
------------------------------------------------------------
735
920
revno: 2
 
921
author: Joe Bar <joe@bar.com>
736
922
committer: Joe Foo <joe@foo.com>
737
923
branch nick: test
738
 
timestamp: Tue 2005-11-22 00:00:01 +0000
 
924
timestamp: Mon 2005-11-21 09:27:22 -0600
739
925
message:
740
926
  multiline
741
927
  log
744
930
revno: 1
745
931
committer: Joe Foo <joe@foo.com>
746
932
branch nick: test
747
 
timestamp: Tue 2005-11-22 00:00:00 +0000
 
933
timestamp: Mon 2005-11-21 09:24:15 -0600
748
934
message:
749
935
  simple log message
750
936
""",
751
 
        b, log.LongLogFormatter,
752
 
        formatter_kwargs=dict(levels=1))
 
937
                             sio.getvalue())
753
938
 
754
939
    def test_long_author_in_log(self):
755
940
        """Log includes the author name if it's set in
756
941
        the revision properties
757
942
        """
758
 
        wt = self.make_standard_commit('test_author_log')
759
 
        self.assertFormatterResult("""\
 
943
        wt = self.make_branch_and_tree('.')
 
944
        b = wt.branch
 
945
        self.build_tree(['a'])
 
946
        wt.add('a')
 
947
        b.nick = 'test_author_log'
 
948
        wt.commit(message='add a',
 
949
                  timestamp=1132711707,
 
950
                  timezone=36000,
 
951
                  committer='Lorem Ipsum <test@example.com>',
 
952
                  authors=['John Doe <jdoe@example.com>'])
 
953
        sio = StringIO()
 
954
        formatter = log.LongLogFormatter(to_file=sio, levels=1)
 
955
        log.show_log(b, formatter)
 
956
        self.assertEqualDiff('''\
760
957
------------------------------------------------------------
761
958
revno: 1
762
959
author: John Doe <jdoe@example.com>
763
960
committer: Lorem Ipsum <test@example.com>
764
961
branch nick: test_author_log
765
 
timestamp: Tue 2005-11-22 00:00:00 +0000
 
962
timestamp: Wed 2005-11-23 12:08:27 +1000
766
963
message:
767
964
  add a
768
 
""",
769
 
            wt.branch, log.LongLogFormatter,
770
 
            formatter_kwargs=dict(levels=1))
 
965
''',
 
966
                             sio.getvalue())
771
967
 
772
968
    def test_long_properties_in_log(self):
773
969
        """Log includes the custom properties returned by the registered
774
970
        handlers.
775
971
        """
776
 
        wt = self.make_standard_commit('test_properties_in_log')
777
 
        def trivial_custom_prop_handler(revision):
778
 
            return {'test_prop':'test_value'}
 
972
        wt = self.make_branch_and_tree('.')
 
973
        b = wt.branch
 
974
        self.build_tree(['a'])
 
975
        wt.add('a')
 
976
        b.nick = 'test_properties_in_log'
 
977
        wt.commit(message='add a',
 
978
                  timestamp=1132711707,
 
979
                  timezone=36000,
 
980
                  committer='Lorem Ipsum <test@example.com>',
 
981
                  authors=['John Doe <jdoe@example.com>'])
 
982
        sio = StringIO()
 
983
        formatter = log.LongLogFormatter(to_file=sio, levels=1)
 
984
        try:
 
985
            def trivial_custom_prop_handler(revision):
 
986
                return {'test_prop':'test_value'}
779
987
 
780
 
        log.properties_handler_registry.register(
781
 
            'trivial_custom_prop_handler',
782
 
            trivial_custom_prop_handler)
783
 
        self.assertFormatterResult("""\
 
988
            log.properties_handler_registry.register(
 
989
                'trivial_custom_prop_handler',
 
990
                trivial_custom_prop_handler)
 
991
            log.show_log(b, formatter)
 
992
        finally:
 
993
            log.properties_handler_registry.remove(
 
994
                'trivial_custom_prop_handler')
 
995
            self.assertEqualDiff('''\
784
996
------------------------------------------------------------
785
997
revno: 1
786
998
test_prop: test_value
787
999
author: John Doe <jdoe@example.com>
788
1000
committer: Lorem Ipsum <test@example.com>
789
1001
branch nick: test_properties_in_log
790
 
timestamp: Tue 2005-11-22 00:00:00 +0000
 
1002
timestamp: Wed 2005-11-23 12:08:27 +1000
791
1003
message:
792
1004
  add a
793
 
""",
794
 
            wt.branch, log.LongLogFormatter,
795
 
            formatter_kwargs=dict(levels=1))
796
 
 
797
 
 
798
 
class TestLineLogFormatter(TestCaseForLogFormatter):
 
1005
''',
 
1006
                                 sio.getvalue())
 
1007
 
 
1008
 
 
1009
class TestLineLogFormatter(tests.TestCaseWithTransport):
799
1010
 
800
1011
    def test_line_log(self):
801
1012
        """Line log should show revno
802
1013
 
803
1014
        bug #5162
804
1015
        """
805
 
        wt = self.make_standard_commit('test-line-log',
806
 
                committer='Line-Log-Formatter Tester <test@line.log>',
807
 
                authors=[])
808
 
        self.assertFormatterResult("""\
809
 
1: Line-Log-Formatte... 2005-11-22 add a
810
 
""",
811
 
            wt.branch, log.LineLogFormatter)
 
1016
        wt = self.make_branch_and_tree('.')
 
1017
        b = wt.branch
 
1018
        self.build_tree(['a'])
 
1019
        wt.add('a')
 
1020
        b.nick = 'test-line-log'
 
1021
        wt.commit(message='add a',
 
1022
                  timestamp=1132711707,
 
1023
                  timezone=36000,
 
1024
                  committer='Line-Log-Formatter Tester <test@line.log>')
 
1025
        logfile = file('out.tmp', 'w+')
 
1026
        formatter = log.LineLogFormatter(to_file=logfile)
 
1027
        log.show_log(b, formatter)
 
1028
        logfile.flush()
 
1029
        logfile.seek(0)
 
1030
        log_contents = logfile.read()
 
1031
        self.assertEqualDiff('1: Line-Log-Formatte... 2005-11-23 add a\n',
 
1032
                             log_contents)
812
1033
 
813
1034
    def test_trailing_newlines(self):
814
1035
        wt = self.make_branch_and_tree('.')
815
 
        b = self.make_commits_with_trailing_newlines(wt)
816
 
        self.assertFormatterResult("""\
817
 
3: Joe Foo 2005-11-22 single line with trailing newline
818
 
2: Joe Foo 2005-11-22 multiline
819
 
1: Joe Foo 2005-11-22 simple log message
 
1036
        b = make_commits_with_trailing_newlines(wt)
 
1037
        sio = self.make_utf8_encoded_stringio()
 
1038
        lf = log.LineLogFormatter(to_file=sio)
 
1039
        log.show_log(b, lf)
 
1040
        self.assertEqualDiff("""\
 
1041
3: Joe Foo 2005-11-21 single line with trailing newline
 
1042
2: Joe Bar 2005-11-21 multiline
 
1043
1: Joe Foo 2005-11-21 simple log message
820
1044
""",
821
 
            b, log.LineLogFormatter)
 
1045
                             sio.getvalue())
 
1046
 
 
1047
    def _prepare_tree_with_merges(self, with_tags=False):
 
1048
        wt = self.make_branch_and_memory_tree('.')
 
1049
        wt.lock_write()
 
1050
        self.addCleanup(wt.unlock)
 
1051
        wt.add('')
 
1052
        wt.commit('rev-1', rev_id='rev-1',
 
1053
                  timestamp=1132586655, timezone=36000,
 
1054
                  committer='Joe Foo <joe@foo.com>')
 
1055
        wt.commit('rev-merged', rev_id='rev-2a',
 
1056
                  timestamp=1132586700, timezone=36000,
 
1057
                  committer='Joe Foo <joe@foo.com>')
 
1058
        wt.set_parent_ids(['rev-1', 'rev-2a'])
 
1059
        wt.branch.set_last_revision_info(1, 'rev-1')
 
1060
        wt.commit('rev-2', rev_id='rev-2b',
 
1061
                  timestamp=1132586800, timezone=36000,
 
1062
                  committer='Joe Foo <joe@foo.com>')
 
1063
        if with_tags:
 
1064
            branch = wt.branch
 
1065
            branch.tags.set_tag('v0.2', 'rev-2b')
 
1066
            wt.commit('rev-3', rev_id='rev-3',
 
1067
                      timestamp=1132586900, timezone=36000,
 
1068
                      committer='Jane Foo <jane@foo.com>')
 
1069
            branch.tags.set_tag('v1.0rc1', 'rev-3')
 
1070
            branch.tags.set_tag('v1.0', 'rev-3')
 
1071
        return wt
822
1072
 
823
1073
    def test_line_log_single_merge_revision(self):
824
1074
        wt = self._prepare_tree_with_merges()
 
1075
        logfile = self.make_utf8_encoded_stringio()
 
1076
        formatter = log.LineLogFormatter(to_file=logfile)
825
1077
        revspec = revisionspec.RevisionSpec.from_string('1.1.1')
826
 
        rev = revspec.in_history(wt.branch)
827
 
        self.assertFormatterResult("""\
 
1078
        wtb = wt.branch
 
1079
        rev = revspec.in_history(wtb)
 
1080
        log.show_log(wtb, formatter, start_revision=rev, end_revision=rev)
 
1081
        self.assertEqualDiff("""\
828
1082
1.1.1: Joe Foo 2005-11-22 rev-merged
829
1083
""",
830
 
            wt.branch, log.LineLogFormatter,
831
 
            show_log_kwargs=dict(start_revision=rev, end_revision=rev))
 
1084
                             logfile.getvalue())
832
1085
 
833
1086
    def test_line_log_with_tags(self):
834
1087
        wt = self._prepare_tree_with_merges(with_tags=True)
835
 
        self.assertFormatterResult("""\
836
 
3: Joe Foo 2005-11-22 {v1.0, v1.0rc1} rev-3
 
1088
        logfile = self.make_utf8_encoded_stringio()
 
1089
        formatter = log.LineLogFormatter(to_file=logfile)
 
1090
        log.show_log(wt.branch, formatter)
 
1091
        self.assertEqualDiff("""\
 
1092
3: Jane Foo 2005-11-22 {v1.0, v1.0rc1} rev-3
837
1093
2: Joe Foo 2005-11-22 [merge] {v0.2} rev-2
838
1094
1: Joe Foo 2005-11-22 rev-1
839
1095
""",
840
 
            wt.branch, log.LineLogFormatter)
841
 
 
842
 
 
843
 
class TestLineLogFormatterWithMergeRevisions(TestCaseForLogFormatter):
 
1096
                             logfile.getvalue())
 
1097
 
 
1098
class TestLineLogFormatterWithMergeRevisions(tests.TestCaseWithTransport):
844
1099
 
845
1100
    def test_line_merge_revs_log(self):
846
1101
        """Line log should show revno
847
1102
 
848
1103
        bug #5162
849
1104
        """
850
 
        wt = self.make_standard_commit('test-line-log',
851
 
                committer='Line-Log-Formatter Tester <test@line.log>',
852
 
                authors=[])
853
 
        self.assertFormatterResult("""\
854
 
1: Line-Log-Formatte... 2005-11-22 add a
855
 
""",
856
 
            wt.branch, log.LineLogFormatter)
 
1105
        wt = self.make_branch_and_tree('.')
 
1106
        b = wt.branch
 
1107
        self.build_tree(['a'])
 
1108
        wt.add('a')
 
1109
        b.nick = 'test-line-log'
 
1110
        wt.commit(message='add a',
 
1111
                  timestamp=1132711707,
 
1112
                  timezone=36000,
 
1113
                  committer='Line-Log-Formatter Tester <test@line.log>')
 
1114
        logfile = file('out.tmp', 'w+')
 
1115
        formatter = log.LineLogFormatter(to_file=logfile, levels=0)
 
1116
        log.show_log(b, formatter)
 
1117
        logfile.flush()
 
1118
        logfile.seek(0)
 
1119
        log_contents = logfile.read()
 
1120
        self.assertEqualDiff('1: Line-Log-Formatte... 2005-11-23 add a\n',
 
1121
                             log_contents)
857
1122
 
858
1123
    def test_line_merge_revs_log_single_merge_revision(self):
859
 
        wt = self._prepare_tree_with_merges()
 
1124
        wt = self.make_branch_and_memory_tree('.')
 
1125
        wt.lock_write()
 
1126
        self.addCleanup(wt.unlock)
 
1127
        wt.add('')
 
1128
        wt.commit('rev-1', rev_id='rev-1',
 
1129
                  timestamp=1132586655, timezone=36000,
 
1130
                  committer='Joe Foo <joe@foo.com>')
 
1131
        wt.commit('rev-merged', rev_id='rev-2a',
 
1132
                  timestamp=1132586700, timezone=36000,
 
1133
                  committer='Joe Foo <joe@foo.com>')
 
1134
        wt.set_parent_ids(['rev-1', 'rev-2a'])
 
1135
        wt.branch.set_last_revision_info(1, 'rev-1')
 
1136
        wt.commit('rev-2', rev_id='rev-2b',
 
1137
                  timestamp=1132586800, timezone=36000,
 
1138
                  committer='Joe Foo <joe@foo.com>')
 
1139
        logfile = self.make_utf8_encoded_stringio()
 
1140
        formatter = log.LineLogFormatter(to_file=logfile, levels=0)
860
1141
        revspec = revisionspec.RevisionSpec.from_string('1.1.1')
861
 
        rev = revspec.in_history(wt.branch)
862
 
        self.assertFormatterResult("""\
 
1142
        wtb = wt.branch
 
1143
        rev = revspec.in_history(wtb)
 
1144
        log.show_log(wtb, formatter, start_revision=rev, end_revision=rev)
 
1145
        self.assertEqualDiff("""\
863
1146
1.1.1: Joe Foo 2005-11-22 rev-merged
864
1147
""",
865
 
            wt.branch, log.LineLogFormatter,
866
 
            formatter_kwargs=dict(levels=0),
867
 
            show_log_kwargs=dict(start_revision=rev, end_revision=rev))
 
1148
                             logfile.getvalue())
868
1149
 
869
1150
    def test_line_merge_revs_log_with_merges(self):
870
 
        wt = self._prepare_tree_with_merges()
871
 
        self.assertFormatterResult("""\
 
1151
        wt = self.make_branch_and_memory_tree('.')
 
1152
        wt.lock_write()
 
1153
        self.addCleanup(wt.unlock)
 
1154
        wt.add('')
 
1155
        wt.commit('rev-1', rev_id='rev-1',
 
1156
                  timestamp=1132586655, timezone=36000,
 
1157
                  committer='Joe Foo <joe@foo.com>')
 
1158
        wt.commit('rev-merged', rev_id='rev-2a',
 
1159
                  timestamp=1132586700, timezone=36000,
 
1160
                  committer='Joe Foo <joe@foo.com>')
 
1161
        wt.set_parent_ids(['rev-1', 'rev-2a'])
 
1162
        wt.branch.set_last_revision_info(1, 'rev-1')
 
1163
        wt.commit('rev-2', rev_id='rev-2b',
 
1164
                  timestamp=1132586800, timezone=36000,
 
1165
                  committer='Joe Foo <joe@foo.com>')
 
1166
        logfile = self.make_utf8_encoded_stringio()
 
1167
        formatter = log.LineLogFormatter(to_file=logfile, levels=0)
 
1168
        log.show_log(wt.branch, formatter)
 
1169
        self.assertEqualDiff("""\
872
1170
2: Joe Foo 2005-11-22 [merge] rev-2
873
1171
  1.1.1: Joe Foo 2005-11-22 rev-merged
874
1172
1: Joe Foo 2005-11-22 rev-1
875
1173
""",
876
 
            wt.branch, log.LineLogFormatter,
877
 
            formatter_kwargs=dict(levels=0))
878
 
 
879
 
 
880
 
class TestGetViewRevisions(tests.TestCaseWithTransport, TestLogMixin):
881
 
 
882
 
    def _get_view_revisions(self, *args, **kwargs):
883
 
        return self.applyDeprecated(symbol_versioning.deprecated_in((2, 2, 0)),
884
 
                                    log.get_view_revisions, *args, **kwargs)
 
1174
                             logfile.getvalue())
 
1175
 
 
1176
class TestGetViewRevisions(tests.TestCaseWithTransport):
885
1177
 
886
1178
    def make_tree_with_commits(self):
887
1179
        """Create a tree with well-known revision ids"""
888
1180
        wt = self.make_branch_and_tree('tree1')
889
 
        self.wt_commit(wt, 'commit one', rev_id='1')
890
 
        self.wt_commit(wt, 'commit two', rev_id='2')
891
 
        self.wt_commit(wt, 'commit three', rev_id='3')
 
1181
        wt.commit('commit one', rev_id='1')
 
1182
        wt.commit('commit two', rev_id='2')
 
1183
        wt.commit('commit three', rev_id='3')
892
1184
        mainline_revs = [None, '1', '2', '3']
893
1185
        rev_nos = {'1': 1, '2': 2, '3': 3}
894
1186
        return mainline_revs, rev_nos, wt
897
1189
        """Create a tree with well-known revision ids and a merge"""
898
1190
        mainline_revs, rev_nos, wt = self.make_tree_with_commits()
899
1191
        tree2 = wt.bzrdir.sprout('tree2').open_workingtree()
900
 
        self.wt_commit(tree2, 'four-a', rev_id='4a')
 
1192
        tree2.commit('four-a', rev_id='4a')
901
1193
        wt.merge_from_branch(tree2.branch)
902
 
        self.wt_commit(wt, 'four-b', rev_id='4b')
 
1194
        wt.commit('four-b', rev_id='4b')
903
1195
        mainline_revs.append('4b')
904
1196
        rev_nos['4b'] = 4
905
1197
        # 4a: 3.1.1
906
1198
        return mainline_revs, rev_nos, wt
907
1199
 
908
 
    def make_branch_with_many_merges(self):
 
1200
    def make_tree_with_many_merges(self):
909
1201
        """Create a tree with well-known revision ids"""
910
 
        builder = self.make_branch_builder('tree1')
911
 
        builder.start_series()
912
 
        builder.build_snapshot('1', None, [
913
 
            ('add', ('', 'TREE_ROOT', 'directory', '')),
914
 
            ('add', ('f', 'f-id', 'file', '1\n'))])
915
 
        builder.build_snapshot('2', ['1'], [])
916
 
        builder.build_snapshot('3a', ['2'], [
917
 
            ('modify', ('f-id', '1\n2\n3a\n'))])
918
 
        builder.build_snapshot('3b', ['2', '3a'], [
919
 
            ('modify', ('f-id', '1\n2\n3a\n'))])
920
 
        builder.build_snapshot('3c', ['2', '3b'], [
921
 
            ('modify', ('f-id', '1\n2\n3a\n'))])
922
 
        builder.build_snapshot('4a', ['3b'], [])
923
 
        builder.build_snapshot('4b', ['3c', '4a'], [])
924
 
        builder.finish_series()
925
 
 
926
 
        # 1
927
 
        # |
928
 
        # 2-.
929
 
        # |\ \
930
 
        # | | 3a
931
 
        # | |/
932
 
        # | 3b
933
 
        # |/|
934
 
        # 3c4a
935
 
        # |/
936
 
        # 4b
 
1202
        wt = self.make_branch_and_tree('tree1')
 
1203
        self.build_tree_contents([('tree1/f', '1\n')])
 
1204
        wt.add(['f'], ['f-id'])
 
1205
        wt.commit('commit one', rev_id='1')
 
1206
        wt.commit('commit two', rev_id='2')
 
1207
 
 
1208
        tree3 = wt.bzrdir.sprout('tree3').open_workingtree()
 
1209
        self.build_tree_contents([('tree3/f', '1\n2\n3a\n')])
 
1210
        tree3.commit('commit three a', rev_id='3a')
 
1211
 
 
1212
        tree2 = wt.bzrdir.sprout('tree2').open_workingtree()
 
1213
        tree2.merge_from_branch(tree3.branch)
 
1214
        tree2.commit('commit three b', rev_id='3b')
 
1215
 
 
1216
        wt.merge_from_branch(tree2.branch)
 
1217
        wt.commit('commit three c', rev_id='3c')
 
1218
        tree2.commit('four-a', rev_id='4a')
 
1219
 
 
1220
        wt.merge_from_branch(tree2.branch)
 
1221
        wt.commit('four-b', rev_id='4b')
937
1222
 
938
1223
        mainline_revs = [None, '1', '2', '3c', '4b']
939
1224
        rev_nos = {'1':1, '2':2, '3c': 3, '4b':4}
946
1231
            '4a': '2.2.2', # second commit tree 2
947
1232
            '4b': '4', # merges 4a to main
948
1233
            }
949
 
        return mainline_revs, rev_nos, builder.get_branch()
 
1234
        return mainline_revs, rev_nos, wt
950
1235
 
951
1236
    def test_get_view_revisions_forward(self):
952
1237
        """Test the get_view_revisions method"""
953
1238
        mainline_revs, rev_nos, wt = self.make_tree_with_commits()
954
1239
        wt.lock_read()
955
1240
        self.addCleanup(wt.unlock)
956
 
        revisions = list(self._get_view_revisions(
 
1241
        revisions = list(log.get_view_revisions(
957
1242
                mainline_revs, rev_nos, wt.branch, 'forward'))
958
1243
        self.assertEqual([('1', '1', 0), ('2', '2', 0), ('3', '3', 0)],
959
1244
                         revisions)
960
 
        revisions2 = list(self._get_view_revisions(
 
1245
        revisions2 = list(log.get_view_revisions(
961
1246
                mainline_revs, rev_nos, wt.branch, 'forward',
962
1247
                include_merges=False))
963
1248
        self.assertEqual(revisions, revisions2)
967
1252
        mainline_revs, rev_nos, wt = self.make_tree_with_commits()
968
1253
        wt.lock_read()
969
1254
        self.addCleanup(wt.unlock)
970
 
        revisions = list(self._get_view_revisions(
 
1255
        revisions = list(log.get_view_revisions(
971
1256
                mainline_revs, rev_nos, wt.branch, 'reverse'))
972
1257
        self.assertEqual([('3', '3', 0), ('2', '2', 0), ('1', '1', 0), ],
973
1258
                         revisions)
974
 
        revisions2 = list(self._get_view_revisions(
 
1259
        revisions2 = list(log.get_view_revisions(
975
1260
                mainline_revs, rev_nos, wt.branch, 'reverse',
976
1261
                include_merges=False))
977
1262
        self.assertEqual(revisions, revisions2)
981
1266
        mainline_revs, rev_nos, wt = self.make_tree_with_merges()
982
1267
        wt.lock_read()
983
1268
        self.addCleanup(wt.unlock)
984
 
        revisions = list(self._get_view_revisions(
 
1269
        revisions = list(log.get_view_revisions(
985
1270
                mainline_revs, rev_nos, wt.branch, 'forward'))
986
1271
        self.assertEqual([('1', '1', 0), ('2', '2', 0), ('3', '3', 0),
987
1272
                          ('4b', '4', 0), ('4a', '3.1.1', 1)],
988
1273
                         revisions)
989
 
        revisions = list(self._get_view_revisions(
 
1274
        revisions = list(log.get_view_revisions(
990
1275
                mainline_revs, rev_nos, wt.branch, 'forward',
991
1276
                include_merges=False))
992
1277
        self.assertEqual([('1', '1', 0), ('2', '2', 0), ('3', '3', 0),
998
1283
        mainline_revs, rev_nos, wt = self.make_tree_with_merges()
999
1284
        wt.lock_read()
1000
1285
        self.addCleanup(wt.unlock)
1001
 
        revisions = list(self._get_view_revisions(
 
1286
        revisions = list(log.get_view_revisions(
1002
1287
                mainline_revs, rev_nos, wt.branch, 'reverse'))
1003
1288
        self.assertEqual([('4b', '4', 0), ('4a', '3.1.1', 1),
1004
1289
                          ('3', '3', 0), ('2', '2', 0), ('1', '1', 0)],
1005
1290
                         revisions)
1006
 
        revisions = list(self._get_view_revisions(
 
1291
        revisions = list(log.get_view_revisions(
1007
1292
                mainline_revs, rev_nos, wt.branch, 'reverse',
1008
1293
                include_merges=False))
1009
1294
        self.assertEqual([('4b', '4', 0), ('3', '3', 0), ('2', '2', 0),
1012
1297
 
1013
1298
    def test_get_view_revisions_merge2(self):
1014
1299
        """Test get_view_revisions when there are merges"""
1015
 
        mainline_revs, rev_nos, b = self.make_branch_with_many_merges()
1016
 
        b.lock_read()
1017
 
        self.addCleanup(b.unlock)
1018
 
        revisions = list(self._get_view_revisions(
1019
 
                mainline_revs, rev_nos, b, 'forward'))
 
1300
        mainline_revs, rev_nos, wt = self.make_tree_with_many_merges()
 
1301
        wt.lock_read()
 
1302
        self.addCleanup(wt.unlock)
 
1303
        revisions = list(log.get_view_revisions(
 
1304
                mainline_revs, rev_nos, wt.branch, 'forward'))
1020
1305
        expected = [('1', '1', 0), ('2', '2', 0), ('3c', '3', 0),
1021
 
                    ('3b', '2.2.1', 1), ('3a', '2.1.1', 2), ('4b', '4', 0),
 
1306
                    ('3a', '2.1.1', 1), ('3b', '2.2.1', 1), ('4b', '4', 0),
1022
1307
                    ('4a', '2.2.2', 1)]
1023
1308
        self.assertEqual(expected, revisions)
1024
 
        revisions = list(self._get_view_revisions(
1025
 
                mainline_revs, rev_nos, b, 'forward',
 
1309
        revisions = list(log.get_view_revisions(
 
1310
                mainline_revs, rev_nos, wt.branch, 'forward',
1026
1311
                include_merges=False))
1027
1312
        self.assertEqual([('1', '1', 0), ('2', '2', 0), ('3c', '3', 0),
1028
1313
                          ('4b', '4', 0)],
1029
1314
                         revisions)
1030
1315
 
 
1316
 
1031
1317
    def test_file_id_for_range(self):
1032
 
        mainline_revs, rev_nos, b = self.make_branch_with_many_merges()
1033
 
        b.lock_read()
1034
 
        self.addCleanup(b.unlock)
 
1318
        mainline_revs, rev_nos, wt = self.make_tree_with_many_merges()
 
1319
        wt.lock_read()
 
1320
        self.addCleanup(wt.unlock)
1035
1321
 
1036
1322
        def rev_from_rev_id(revid, branch):
1037
1323
            revspec = revisionspec.RevisionSpec.from_string('revid:%s' % revid)
1038
1324
            return revspec.in_history(branch)
1039
1325
 
1040
1326
        def view_revs(start_rev, end_rev, file_id, direction):
1041
 
            revs = self.applyDeprecated(
1042
 
                symbol_versioning.deprecated_in((2, 2, 0)),
1043
 
                log.calculate_view_revisions,
1044
 
                b,
 
1327
            revs = log.calculate_view_revisions(
 
1328
                wt.branch,
1045
1329
                start_rev, # start_revision
1046
1330
                end_rev, # end_revision
1047
1331
                direction, # direction
1050
1334
                )
1051
1335
            return revs
1052
1336
 
1053
 
        rev_3a = rev_from_rev_id('3a', b)
1054
 
        rev_4b = rev_from_rev_id('4b', b)
1055
 
        self.assertEqual([('3c', '3', 0), ('3b', '2.2.1', 1),
1056
 
                          ('3a', '2.1.1', 2)],
 
1337
        rev_3a = rev_from_rev_id('3a', wt.branch)
 
1338
        rev_4b = rev_from_rev_id('4b', wt.branch)
 
1339
        self.assertEqual([('3c', '3', 0), ('3a', '2.1.1', 1)],
1057
1340
                          view_revs(rev_3a, rev_4b, 'f-id', 'reverse'))
1058
1341
        # Note: 3c still appears before 3a here because of depth-based sorting
1059
 
        self.assertEqual([('3c', '3', 0), ('3b', '2.2.1', 1),
1060
 
                          ('3a', '2.1.1', 2)],
 
1342
        self.assertEqual([('3c', '3', 0), ('3a', '2.1.1', 1)],
1061
1343
                          view_revs(rev_3a, rev_4b, 'f-id', 'forward'))
1062
1344
 
1063
1345
 
1064
1346
class TestGetRevisionsTouchingFileID(tests.TestCaseWithTransport):
1065
1347
 
1066
 
    def get_view_revisions(self, *args):
1067
 
        return self.applyDeprecated(symbol_versioning.deprecated_in((2, 2, 0)),
1068
 
                                    log.get_view_revisions, *args)
1069
 
 
1070
1348
    def create_tree_with_single_merge(self):
1071
1349
        """Create a branch with a moderate layout.
1072
1350
 
1090
1368
        #       use it. Since 'log' only uses the tree in a readonly
1091
1369
        #       fashion, it seems a shame to regenerate an identical
1092
1370
        #       tree for each test.
1093
 
        # TODO: vila 20100122 One way to address the shame above will be to
1094
 
        #       create a memory tree during test parametrization and give a
1095
 
        #       *copy* of this tree to each test. Copying a memory tree ought
1096
 
        #       to be cheap, at least cheaper than creating them with such
1097
 
        #       complex setups.
1098
1371
        tree = self.make_branch_and_tree('tree')
1099
1372
        tree.lock_write()
1100
1373
        self.addCleanup(tree.unlock)
1175
1448
        mainline = tree.branch.revision_history()
1176
1449
        mainline.insert(0, None)
1177
1450
        revnos = dict((rev, idx+1) for idx, rev in enumerate(mainline))
1178
 
        view_revs_iter = self.get_view_revisions(
1179
 
            mainline, revnos, tree.branch, 'reverse', True)
 
1451
        view_revs_iter = log.get_view_revisions(mainline, revnos, tree.branch,
 
1452
                                                'reverse', True)
1180
1453
        actual_revs = log._filter_revisions_touching_file_id(
1181
 
            tree.branch, file_id, list(view_revs_iter))
 
1454
                            tree.branch,
 
1455
                            file_id,
 
1456
                            list(view_revs_iter))
1182
1457
        self.assertEqual(revisions, [r for r, revno, depth in actual_revs])
1183
1458
 
1184
1459
    def test_file_id_f1(self):
1236
1511
 
1237
1512
class TestLogFormatter(tests.TestCase):
1238
1513
 
1239
 
    def setUp(self):
1240
 
        super(TestLogFormatter, self).setUp()
1241
 
        self.rev = revision.Revision('a-id')
1242
 
        self.lf = log.LogFormatter(None)
1243
 
 
1244
1514
    def test_short_committer(self):
1245
 
        def assertCommitter(expected, committer):
1246
 
            self.rev.committer = committer
1247
 
            self.assertEqual(expected, self.lf.short_committer(self.rev))
1248
 
 
1249
 
        assertCommitter('John Doe', 'John Doe <jdoe@example.com>')
1250
 
        assertCommitter('John Smith', 'John Smith <jsmith@example.com>')
1251
 
        assertCommitter('John Smith', 'John Smith')
1252
 
        assertCommitter('jsmith@example.com', 'jsmith@example.com')
1253
 
        assertCommitter('jsmith@example.com', '<jsmith@example.com>')
1254
 
        assertCommitter('John Smith', 'John Smith jsmith@example.com')
 
1515
        rev = revision.Revision('a-id')
 
1516
        rev.committer = 'John Doe <jdoe@example.com>'
 
1517
        lf = log.LogFormatter(None)
 
1518
        self.assertEqual('John Doe', lf.short_committer(rev))
 
1519
        rev.committer = 'John Smith <jsmith@example.com>'
 
1520
        self.assertEqual('John Smith', lf.short_committer(rev))
 
1521
        rev.committer = 'John Smith'
 
1522
        self.assertEqual('John Smith', lf.short_committer(rev))
 
1523
        rev.committer = 'jsmith@example.com'
 
1524
        self.assertEqual('jsmith@example.com', lf.short_committer(rev))
 
1525
        rev.committer = '<jsmith@example.com>'
 
1526
        self.assertEqual('jsmith@example.com', lf.short_committer(rev))
 
1527
        rev.committer = 'John Smith jsmith@example.com'
 
1528
        self.assertEqual('John Smith', lf.short_committer(rev))
1255
1529
 
1256
1530
    def test_short_author(self):
1257
 
        def assertAuthor(expected, author):
1258
 
            self.rev.properties['author'] = author
1259
 
            self.assertEqual(expected, self.lf.short_author(self.rev))
1260
 
 
1261
 
        assertAuthor('John Smith', 'John Smith <jsmith@example.com>')
1262
 
        assertAuthor('John Smith', 'John Smith')
1263
 
        assertAuthor('jsmith@example.com', 'jsmith@example.com')
1264
 
        assertAuthor('jsmith@example.com', '<jsmith@example.com>')
1265
 
        assertAuthor('John Smith', 'John Smith jsmith@example.com')
1266
 
 
1267
 
    def test_short_author_from_committer(self):
1268
 
        self.rev.committer = 'John Doe <jdoe@example.com>'
1269
 
        self.assertEqual('John Doe', self.lf.short_author(self.rev))
1270
 
 
1271
 
    def test_short_author_from_authors(self):
1272
 
        self.rev.properties['authors'] = ('John Smith <jsmith@example.com>\n'
1273
 
                                          'Jane Rey <jrey@example.com>')
1274
 
        self.assertEqual('John Smith', self.lf.short_author(self.rev))
 
1531
        rev = revision.Revision('a-id')
 
1532
        rev.committer = 'John Doe <jdoe@example.com>'
 
1533
        lf = log.LogFormatter(None)
 
1534
        self.assertEqual('John Doe', lf.short_author(rev))
 
1535
        rev.properties['author'] = 'John Smith <jsmith@example.com>'
 
1536
        self.assertEqual('John Smith', lf.short_author(rev))
 
1537
        rev.properties['author'] = 'John Smith'
 
1538
        self.assertEqual('John Smith', lf.short_author(rev))
 
1539
        rev.properties['author'] = 'jsmith@example.com'
 
1540
        self.assertEqual('jsmith@example.com', lf.short_author(rev))
 
1541
        rev.properties['author'] = '<jsmith@example.com>'
 
1542
        self.assertEqual('jsmith@example.com', lf.short_author(rev))
 
1543
        rev.properties['author'] = 'John Smith jsmith@example.com'
 
1544
        self.assertEqual('John Smith', lf.short_author(rev))
 
1545
        del rev.properties['author']
 
1546
        rev.properties['authors'] = ('John Smith <jsmith@example.com>\n'
 
1547
                'Jane Rey <jrey@example.com>')
 
1548
        self.assertEqual('John Smith', lf.short_author(rev))
1275
1549
 
1276
1550
 
1277
1551
class TestReverseByDepth(tests.TestCase):
1423
1697
        log.show_branch_change(tree.branch, s, 3, '3b')
1424
1698
        self.assertContainsRe(s.getvalue(), 'Removed Revisions:')
1425
1699
        self.assertNotContainsRe(s.getvalue(), 'Added Revisions:')
1426
 
 
1427
 
 
1428
 
 
1429
 
class TestLogWithBugs(TestCaseForLogFormatter, TestLogMixin):
1430
 
 
1431
 
    def setUp(self):
1432
 
        TestCaseForLogFormatter.setUp(self)
1433
 
        log.properties_handler_registry.register(
1434
 
            'bugs_properties_handler',
1435
 
            log._bugs_properties_handler)
1436
 
 
1437
 
    def make_commits_with_bugs(self):
1438
 
        """Helper method for LogFormatter tests"""
1439
 
        tree = self.make_branch_and_tree(u'.')
1440
 
        self.build_tree(['a', 'b'])
1441
 
        tree.add('a')
1442
 
        self.wt_commit(tree, 'simple log message', rev_id='a1',
1443
 
                       revprops={'bugs': 'test://bug/id fixed'})
1444
 
        tree.add('b')
1445
 
        self.wt_commit(tree, 'multiline\nlog\nmessage\n', rev_id='a2',
1446
 
                       authors=['Joe Bar <joe@bar.com>'],
1447
 
                       revprops={'bugs': 'test://bug/id fixed\n'
1448
 
                                 'test://bug/2 fixed'})
1449
 
        return tree
1450
 
 
1451
 
 
1452
 
    def test_long_bugs(self):
1453
 
        tree = self.make_commits_with_bugs()
1454
 
        self.assertFormatterResult("""\
1455
 
------------------------------------------------------------
1456
 
revno: 2
1457
 
fixes bug(s): test://bug/id test://bug/2
1458
 
author: Joe Bar <joe@bar.com>
1459
 
committer: Joe Foo <joe@foo.com>
1460
 
branch nick: work
1461
 
timestamp: Tue 2005-11-22 00:00:01 +0000
1462
 
message:
1463
 
  multiline
1464
 
  log
1465
 
  message
1466
 
------------------------------------------------------------
1467
 
revno: 1
1468
 
fixes bug(s): test://bug/id
1469
 
committer: Joe Foo <joe@foo.com>
1470
 
branch nick: work
1471
 
timestamp: Tue 2005-11-22 00:00:00 +0000
1472
 
message:
1473
 
  simple log message
1474
 
""",
1475
 
            tree.branch, log.LongLogFormatter)
1476
 
 
1477
 
    def test_short_bugs(self):
1478
 
        tree = self.make_commits_with_bugs()
1479
 
        self.assertFormatterResult("""\
1480
 
    2 Joe Bar\t2005-11-22
1481
 
      fixes bug(s): test://bug/id test://bug/2
1482
 
      multiline
1483
 
      log
1484
 
      message
1485
 
 
1486
 
    1 Joe Foo\t2005-11-22
1487
 
      fixes bug(s): test://bug/id
1488
 
      simple log message
1489
 
 
1490
 
""",
1491
 
            tree.branch, log.ShortLogFormatter)
1492
 
 
1493
 
    def test_wrong_bugs_property(self):
1494
 
        tree = self.make_branch_and_tree(u'.')
1495
 
        self.build_tree(['foo'])
1496
 
        self.wt_commit(tree, 'simple log message', rev_id='a1',
1497
 
                       revprops={'bugs': 'test://bug/id invalid_value'})
1498
 
        self.assertFormatterResult("""\
1499
 
    1 Joe Foo\t2005-11-22
1500
 
      simple log message
1501
 
 
1502
 
""",
1503
 
            tree.branch, log.ShortLogFormatter)
1504
 
 
1505
 
    def test_bugs_handler_present(self):
1506
 
        self.properties_handler_registry.get('bugs_properties_handler')