~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_log.py

  • Committer: John Arbash Meinel
  • Date: 2010-02-17 17:11:16 UTC
  • mfrom: (4797.2.17 2.1)
  • mto: (4797.2.18 2.1)
  • mto: This revision was merged to the branch mainline in revision 5055.
  • Revision ID: john@arbash-meinel.com-20100217171116-h7t9223ystbnx5h8
merge bzr.2.1 in preparation for NEWS entry.

Show diffs side-by-side

added added

removed removed

Lines of Context:
18
18
from cStringIO import StringIO
19
19
 
20
20
from bzrlib import (
21
 
    branchbuilder,
22
21
    errors,
23
22
    log,
24
23
    registry,
25
24
    revision,
26
25
    revisionspec,
27
 
    symbol_versioning,
28
26
    tests,
29
27
    )
30
28
 
31
29
 
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):
 
30
class TestCaseForLogFormatter(tests.TestCaseWithTransport):
52
31
 
53
32
    def setUp(self):
54
33
        super(TestCaseForLogFormatter, self).setUp()
62
41
        self.addCleanup(restore)
63
42
 
64
43
    def assertFormatterResult(self, result, branch, formatter_class,
65
 
                              formatter_kwargs=None, show_log_kwargs=None):
 
44
                              formatter_kwargs=None, show_log_kwargs=None,
 
45
                              normalize=False):
66
46
        logfile = self.make_utf8_encoded_stringio()
67
47
        if formatter_kwargs is None:
68
48
            formatter_kwargs = {}
70
50
        if show_log_kwargs is None:
71
51
            show_log_kwargs = {}
72
52
        log.show_log(branch, formatter, **show_log_kwargs)
73
 
        self.assertEqualDiff(result, logfile.getvalue())
 
53
        log_content = logfile.getvalue()
 
54
        if normalize:
 
55
            log_content = normalize_log(log_content)
 
56
        self.assertEqualDiff(result, log_content)
74
57
 
75
58
    def make_standard_commit(self, branch_nick, **kwargs):
76
59
        wt = self.make_branch_and_tree('.')
79
62
        self.build_tree(['a'])
80
63
        wt.add(['a'])
81
64
        wt.branch.nick = branch_nick
 
65
        kwargs = dict(kwargs)
 
66
        kwargs.setdefault('message', 'add a')
 
67
        kwargs.setdefault('timestamp', 1132711707)
 
68
        kwargs.setdefault('timezone', 36000)
82
69
        kwargs.setdefault('committer', 'Lorem Ipsum <test@example.com>')
83
70
        kwargs.setdefault('authors', ['John Doe <jdoe@example.com>'])
84
 
        self.wt_commit(wt, 'add a', **kwargs)
 
71
        wt.commit(**kwargs)
85
72
        return wt
86
73
 
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
74
    def _prepare_tree_with_merges(self, with_tags=False):
103
75
        wt = self.make_branch_and_memory_tree('.')
104
76
        wt.lock_write()
105
77
        self.addCleanup(wt.unlock)
106
78
        wt.add('')
107
 
        self.wt_commit(wt, 'rev-1', rev_id='rev-1')
108
 
        self.wt_commit(wt, 'rev-merged', rev_id='rev-2a')
 
79
        wt.commit('rev-1', rev_id='rev-1',
 
80
                  timestamp=1132586655, timezone=36000,
 
81
                  committer='Joe Foo <joe@foo.com>')
 
82
        wt.commit('rev-merged', rev_id='rev-2a',
 
83
                  timestamp=1132586700, timezone=36000,
 
84
                  committer='Joe Foo <joe@foo.com>')
109
85
        wt.set_parent_ids(['rev-1', 'rev-2a'])
110
86
        wt.branch.set_last_revision_info(1, 'rev-1')
111
 
        self.wt_commit(wt, 'rev-2', rev_id='rev-2b')
 
87
        wt.commit('rev-2', rev_id='rev-2b',
 
88
                  timestamp=1132586800, timezone=36000,
 
89
                  committer='Joe Foo <joe@foo.com>')
112
90
        if with_tags:
113
91
            branch = wt.branch
114
92
            branch.tags.set_tag('v0.2', 'rev-2b')
115
 
            self.wt_commit(wt, 'rev-3', rev_id='rev-3')
 
93
            wt.commit('rev-3', rev_id='rev-3',
 
94
                      timestamp=1132586900, timezone=36000,
 
95
                      committer='Jane Foo <jane@foo.com>')
116
96
            branch.tags.set_tag('v1.0rc1', 'rev-3')
117
97
            branch.tags.set_tag('v1.0', 'rev-3')
118
98
        return wt
119
99
 
 
100
        
 
101
 
 
102
 
120
103
class LogCatcher(log.LogFormatter):
121
104
    """Pull log messages into a list rather than displaying them.
122
105
 
125
108
    being dependent on the formatting.
126
109
    """
127
110
 
128
 
    supports_merge_revisions = True
129
111
    supports_delta = True
130
 
    supports_diff = True
131
 
    preferred_levels = 0
132
112
 
133
 
    def __init__(self, *args, **kwargs):
134
 
        kwargs.update(dict(to_file=None))
135
 
        super(LogCatcher, self).__init__(*args, **kwargs)
 
113
    def __init__(self):
 
114
        super(LogCatcher, self).__init__(to_file=None)
136
115
        self.revisions = []
137
116
 
138
117
    def log_revision(self, revision):
281
260
        self.checkDelta(logentry.delta, added=['file1', 'file2'])
282
261
 
283
262
 
 
263
def make_commits_with_trailing_newlines(wt):
 
264
    """Helper method for LogFormatter tests"""
 
265
    b = wt.branch
 
266
    b.nick='test'
 
267
    open('a', 'wb').write('hello moto\n')
 
268
    wt.add('a')
 
269
    wt.commit('simple log message', rev_id='a1',
 
270
              timestamp=1132586655.459960938, timezone=-6*3600,
 
271
              committer='Joe Foo <joe@foo.com>')
 
272
    open('b', 'wb').write('goodbye\n')
 
273
    wt.add('b')
 
274
    wt.commit('multiline\nlog\nmessage\n', rev_id='a2',
 
275
              timestamp=1132586842.411175966, timezone=-6*3600,
 
276
              committer='Joe Foo <joe@foo.com>',
 
277
              authors=['Joe Bar <joe@bar.com>'])
 
278
 
 
279
    open('c', 'wb').write('just another manic monday\n')
 
280
    wt.add('c')
 
281
    wt.commit('single line with trailing newline\n', rev_id='a3',
 
282
              timestamp=1132587176.835228920, timezone=-6*3600,
 
283
              committer = 'Joe Foo <joe@foo.com>')
 
284
    return b
 
285
 
 
286
 
 
287
def normalize_log(log):
 
288
    """Replaces the variable lines of logs with fixed lines"""
 
289
    author = 'author: Dolor Sit <test@example.com>'
 
290
    committer = 'committer: Lorem Ipsum <test@example.com>'
 
291
    lines = log.splitlines(True)
 
292
    for idx,line in enumerate(lines):
 
293
        stripped_line = line.lstrip()
 
294
        indent = ' ' * (len(line) - len(stripped_line))
 
295
        if stripped_line.startswith('author:'):
 
296
            lines[idx] = indent + author + '\n'
 
297
        elif stripped_line.startswith('committer:'):
 
298
            lines[idx] = indent + committer + '\n'
 
299
        elif stripped_line.startswith('timestamp:'):
 
300
            lines[idx] = indent + 'timestamp: Just now\n'
 
301
    return ''.join(lines)
 
302
 
 
303
 
284
304
class TestShortLogFormatter(TestCaseForLogFormatter):
285
305
 
286
306
    def test_trailing_newlines(self):
287
307
        wt = self.make_branch_and_tree('.')
288
 
        b = self.make_commits_with_trailing_newlines(wt)
 
308
        b = make_commits_with_trailing_newlines(wt)
289
309
        self.assertFormatterResult("""\
290
 
    3 Joe Foo\t2005-11-22
 
310
    3 Joe Foo\t2005-11-21
291
311
      single line with trailing newline
292
312
 
293
 
    2 Joe Foo\t2005-11-22
 
313
    2 Joe Bar\t2005-11-21
294
314
      multiline
295
315
      log
296
316
      message
297
317
 
298
 
    1 Joe Foo\t2005-11-22
 
318
    1 Joe Foo\t2005-11-21
299
319
      simple log message
300
320
 
301
321
""",
328
348
            formatter_kwargs=dict(show_advice=True))
329
349
 
330
350
    def test_short_log_with_merges_and_range(self):
331
 
        wt = self._prepare_tree_with_merges()
332
 
        self.wt_commit(wt, 'rev-3a', rev_id='rev-3a')
 
351
        wt = self.make_branch_and_memory_tree('.')
 
352
        wt.lock_write()
 
353
        self.addCleanup(wt.unlock)
 
354
        wt.add('')
 
355
        wt.commit('rev-1', rev_id='rev-1',
 
356
                  timestamp=1132586655, timezone=36000,
 
357
                  committer='Joe Foo <joe@foo.com>')
 
358
        wt.commit('rev-merged', rev_id='rev-2a',
 
359
                  timestamp=1132586700, timezone=36000,
 
360
                  committer='Joe Foo <joe@foo.com>')
 
361
        wt.branch.set_last_revision_info(1, 'rev-1')
 
362
        wt.set_parent_ids(['rev-1', 'rev-2a'])
 
363
        wt.commit('rev-2b', rev_id='rev-2b',
 
364
                  timestamp=1132586800, timezone=36000,
 
365
                  committer='Joe Foo <joe@foo.com>')
 
366
        wt.commit('rev-3a', rev_id='rev-3a',
 
367
                  timestamp=1132586800, timezone=36000,
 
368
                  committer='Joe Foo <joe@foo.com>')
333
369
        wt.branch.set_last_revision_info(2, 'rev-2b')
334
370
        wt.set_parent_ids(['rev-2b', 'rev-3a'])
335
 
        self.wt_commit(wt, 'rev-3b', rev_id='rev-3b')
 
371
        wt.commit('rev-3b', rev_id='rev-3b',
 
372
                  timestamp=1132586800, timezone=36000,
 
373
                  committer='Joe Foo <joe@foo.com>')
336
374
        self.assertFormatterResult("""\
337
375
    3 Joe Foo\t2005-11-22 [merge]
338
376
      rev-3b
339
377
 
340
378
    2 Joe Foo\t2005-11-22 [merge]
341
 
      rev-2
 
379
      rev-2b
342
380
 
343
381
""",
344
382
            wt.branch, log.ShortLogFormatter,
347
385
    def test_short_log_with_tags(self):
348
386
        wt = self._prepare_tree_with_merges(with_tags=True)
349
387
        self.assertFormatterResult("""\
350
 
    3 Joe Foo\t2005-11-22 {v1.0, v1.0rc1}
 
388
    3 Jane Foo\t2005-11-22 {v1.0, v1.0rc1}
351
389
      rev-3
352
390
 
353
391
    2 Joe Foo\t2005-11-22 {v0.2} [merge]
360
398
            wt.branch, log.ShortLogFormatter)
361
399
 
362
400
    def test_short_log_single_merge_revision(self):
363
 
        wt = self._prepare_tree_with_merges()
 
401
        wt = self.make_branch_and_memory_tree('.')
 
402
        wt.lock_write()
 
403
        self.addCleanup(wt.unlock)
 
404
        wt.add('')
 
405
        wt.commit('rev-1', rev_id='rev-1',
 
406
                  timestamp=1132586655, timezone=36000,
 
407
                  committer='Joe Foo <joe@foo.com>')
 
408
        wt.commit('rev-merged', rev_id='rev-2a',
 
409
                  timestamp=1132586700, timezone=36000,
 
410
                  committer='Joe Foo <joe@foo.com>')
 
411
        wt.set_parent_ids(['rev-1', 'rev-2a'])
 
412
        wt.branch.set_last_revision_info(1, 'rev-1')
 
413
        wt.commit('rev-2', rev_id='rev-2b',
 
414
                  timestamp=1132586800, timezone=36000,
 
415
                  committer='Joe Foo <joe@foo.com>')
364
416
        revspec = revisionspec.RevisionSpec.from_string('1.1.1')
365
417
        rev = revspec.in_history(wt.branch)
366
418
        self.assertFormatterResult("""\
375
427
class TestShortLogFormatterWithMergeRevisions(TestCaseForLogFormatter):
376
428
 
377
429
    def test_short_merge_revs_log_with_merges(self):
378
 
        wt = self._prepare_tree_with_merges()
 
430
        wt = self.make_branch_and_memory_tree('.')
 
431
        wt.lock_write()
 
432
        self.addCleanup(wt.unlock)
 
433
        wt.add('')
 
434
        wt.commit('rev-1', rev_id='rev-1',
 
435
                  timestamp=1132586655, timezone=36000,
 
436
                  committer='Joe Foo <joe@foo.com>')
 
437
        wt.commit('rev-merged', rev_id='rev-2a',
 
438
                  timestamp=1132586700, timezone=36000,
 
439
                  committer='Joe Foo <joe@foo.com>')
 
440
        wt.set_parent_ids(['rev-1', 'rev-2a'])
 
441
        wt.branch.set_last_revision_info(1, 'rev-1')
 
442
        wt.commit('rev-2', rev_id='rev-2b',
 
443
                  timestamp=1132586800, timezone=36000,
 
444
                  committer='Joe Foo <joe@foo.com>')
379
445
        # Note that the 1.1.1 indenting is in fact correct given that
380
446
        # the revision numbers are right justified within 5 characters
381
447
        # for mainline revnos and 9 characters for dotted revnos.
394
460
            formatter_kwargs=dict(levels=0))
395
461
 
396
462
    def test_short_merge_revs_log_single_merge_revision(self):
397
 
        wt = self._prepare_tree_with_merges()
 
463
        wt = self.make_branch_and_memory_tree('.')
 
464
        wt.lock_write()
 
465
        self.addCleanup(wt.unlock)
 
466
        wt.add('')
 
467
        wt.commit('rev-1', rev_id='rev-1',
 
468
                  timestamp=1132586655, timezone=36000,
 
469
                  committer='Joe Foo <joe@foo.com>')
 
470
        wt.commit('rev-merged', rev_id='rev-2a',
 
471
                  timestamp=1132586700, timezone=36000,
 
472
                  committer='Joe Foo <joe@foo.com>')
 
473
        wt.set_parent_ids(['rev-1', 'rev-2a'])
 
474
        wt.branch.set_last_revision_info(1, 'rev-1')
 
475
        wt.commit('rev-2', rev_id='rev-2b',
 
476
                  timestamp=1132586800, timezone=36000,
 
477
                  committer='Joe Foo <joe@foo.com>')
398
478
        revspec = revisionspec.RevisionSpec.from_string('1.1.1')
399
479
        rev = revspec.in_history(wt.branch)
400
480
        self.assertFormatterResult("""\
420
500
revno: 1
421
501
committer: Lorem Ipsum <test@example.com>
422
502
branch nick: test_verbose_log
423
 
timestamp: Tue 2005-11-22 00:00:00 +0000
 
503
timestamp: Wed 2005-11-23 12:08:27 +1000
424
504
message:
425
505
  add a
426
506
added:
431
511
 
432
512
    def test_merges_are_indented_by_level(self):
433
513
        wt = self.make_branch_and_tree('parent')
434
 
        self.wt_commit(wt, 'first post')
435
 
        child_wt = wt.bzrdir.sprout('child').open_workingtree()
436
 
        self.wt_commit(child_wt, 'branch 1')
437
 
        smallerchild_wt = wt.bzrdir.sprout('smallerchild').open_workingtree()
438
 
        self.wt_commit(smallerchild_wt, 'branch 2')
439
 
        child_wt.merge_from_branch(smallerchild_wt.branch)
440
 
        self.wt_commit(child_wt, 'merge branch 2')
441
 
        wt.merge_from_branch(child_wt.branch)
442
 
        self.wt_commit(wt, 'merge branch 1')
 
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')
443
526
        self.assertFormatterResult("""\
444
527
------------------------------------------------------------
445
528
revno: 2 [merge]
446
 
committer: Joe Foo <joe@foo.com>
 
529
committer: Lorem Ipsum <test@example.com>
447
530
branch nick: parent
448
 
timestamp: Tue 2005-11-22 00:00:04 +0000
 
531
timestamp: Just now
449
532
message:
450
533
  merge branch 1
451
534
    ------------------------------------------------------------
452
535
    revno: 1.1.2 [merge]
453
 
    committer: Joe Foo <joe@foo.com>
 
536
    committer: Lorem Ipsum <test@example.com>
454
537
    branch nick: child
455
 
    timestamp: Tue 2005-11-22 00:00:03 +0000
 
538
    timestamp: Just now
456
539
    message:
457
540
      merge branch 2
458
541
        ------------------------------------------------------------
459
542
        revno: 1.2.1
460
 
        committer: Joe Foo <joe@foo.com>
 
543
        committer: Lorem Ipsum <test@example.com>
461
544
        branch nick: smallerchild
462
 
        timestamp: Tue 2005-11-22 00:00:02 +0000
 
545
        timestamp: Just now
463
546
        message:
464
547
          branch 2
465
548
    ------------------------------------------------------------
466
549
    revno: 1.1.1
467
 
    committer: Joe Foo <joe@foo.com>
 
550
    committer: Lorem Ipsum <test@example.com>
468
551
    branch nick: child
469
 
    timestamp: Tue 2005-11-22 00:00:01 +0000
 
552
    timestamp: Just now
470
553
    message:
471
554
      branch 1
472
555
------------------------------------------------------------
473
556
revno: 1
474
 
committer: Joe Foo <joe@foo.com>
 
557
committer: Lorem Ipsum <test@example.com>
475
558
branch nick: parent
476
 
timestamp: Tue 2005-11-22 00:00:00 +0000
 
559
timestamp: Just now
477
560
message:
478
561
  first post
479
562
""",
480
563
            wt.branch, log.LongLogFormatter,
481
564
            formatter_kwargs=dict(levels=0),
482
 
            show_log_kwargs=dict(verbose=True))
 
565
            show_log_kwargs=dict(verbose=True),
 
566
            normalize=True)
483
567
 
484
568
    def test_verbose_merge_revisions_contain_deltas(self):
485
569
        wt = self.make_branch_and_tree('parent')
486
570
        self.build_tree(['parent/f1', 'parent/f2'])
487
571
        wt.add(['f1','f2'])
488
 
        self.wt_commit(wt, 'first post')
489
 
        child_wt = wt.bzrdir.sprout('child').open_workingtree()
 
572
        wt.commit('first post')
 
573
        self.run_bzr('branch parent child')
490
574
        os.unlink('child/f1')
491
 
        self.build_tree_contents([('child/f2', 'hello\n')])
492
 
        self.wt_commit(child_wt, 'removed f1 and modified f2')
493
 
        wt.merge_from_branch(child_wt.branch)
494
 
        self.wt_commit(wt, 'merge branch 1')
 
575
        file('child/f2', 'wb').write('hello\n')
 
576
        self.run_bzr(['commit', '-m', 'removed f1 and modified f2',
 
577
            'child'])
 
578
        os.chdir('parent')
 
579
        self.run_bzr('merge ../child')
 
580
        wt.commit('merge branch 1')
495
581
        self.assertFormatterResult("""\
496
582
------------------------------------------------------------
497
583
revno: 2 [merge]
498
 
committer: Joe Foo <joe@foo.com>
 
584
committer: Lorem Ipsum <test@example.com>
499
585
branch nick: parent
500
 
timestamp: Tue 2005-11-22 00:00:02 +0000
 
586
timestamp: Just now
501
587
message:
502
588
  merge branch 1
503
589
removed:
506
592
  f2
507
593
    ------------------------------------------------------------
508
594
    revno: 1.1.1
509
 
    committer: Joe Foo <joe@foo.com>
 
595
    committer: Lorem Ipsum <test@example.com>
510
596
    branch nick: child
511
 
    timestamp: Tue 2005-11-22 00:00:01 +0000
 
597
    timestamp: Just now
512
598
    message:
513
599
      removed f1 and modified f2
514
600
    removed:
517
603
      f2
518
604
------------------------------------------------------------
519
605
revno: 1
520
 
committer: Joe Foo <joe@foo.com>
 
606
committer: Lorem Ipsum <test@example.com>
521
607
branch nick: parent
522
 
timestamp: Tue 2005-11-22 00:00:00 +0000
 
608
timestamp: Just now
523
609
message:
524
610
  first post
525
611
added:
528
614
""",
529
615
            wt.branch, log.LongLogFormatter,
530
616
            formatter_kwargs=dict(levels=0),
531
 
            show_log_kwargs=dict(verbose=True))
 
617
            show_log_kwargs=dict(verbose=True),
 
618
            normalize=True)
532
619
 
533
620
    def test_trailing_newlines(self):
534
621
        wt = self.make_branch_and_tree('.')
535
 
        b = self.make_commits_with_trailing_newlines(wt)
 
622
        b = make_commits_with_trailing_newlines(wt)
536
623
        self.assertFormatterResult("""\
537
624
------------------------------------------------------------
538
625
revno: 3
539
626
committer: Joe Foo <joe@foo.com>
540
627
branch nick: test
541
 
timestamp: Tue 2005-11-22 00:00:02 +0000
 
628
timestamp: Mon 2005-11-21 09:32:56 -0600
542
629
message:
543
630
  single line with trailing newline
544
631
------------------------------------------------------------
545
632
revno: 2
 
633
author: Joe Bar <joe@bar.com>
546
634
committer: Joe Foo <joe@foo.com>
547
635
branch nick: test
548
 
timestamp: Tue 2005-11-22 00:00:01 +0000
 
636
timestamp: Mon 2005-11-21 09:27:22 -0600
549
637
message:
550
638
  multiline
551
639
  log
554
642
revno: 1
555
643
committer: Joe Foo <joe@foo.com>
556
644
branch nick: test
557
 
timestamp: Tue 2005-11-22 00:00:00 +0000
 
645
timestamp: Mon 2005-11-21 09:24:15 -0600
558
646
message:
559
647
  simple log message
560
648
""",
573
661
author: John Doe <jdoe@example.com>, Jane Rey <jrey@example.com>
574
662
committer: Lorem Ipsum <test@example.com>
575
663
branch nick: test_author_log
576
 
timestamp: Tue 2005-11-22 00:00:00 +0000
 
664
timestamp: Wed 2005-11-23 12:08:27 +1000
577
665
message:
578
666
  add a
579
667
""",
598
686
author: John Doe <jdoe@example.com>
599
687
committer: Lorem Ipsum <test@example.com>
600
688
branch nick: test_properties_in_log
601
 
timestamp: Tue 2005-11-22 00:00:00 +0000
 
689
timestamp: Wed 2005-11-23 12:08:27 +1000
602
690
message:
603
691
  add a
604
692
""",
616
704
            'trivial_custom_prop_handler',
617
705
            trivial_custom_prop_handler)
618
706
        self.assertFormatterResult("""\
619
 
    1 John Doe\t2005-11-22
 
707
    1 John Doe\t2005-11-23
620
708
      test_prop: test_value
621
709
      add a
622
710
 
673
761
revno: 1
674
762
committer: Lorem Ipsum <test@example.com>
675
763
branch nick: test_long_verbose_log
676
 
timestamp: Tue 2005-11-22 00:00:00 +0000
 
764
timestamp: Wed 2005-11-23 12:08:27 +1000
677
765
message:
678
766
  add a
679
767
added:
687
775
        wt = self.make_branch_and_tree('parent')
688
776
        self.build_tree(['parent/f1', 'parent/f2'])
689
777
        wt.add(['f1','f2'])
690
 
        self.wt_commit(wt, 'first post')
 
778
        wt.commit('first post')
691
779
        child_wt = wt.bzrdir.sprout('child').open_workingtree()
692
780
        os.unlink('child/f1')
693
781
        self.build_tree_contents([('child/f2', 'hello\n')])
694
 
        self.wt_commit(child_wt, 'removed f1 and modified f2')
 
782
        child_wt.commit('removed f1 and modified f2')
695
783
        wt.merge_from_branch(child_wt.branch)
696
 
        self.wt_commit(wt, 'merge branch 1')
 
784
        wt.commit('merge branch 1')
697
785
        self.assertFormatterResult("""\
698
786
------------------------------------------------------------
699
787
revno: 2 [merge]
700
 
committer: Joe Foo <joe@foo.com>
 
788
committer: Lorem Ipsum <test@example.com>
701
789
branch nick: parent
702
 
timestamp: Tue 2005-11-22 00:00:02 +0000
 
790
timestamp: Just now
703
791
message:
704
792
  merge branch 1
705
793
removed:
708
796
  f2
709
797
------------------------------------------------------------
710
798
revno: 1
711
 
committer: Joe Foo <joe@foo.com>
 
799
committer: Lorem Ipsum <test@example.com>
712
800
branch nick: parent
713
 
timestamp: Tue 2005-11-22 00:00:00 +0000
 
801
timestamp: Just now
714
802
message:
715
803
  first post
716
804
added:
719
807
""",
720
808
            wt.branch, log.LongLogFormatter,
721
809
            formatter_kwargs=dict(levels=1),
722
 
            show_log_kwargs=dict(verbose=True))
 
810
            show_log_kwargs=dict(verbose=True),
 
811
            normalize=True)
723
812
 
724
813
    def test_long_trailing_newlines(self):
725
814
        wt = self.make_branch_and_tree('.')
726
 
        b = self.make_commits_with_trailing_newlines(wt)
 
815
        b = make_commits_with_trailing_newlines(wt)
727
816
        self.assertFormatterResult("""\
728
817
------------------------------------------------------------
729
818
revno: 3
730
819
committer: Joe Foo <joe@foo.com>
731
820
branch nick: test
732
 
timestamp: Tue 2005-11-22 00:00:02 +0000
 
821
timestamp: Mon 2005-11-21 09:32:56 -0600
733
822
message:
734
823
  single line with trailing newline
735
824
------------------------------------------------------------
736
825
revno: 2
 
826
author: Joe Bar <joe@bar.com>
737
827
committer: Joe Foo <joe@foo.com>
738
828
branch nick: test
739
 
timestamp: Tue 2005-11-22 00:00:01 +0000
 
829
timestamp: Mon 2005-11-21 09:27:22 -0600
740
830
message:
741
831
  multiline
742
832
  log
745
835
revno: 1
746
836
committer: Joe Foo <joe@foo.com>
747
837
branch nick: test
748
 
timestamp: Tue 2005-11-22 00:00:00 +0000
 
838
timestamp: Mon 2005-11-21 09:24:15 -0600
749
839
message:
750
840
  simple log message
751
841
""",
763
853
author: John Doe <jdoe@example.com>
764
854
committer: Lorem Ipsum <test@example.com>
765
855
branch nick: test_author_log
766
 
timestamp: Tue 2005-11-22 00:00:00 +0000
 
856
timestamp: Wed 2005-11-23 12:08:27 +1000
767
857
message:
768
858
  add a
769
859
""",
788
878
author: John Doe <jdoe@example.com>
789
879
committer: Lorem Ipsum <test@example.com>
790
880
branch nick: test_properties_in_log
791
 
timestamp: Tue 2005-11-22 00:00:00 +0000
 
881
timestamp: Wed 2005-11-23 12:08:27 +1000
792
882
message:
793
883
  add a
794
884
""",
807
897
                committer='Line-Log-Formatter Tester <test@line.log>',
808
898
                authors=[])
809
899
        self.assertFormatterResult("""\
810
 
1: Line-Log-Formatte... 2005-11-22 add a
 
900
1: Line-Log-Formatte... 2005-11-23 add a
811
901
""",
812
902
            wt.branch, log.LineLogFormatter)
813
903
 
814
904
    def test_trailing_newlines(self):
815
905
        wt = self.make_branch_and_tree('.')
816
 
        b = self.make_commits_with_trailing_newlines(wt)
 
906
        b = make_commits_with_trailing_newlines(wt)
817
907
        self.assertFormatterResult("""\
818
 
3: Joe Foo 2005-11-22 single line with trailing newline
819
 
2: Joe Foo 2005-11-22 multiline
820
 
1: Joe Foo 2005-11-22 simple log message
 
908
3: Joe Foo 2005-11-21 single line with trailing newline
 
909
2: Joe Bar 2005-11-21 multiline
 
910
1: Joe Foo 2005-11-21 simple log message
821
911
""",
822
912
            b, log.LineLogFormatter)
823
913
 
834
924
    def test_line_log_with_tags(self):
835
925
        wt = self._prepare_tree_with_merges(with_tags=True)
836
926
        self.assertFormatterResult("""\
837
 
3: Joe Foo 2005-11-22 {v1.0, v1.0rc1} rev-3
 
927
3: Jane Foo 2005-11-22 {v1.0, v1.0rc1} rev-3
838
928
2: Joe Foo 2005-11-22 [merge] {v0.2} rev-2
839
929
1: Joe Foo 2005-11-22 rev-1
840
930
""",
852
942
                committer='Line-Log-Formatter Tester <test@line.log>',
853
943
                authors=[])
854
944
        self.assertFormatterResult("""\
855
 
1: Line-Log-Formatte... 2005-11-22 add a
 
945
1: Line-Log-Formatte... 2005-11-23 add a
856
946
""",
857
947
            wt.branch, log.LineLogFormatter)
858
948
 
859
949
    def test_line_merge_revs_log_single_merge_revision(self):
860
 
        wt = self._prepare_tree_with_merges()
 
950
        wt = self.make_branch_and_memory_tree('.')
 
951
        wt.lock_write()
 
952
        self.addCleanup(wt.unlock)
 
953
        wt.add('')
 
954
        wt.commit('rev-1', rev_id='rev-1',
 
955
                  timestamp=1132586655, timezone=36000,
 
956
                  committer='Joe Foo <joe@foo.com>')
 
957
        wt.commit('rev-merged', rev_id='rev-2a',
 
958
                  timestamp=1132586700, timezone=36000,
 
959
                  committer='Joe Foo <joe@foo.com>')
 
960
        wt.set_parent_ids(['rev-1', 'rev-2a'])
 
961
        wt.branch.set_last_revision_info(1, 'rev-1')
 
962
        wt.commit('rev-2', rev_id='rev-2b',
 
963
                  timestamp=1132586800, timezone=36000,
 
964
                  committer='Joe Foo <joe@foo.com>')
861
965
        revspec = revisionspec.RevisionSpec.from_string('1.1.1')
862
966
        rev = revspec.in_history(wt.branch)
863
967
        self.assertFormatterResult("""\
868
972
            show_log_kwargs=dict(start_revision=rev, end_revision=rev))
869
973
 
870
974
    def test_line_merge_revs_log_with_merges(self):
871
 
        wt = self._prepare_tree_with_merges()
 
975
        wt = self.make_branch_and_memory_tree('.')
 
976
        wt.lock_write()
 
977
        self.addCleanup(wt.unlock)
 
978
        wt.add('')
 
979
        wt.commit('rev-1', rev_id='rev-1',
 
980
                  timestamp=1132586655, timezone=36000,
 
981
                  committer='Joe Foo <joe@foo.com>')
 
982
        wt.commit('rev-merged', rev_id='rev-2a',
 
983
                  timestamp=1132586700, timezone=36000,
 
984
                  committer='Joe Foo <joe@foo.com>')
 
985
        wt.set_parent_ids(['rev-1', 'rev-2a'])
 
986
        wt.branch.set_last_revision_info(1, 'rev-1')
 
987
        wt.commit('rev-2', rev_id='rev-2b',
 
988
                  timestamp=1132586800, timezone=36000,
 
989
                  committer='Joe Foo <joe@foo.com>')
872
990
        self.assertFormatterResult("""\
873
991
2: Joe Foo 2005-11-22 [merge] rev-2
874
992
  1.1.1: Joe Foo 2005-11-22 rev-merged
878
996
            formatter_kwargs=dict(levels=0))
879
997
 
880
998
 
881
 
class TestGnuChangelogFormatter(TestCaseForLogFormatter):
882
 
 
883
 
    def test_gnu_changelog(self):
884
 
        wt = self.make_standard_commit('nicky', authors=[])
885
 
        self.assertFormatterResult('''\
886
 
2005-11-22  Lorem Ipsum  <test@example.com>
887
 
 
888
 
\tadd a
889
 
 
890
 
''',
891
 
            wt.branch, log.GnuChangelogLogFormatter)
892
 
 
893
 
    def test_with_authors(self):
894
 
        wt = self.make_standard_commit('nicky',
895
 
            authors=['Fooa Fooz <foo@example.com>',
896
 
                     'Bari Baro <bar@example.com>'])
897
 
        self.assertFormatterResult('''\
898
 
2005-11-22  Fooa Fooz  <foo@example.com>
899
 
 
900
 
\tadd a
901
 
 
902
 
''',
903
 
            wt.branch, log.GnuChangelogLogFormatter)
904
 
 
905
 
    def test_verbose(self):
906
 
        wt = self.make_standard_commit('nicky')
907
 
        self.assertFormatterResult('''\
908
 
2005-11-22  John Doe  <jdoe@example.com>
909
 
 
910
 
\t* a:
911
 
 
912
 
\tadd a
913
 
 
914
 
''',
915
 
            wt.branch, log.GnuChangelogLogFormatter,
916
 
            show_log_kwargs=dict(verbose=True))
917
 
 
918
 
class TestGetViewRevisions(tests.TestCaseWithTransport, TestLogMixin):
919
 
 
920
 
    def _get_view_revisions(self, *args, **kwargs):
921
 
        return self.applyDeprecated(symbol_versioning.deprecated_in((2, 2, 0)),
922
 
                                    log.get_view_revisions, *args, **kwargs)
 
999
class TestGetViewRevisions(tests.TestCaseWithTransport):
923
1000
 
924
1001
    def make_tree_with_commits(self):
925
1002
        """Create a tree with well-known revision ids"""
926
1003
        wt = self.make_branch_and_tree('tree1')
927
 
        self.wt_commit(wt, 'commit one', rev_id='1')
928
 
        self.wt_commit(wt, 'commit two', rev_id='2')
929
 
        self.wt_commit(wt, 'commit three', rev_id='3')
 
1004
        wt.commit('commit one', rev_id='1')
 
1005
        wt.commit('commit two', rev_id='2')
 
1006
        wt.commit('commit three', rev_id='3')
930
1007
        mainline_revs = [None, '1', '2', '3']
931
1008
        rev_nos = {'1': 1, '2': 2, '3': 3}
932
1009
        return mainline_revs, rev_nos, wt
935
1012
        """Create a tree with well-known revision ids and a merge"""
936
1013
        mainline_revs, rev_nos, wt = self.make_tree_with_commits()
937
1014
        tree2 = wt.bzrdir.sprout('tree2').open_workingtree()
938
 
        self.wt_commit(tree2, 'four-a', rev_id='4a')
 
1015
        tree2.commit('four-a', rev_id='4a')
939
1016
        wt.merge_from_branch(tree2.branch)
940
 
        self.wt_commit(wt, 'four-b', rev_id='4b')
 
1017
        wt.commit('four-b', rev_id='4b')
941
1018
        mainline_revs.append('4b')
942
1019
        rev_nos['4b'] = 4
943
1020
        # 4a: 3.1.1
991
1068
        mainline_revs, rev_nos, wt = self.make_tree_with_commits()
992
1069
        wt.lock_read()
993
1070
        self.addCleanup(wt.unlock)
994
 
        revisions = list(self._get_view_revisions(
 
1071
        revisions = list(log.get_view_revisions(
995
1072
                mainline_revs, rev_nos, wt.branch, 'forward'))
996
1073
        self.assertEqual([('1', '1', 0), ('2', '2', 0), ('3', '3', 0)],
997
1074
                         revisions)
998
 
        revisions2 = list(self._get_view_revisions(
 
1075
        revisions2 = list(log.get_view_revisions(
999
1076
                mainline_revs, rev_nos, wt.branch, 'forward',
1000
1077
                include_merges=False))
1001
1078
        self.assertEqual(revisions, revisions2)
1005
1082
        mainline_revs, rev_nos, wt = self.make_tree_with_commits()
1006
1083
        wt.lock_read()
1007
1084
        self.addCleanup(wt.unlock)
1008
 
        revisions = list(self._get_view_revisions(
 
1085
        revisions = list(log.get_view_revisions(
1009
1086
                mainline_revs, rev_nos, wt.branch, 'reverse'))
1010
1087
        self.assertEqual([('3', '3', 0), ('2', '2', 0), ('1', '1', 0), ],
1011
1088
                         revisions)
1012
 
        revisions2 = list(self._get_view_revisions(
 
1089
        revisions2 = list(log.get_view_revisions(
1013
1090
                mainline_revs, rev_nos, wt.branch, 'reverse',
1014
1091
                include_merges=False))
1015
1092
        self.assertEqual(revisions, revisions2)
1019
1096
        mainline_revs, rev_nos, wt = self.make_tree_with_merges()
1020
1097
        wt.lock_read()
1021
1098
        self.addCleanup(wt.unlock)
1022
 
        revisions = list(self._get_view_revisions(
 
1099
        revisions = list(log.get_view_revisions(
1023
1100
                mainline_revs, rev_nos, wt.branch, 'forward'))
1024
1101
        self.assertEqual([('1', '1', 0), ('2', '2', 0), ('3', '3', 0),
1025
1102
                          ('4b', '4', 0), ('4a', '3.1.1', 1)],
1026
1103
                         revisions)
1027
 
        revisions = list(self._get_view_revisions(
 
1104
        revisions = list(log.get_view_revisions(
1028
1105
                mainline_revs, rev_nos, wt.branch, 'forward',
1029
1106
                include_merges=False))
1030
1107
        self.assertEqual([('1', '1', 0), ('2', '2', 0), ('3', '3', 0),
1036
1113
        mainline_revs, rev_nos, wt = self.make_tree_with_merges()
1037
1114
        wt.lock_read()
1038
1115
        self.addCleanup(wt.unlock)
1039
 
        revisions = list(self._get_view_revisions(
 
1116
        revisions = list(log.get_view_revisions(
1040
1117
                mainline_revs, rev_nos, wt.branch, 'reverse'))
1041
1118
        self.assertEqual([('4b', '4', 0), ('4a', '3.1.1', 1),
1042
1119
                          ('3', '3', 0), ('2', '2', 0), ('1', '1', 0)],
1043
1120
                         revisions)
1044
 
        revisions = list(self._get_view_revisions(
 
1121
        revisions = list(log.get_view_revisions(
1045
1122
                mainline_revs, rev_nos, wt.branch, 'reverse',
1046
1123
                include_merges=False))
1047
1124
        self.assertEqual([('4b', '4', 0), ('3', '3', 0), ('2', '2', 0),
1053
1130
        mainline_revs, rev_nos, b = self.make_branch_with_many_merges()
1054
1131
        b.lock_read()
1055
1132
        self.addCleanup(b.unlock)
1056
 
        revisions = list(self._get_view_revisions(
 
1133
        revisions = list(log.get_view_revisions(
1057
1134
                mainline_revs, rev_nos, b, 'forward'))
1058
1135
        expected = [('1', '1', 0), ('2', '2', 0), ('3c', '3', 0),
1059
1136
                    ('3b', '2.2.1', 1), ('3a', '2.1.1', 2), ('4b', '4', 0),
1060
1137
                    ('4a', '2.2.2', 1)]
1061
1138
        self.assertEqual(expected, revisions)
1062
 
        revisions = list(self._get_view_revisions(
 
1139
        revisions = list(log.get_view_revisions(
1063
1140
                mainline_revs, rev_nos, b, 'forward',
1064
1141
                include_merges=False))
1065
1142
        self.assertEqual([('1', '1', 0), ('2', '2', 0), ('3c', '3', 0),
1066
1143
                          ('4b', '4', 0)],
1067
1144
                         revisions)
1068
1145
 
 
1146
 
1069
1147
    def test_file_id_for_range(self):
1070
1148
        mainline_revs, rev_nos, b = self.make_branch_with_many_merges()
1071
1149
        b.lock_read()
1076
1154
            return revspec.in_history(branch)
1077
1155
 
1078
1156
        def view_revs(start_rev, end_rev, file_id, direction):
1079
 
            revs = self.applyDeprecated(
1080
 
                symbol_versioning.deprecated_in((2, 2, 0)),
1081
 
                log.calculate_view_revisions,
 
1157
            revs = log.calculate_view_revisions(
1082
1158
                b,
1083
1159
                start_rev, # start_revision
1084
1160
                end_rev, # end_revision
1090
1166
 
1091
1167
        rev_3a = rev_from_rev_id('3a', b)
1092
1168
        rev_4b = rev_from_rev_id('4b', b)
1093
 
        self.assertEqual([('3c', '3', 0), ('3b', '2.2.1', 1),
1094
 
                          ('3a', '2.1.1', 2)],
 
1169
        self.assertEqual([('3c', '3', 0), ('3b', '2.2.1', 1), ('3a', '2.1.1', 2)],
1095
1170
                          view_revs(rev_3a, rev_4b, 'f-id', 'reverse'))
1096
1171
        # Note: 3c still appears before 3a here because of depth-based sorting
1097
 
        self.assertEqual([('3c', '3', 0), ('3b', '2.2.1', 1),
1098
 
                          ('3a', '2.1.1', 2)],
 
1172
        self.assertEqual([('3c', '3', 0), ('3b', '2.2.1', 1), ('3a', '2.1.1', 2)],
1099
1173
                          view_revs(rev_3a, rev_4b, 'f-id', 'forward'))
1100
1174
 
1101
1175
 
1102
1176
class TestGetRevisionsTouchingFileID(tests.TestCaseWithTransport):
1103
1177
 
1104
 
    def get_view_revisions(self, *args):
1105
 
        return self.applyDeprecated(symbol_versioning.deprecated_in((2, 2, 0)),
1106
 
                                    log.get_view_revisions, *args)
1107
 
 
1108
1178
    def create_tree_with_single_merge(self):
1109
1179
        """Create a branch with a moderate layout.
1110
1180
 
1128
1198
        #       use it. Since 'log' only uses the tree in a readonly
1129
1199
        #       fashion, it seems a shame to regenerate an identical
1130
1200
        #       tree for each test.
1131
 
        # TODO: vila 20100122 One way to address the shame above will be to
1132
 
        #       create a memory tree during test parametrization and give a
1133
 
        #       *copy* of this tree to each test. Copying a memory tree ought
1134
 
        #       to be cheap, at least cheaper than creating them with such
1135
 
        #       complex setups.
1136
1201
        tree = self.make_branch_and_tree('tree')
1137
1202
        tree.lock_write()
1138
1203
        self.addCleanup(tree.unlock)
1213
1278
        mainline = tree.branch.revision_history()
1214
1279
        mainline.insert(0, None)
1215
1280
        revnos = dict((rev, idx+1) for idx, rev in enumerate(mainline))
1216
 
        view_revs_iter = self.get_view_revisions(
1217
 
            mainline, revnos, tree.branch, 'reverse', True)
 
1281
        view_revs_iter = log.get_view_revisions(mainline, revnos, tree.branch,
 
1282
                                                'reverse', True)
1218
1283
        actual_revs = log._filter_revisions_touching_file_id(
1219
 
            tree.branch, file_id, list(view_revs_iter))
 
1284
                            tree.branch,
 
1285
                            file_id,
 
1286
                            list(view_revs_iter))
1220
1287
        self.assertEqual(revisions, [r for r, revno, depth in actual_revs])
1221
1288
 
1222
1289
    def test_file_id_f1(self):
1274
1341
 
1275
1342
class TestLogFormatter(tests.TestCase):
1276
1343
 
1277
 
    def setUp(self):
1278
 
        super(TestLogFormatter, self).setUp()
1279
 
        self.rev = revision.Revision('a-id')
1280
 
        self.lf = log.LogFormatter(None)
1281
 
 
1282
1344
    def test_short_committer(self):
1283
 
        def assertCommitter(expected, committer):
1284
 
            self.rev.committer = committer
1285
 
            self.assertEqual(expected, self.lf.short_committer(self.rev))
1286
 
 
1287
 
        assertCommitter('John Doe', 'John Doe <jdoe@example.com>')
1288
 
        assertCommitter('John Smith', 'John Smith <jsmith@example.com>')
1289
 
        assertCommitter('John Smith', 'John Smith')
1290
 
        assertCommitter('jsmith@example.com', 'jsmith@example.com')
1291
 
        assertCommitter('jsmith@example.com', '<jsmith@example.com>')
1292
 
        assertCommitter('John Smith', 'John Smith jsmith@example.com')
 
1345
        rev = revision.Revision('a-id')
 
1346
        rev.committer = 'John Doe <jdoe@example.com>'
 
1347
        lf = log.LogFormatter(None)
 
1348
        self.assertEqual('John Doe', lf.short_committer(rev))
 
1349
        rev.committer = 'John Smith <jsmith@example.com>'
 
1350
        self.assertEqual('John Smith', lf.short_committer(rev))
 
1351
        rev.committer = 'John Smith'
 
1352
        self.assertEqual('John Smith', lf.short_committer(rev))
 
1353
        rev.committer = 'jsmith@example.com'
 
1354
        self.assertEqual('jsmith@example.com', lf.short_committer(rev))
 
1355
        rev.committer = '<jsmith@example.com>'
 
1356
        self.assertEqual('jsmith@example.com', lf.short_committer(rev))
 
1357
        rev.committer = 'John Smith jsmith@example.com'
 
1358
        self.assertEqual('John Smith', lf.short_committer(rev))
1293
1359
 
1294
1360
    def test_short_author(self):
1295
 
        def assertAuthor(expected, author):
1296
 
            self.rev.properties['author'] = author
1297
 
            self.assertEqual(expected, self.lf.short_author(self.rev))
1298
 
 
1299
 
        assertAuthor('John Smith', 'John Smith <jsmith@example.com>')
1300
 
        assertAuthor('John Smith', 'John Smith')
1301
 
        assertAuthor('jsmith@example.com', 'jsmith@example.com')
1302
 
        assertAuthor('jsmith@example.com', '<jsmith@example.com>')
1303
 
        assertAuthor('John Smith', 'John Smith jsmith@example.com')
1304
 
 
1305
 
    def test_short_author_from_committer(self):
1306
 
        self.rev.committer = 'John Doe <jdoe@example.com>'
1307
 
        self.assertEqual('John Doe', self.lf.short_author(self.rev))
1308
 
 
1309
 
    def test_short_author_from_authors(self):
1310
 
        self.rev.properties['authors'] = ('John Smith <jsmith@example.com>\n'
1311
 
                                          'Jane Rey <jrey@example.com>')
1312
 
        self.assertEqual('John Smith', self.lf.short_author(self.rev))
 
1361
        rev = revision.Revision('a-id')
 
1362
        rev.committer = 'John Doe <jdoe@example.com>'
 
1363
        lf = log.LogFormatter(None)
 
1364
        self.assertEqual('John Doe', lf.short_author(rev))
 
1365
        rev.properties['author'] = 'John Smith <jsmith@example.com>'
 
1366
        self.assertEqual('John Smith', lf.short_author(rev))
 
1367
        rev.properties['author'] = 'John Smith'
 
1368
        self.assertEqual('John Smith', lf.short_author(rev))
 
1369
        rev.properties['author'] = 'jsmith@example.com'
 
1370
        self.assertEqual('jsmith@example.com', lf.short_author(rev))
 
1371
        rev.properties['author'] = '<jsmith@example.com>'
 
1372
        self.assertEqual('jsmith@example.com', lf.short_author(rev))
 
1373
        rev.properties['author'] = 'John Smith jsmith@example.com'
 
1374
        self.assertEqual('John Smith', lf.short_author(rev))
 
1375
        del rev.properties['author']
 
1376
        rev.properties['authors'] = ('John Smith <jsmith@example.com>\n'
 
1377
                'Jane Rey <jrey@example.com>')
 
1378
        self.assertEqual('John Smith', lf.short_author(rev))
1313
1379
 
1314
1380
 
1315
1381
class TestReverseByDepth(tests.TestCase):
1464
1530
 
1465
1531
 
1466
1532
 
1467
 
class TestLogWithBugs(TestCaseForLogFormatter, TestLogMixin):
 
1533
class TestLogWithBugs(TestCaseForLogFormatter):
1468
1534
 
1469
1535
    def setUp(self):
1470
1536
        TestCaseForLogFormatter.setUp(self)
1477
1543
        tree = self.make_branch_and_tree(u'.')
1478
1544
        self.build_tree(['a', 'b'])
1479
1545
        tree.add('a')
1480
 
        self.wt_commit(tree, 'simple log message', rev_id='a1',
1481
 
                       revprops={'bugs': 'test://bug/id fixed'})
 
1546
        tree.commit('simple log message', rev_id='a1',
 
1547
                    timestamp=1132586655.459960938, timezone=-6*3600,
 
1548
                    committer='Joe Foo <joe@foo.com>',
 
1549
                    revprops={'bugs': 'test://bug/id fixed'})
1482
1550
        tree.add('b')
1483
 
        self.wt_commit(tree, 'multiline\nlog\nmessage\n', rev_id='a2',
1484
 
                       authors=['Joe Bar <joe@bar.com>'],
1485
 
                       revprops={'bugs': 'test://bug/id fixed\n'
1486
 
                                 'test://bug/2 fixed'})
 
1551
        tree.commit('multiline\nlog\nmessage\n', rev_id='a2',
 
1552
                    timestamp=1132586842.411175966, timezone=-6*3600,
 
1553
                    committer='Joe Foo <joe@foo.com>',
 
1554
                    authors=['Joe Bar <joe@bar.com>'],
 
1555
                    revprops={'bugs': 'test://bug/id fixed\n'
 
1556
                                      'test://bug/2 fixed'})
1487
1557
        return tree
1488
1558
 
1489
1559
 
1496
1566
author: Joe Bar <joe@bar.com>
1497
1567
committer: Joe Foo <joe@foo.com>
1498
1568
branch nick: work
1499
 
timestamp: Tue 2005-11-22 00:00:01 +0000
 
1569
timestamp: Mon 2005-11-21 09:27:22 -0600
1500
1570
message:
1501
1571
  multiline
1502
1572
  log
1506
1576
fixes bug(s): test://bug/id
1507
1577
committer: Joe Foo <joe@foo.com>
1508
1578
branch nick: work
1509
 
timestamp: Tue 2005-11-22 00:00:00 +0000
 
1579
timestamp: Mon 2005-11-21 09:24:15 -0600
1510
1580
message:
1511
1581
  simple log message
1512
1582
""",
1515
1585
    def test_short_bugs(self):
1516
1586
        tree = self.make_commits_with_bugs()
1517
1587
        self.assertFormatterResult("""\
1518
 
    2 Joe Bar\t2005-11-22
 
1588
    2 Joe Bar\t2005-11-21
1519
1589
      fixes bug(s): test://bug/id test://bug/2
1520
1590
      multiline
1521
1591
      log
1522
1592
      message
1523
1593
 
1524
 
    1 Joe Foo\t2005-11-22
 
1594
    1 Joe Foo\t2005-11-21
1525
1595
      fixes bug(s): test://bug/id
1526
1596
      simple log message
1527
1597
 
1531
1601
    def test_wrong_bugs_property(self):
1532
1602
        tree = self.make_branch_and_tree(u'.')
1533
1603
        self.build_tree(['foo'])
1534
 
        self.wt_commit(tree, 'simple log message', rev_id='a1',
1535
 
                       revprops={'bugs': 'test://bug/id invalid_value'})
 
1604
        tree.commit('simple log message', rev_id='a1',
 
1605
              timestamp=1132586655.459960938, timezone=-6*3600,
 
1606
              committer='Joe Foo <joe@foo.com>',
 
1607
              revprops={'bugs': 'test://bug/id invalid_value'})
1536
1608
        self.assertFormatterResult("""\
1537
 
    1 Joe Foo\t2005-11-22
 
1609
    1 Joe Foo\t2005-11-21
1538
1610
      simple log message
1539
1611
 
1540
1612
""",
1542
1614
 
1543
1615
    def test_bugs_handler_present(self):
1544
1616
        self.properties_handler_registry.get('bugs_properties_handler')
1545
 
 
1546
 
 
1547
 
class TestLogForAuthors(TestCaseForLogFormatter):
1548
 
 
1549
 
    def setUp(self):
1550
 
        TestCaseForLogFormatter.setUp(self)
1551
 
        self.wt = self.make_standard_commit('nicky',
1552
 
            authors=['John Doe <jdoe@example.com>',
1553
 
                     'Jane Rey <jrey@example.com>'])
1554
 
 
1555
 
    def assertFormatterResult(self, formatter, who, result):
1556
 
        formatter_kwargs = dict()
1557
 
        if who is not None:
1558
 
            author_list_handler = log.author_list_registry.get(who)
1559
 
            formatter_kwargs['author_list_handler'] = author_list_handler
1560
 
        TestCaseForLogFormatter.assertFormatterResult(self, result,
1561
 
            self.wt.branch, formatter, formatter_kwargs=formatter_kwargs)
1562
 
 
1563
 
    def test_line_default(self):
1564
 
        self.assertFormatterResult(log.LineLogFormatter, None, """\
1565
 
1: John Doe 2005-11-22 add a
1566
 
""")
1567
 
 
1568
 
    def test_line_committer(self):
1569
 
        self.assertFormatterResult(log.LineLogFormatter, 'committer', """\
1570
 
1: Lorem Ipsum 2005-11-22 add a
1571
 
""")
1572
 
 
1573
 
    def test_line_first(self):
1574
 
        self.assertFormatterResult(log.LineLogFormatter, 'first', """\
1575
 
1: John Doe 2005-11-22 add a
1576
 
""")
1577
 
 
1578
 
    def test_line_all(self):
1579
 
        self.assertFormatterResult(log.LineLogFormatter, 'all', """\
1580
 
1: John Doe, Jane Rey 2005-11-22 add a
1581
 
""")
1582
 
 
1583
 
 
1584
 
    def test_short_default(self):
1585
 
        self.assertFormatterResult(log.ShortLogFormatter, None, """\
1586
 
    1 John Doe\t2005-11-22
1587
 
      add a
1588
 
 
1589
 
""")
1590
 
 
1591
 
    def test_short_committer(self):
1592
 
        self.assertFormatterResult(log.ShortLogFormatter, 'committer', """\
1593
 
    1 Lorem Ipsum\t2005-11-22
1594
 
      add a
1595
 
 
1596
 
""")
1597
 
 
1598
 
    def test_short_first(self):
1599
 
        self.assertFormatterResult(log.ShortLogFormatter, 'first', """\
1600
 
    1 John Doe\t2005-11-22
1601
 
      add a
1602
 
 
1603
 
""")
1604
 
 
1605
 
    def test_short_all(self):
1606
 
        self.assertFormatterResult(log.ShortLogFormatter, 'all', """\
1607
 
    1 John Doe, Jane Rey\t2005-11-22
1608
 
      add a
1609
 
 
1610
 
""")
1611
 
 
1612
 
    def test_long_default(self):
1613
 
        self.assertFormatterResult(log.LongLogFormatter, None, """\
1614
 
------------------------------------------------------------
1615
 
revno: 1
1616
 
author: John Doe <jdoe@example.com>, Jane Rey <jrey@example.com>
1617
 
committer: Lorem Ipsum <test@example.com>
1618
 
branch nick: nicky
1619
 
timestamp: Tue 2005-11-22 00:00:00 +0000
1620
 
message:
1621
 
  add a
1622
 
""")
1623
 
 
1624
 
    def test_long_committer(self):
1625
 
        self.assertFormatterResult(log.LongLogFormatter, 'committer', """\
1626
 
------------------------------------------------------------
1627
 
revno: 1
1628
 
committer: Lorem Ipsum <test@example.com>
1629
 
branch nick: nicky
1630
 
timestamp: Tue 2005-11-22 00:00:00 +0000
1631
 
message:
1632
 
  add a
1633
 
""")
1634
 
 
1635
 
    def test_long_first(self):
1636
 
        self.assertFormatterResult(log.LongLogFormatter, 'first', """\
1637
 
------------------------------------------------------------
1638
 
revno: 1
1639
 
author: John Doe <jdoe@example.com>
1640
 
committer: Lorem Ipsum <test@example.com>
1641
 
branch nick: nicky
1642
 
timestamp: Tue 2005-11-22 00:00:00 +0000
1643
 
message:
1644
 
  add a
1645
 
""")
1646
 
 
1647
 
    def test_long_all(self):
1648
 
        self.assertFormatterResult(log.LongLogFormatter, 'all', """\
1649
 
------------------------------------------------------------
1650
 
revno: 1
1651
 
author: John Doe <jdoe@example.com>, Jane Rey <jrey@example.com>
1652
 
committer: Lorem Ipsum <test@example.com>
1653
 
branch nick: nicky
1654
 
timestamp: Tue 2005-11-22 00:00:00 +0000
1655
 
message:
1656
 
  add a
1657
 
""")
1658
 
 
1659
 
    def test_gnu_changelog_default(self):
1660
 
        self.assertFormatterResult(log.GnuChangelogLogFormatter, None, """\
1661
 
2005-11-22  John Doe  <jdoe@example.com>
1662
 
 
1663
 
\tadd a
1664
 
 
1665
 
""")
1666
 
 
1667
 
    def test_gnu_changelog_committer(self):
1668
 
        self.assertFormatterResult(log.GnuChangelogLogFormatter, 'committer', """\
1669
 
2005-11-22  Lorem Ipsum  <test@example.com>
1670
 
 
1671
 
\tadd a
1672
 
 
1673
 
""")
1674
 
 
1675
 
    def test_gnu_changelog_first(self):
1676
 
        self.assertFormatterResult(log.GnuChangelogLogFormatter, 'first', """\
1677
 
2005-11-22  John Doe  <jdoe@example.com>
1678
 
 
1679
 
\tadd a
1680
 
 
1681
 
""")
1682
 
 
1683
 
    def test_gnu_changelog_all(self):
1684
 
        self.assertFormatterResult(log.GnuChangelogLogFormatter, 'all', """\
1685
 
2005-11-22  John Doe  <jdoe@example.com>, Jane Rey  <jrey@example.com>
1686
 
 
1687
 
\tadd a
1688
 
 
1689
 
""")
1690
 
 
1691
 
class TestLogExcludeAncestry(tests.TestCaseWithTransport):
1692
 
 
1693
 
    def make_branch_with_alternate_ancestries(self, relpath='.'):
1694
 
        # See test_merge_sorted_exclude_ancestry below for the difference with
1695
 
        # bt.per_branch.test_iter_merge_sorted_revision.
1696
 
        # TestIterMergeSortedRevisionsBushyGraph. 
1697
 
        # make_branch_with_alternate_ancestries
1698
 
        # and test_merge_sorted_exclude_ancestry
1699
 
        # See the FIXME in assertLogRevnos too.
1700
 
        builder = branchbuilder.BranchBuilder(self.get_transport(relpath))
1701
 
        # 1
1702
 
        # |\
1703
 
        # 2 \
1704
 
        # |  |
1705
 
        # |  1.1.1
1706
 
        # |  | \
1707
 
        # |  |  1.2.1
1708
 
        # |  | /
1709
 
        # |  1.1.2
1710
 
        # | /
1711
 
        # 3
1712
 
        builder.start_series()
1713
 
        builder.build_snapshot('1', None, [
1714
 
            ('add', ('', 'TREE_ROOT', 'directory', '')),])
1715
 
        builder.build_snapshot('1.1.1', ['1'], [])
1716
 
        builder.build_snapshot('2', ['1'], [])
1717
 
        builder.build_snapshot('1.2.1', ['1.1.1'], [])
1718
 
        builder.build_snapshot('1.1.2', ['1.1.1', '1.2.1'], [])
1719
 
        builder.build_snapshot('3', ['2', '1.1.2'], [])
1720
 
        builder.finish_series()
1721
 
        br = builder.get_branch()
1722
 
        br.lock_read()
1723
 
        self.addCleanup(br.unlock)
1724
 
        return br
1725
 
 
1726
 
    def assertLogRevnos(self, expected_revnos, b, start, end,
1727
 
                        exclude_common_ancestry, generate_merge_revisions=True):
1728
 
        # FIXME: the layering in log makes it hard to test intermediate levels,
1729
 
        # I wish adding filters with their parameters were easier...
1730
 
        # -- vila 20100413
1731
 
        iter_revs = log._calc_view_revisions(
1732
 
            b, start, end, direction='reverse',
1733
 
            generate_merge_revisions=generate_merge_revisions,
1734
 
            exclude_common_ancestry=exclude_common_ancestry)
1735
 
        self.assertEqual(expected_revnos,
1736
 
                         [revid for revid, revno, depth in iter_revs])
1737
 
 
1738
 
    def test_merge_sorted_exclude_ancestry(self):
1739
 
        b = self.make_branch_with_alternate_ancestries()
1740
 
        self.assertLogRevnos(['3', '1.1.2', '1.2.1', '1.1.1', '2', '1'],
1741
 
                             b, '1', '3', exclude_common_ancestry=False)
1742
 
        # '2' is part of the '3' ancestry but not part of '1.1.1' ancestry so
1743
 
        # it should be mentioned even if merge_sort order will make it appear
1744
 
        # after 1.1.1
1745
 
        self.assertLogRevnos(['3', '1.1.2', '1.2.1', '2'],
1746
 
                             b, '1.1.1', '3', exclude_common_ancestry=True)
1747
 
 
1748
 
    def test_merge_sorted_simple_revnos_exclude_ancestry(self):
1749
 
        b = self.make_branch_with_alternate_ancestries()
1750
 
        self.assertLogRevnos(['3', '2'],
1751
 
                             b, '1', '3', exclude_common_ancestry=True,
1752
 
                             generate_merge_revisions=False)
1753
 
        self.assertLogRevnos(['3', '1.1.2', '1.2.1', '1.1.1', '2'],
1754
 
                             b, '1', '3', exclude_common_ancestry=True,
1755
 
                             generate_merge_revisions=True)
1756