~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/log.py

  • Committer: Robert Collins
  • Date: 2010-04-08 04:34:03 UTC
  • mfrom: (5138 +trunk)
  • mto: This revision was merged to the branch mainline in revision 5139.
  • Revision ID: robertc@robertcollins.net-20100408043403-56z0d07vdqrx7f3t
Update bugfix for 528114 to trunk.

Show diffs side-by-side

added added

removed removed

Lines of Context:
88
88
    re_compile_checked,
89
89
    terminal_width,
90
90
    )
 
91
from bzrlib.symbol_versioning import (
 
92
    deprecated_function,
 
93
    deprecated_in,
 
94
    )
91
95
 
92
96
 
93
97
def find_touching_revisions(branch, file_id):
105
109
    last_path = None
106
110
    revno = 1
107
111
    for revision_id in branch.revision_history():
108
 
        this_inv = branch.repository.get_revision_inventory(revision_id)
 
112
        this_inv = branch.repository.get_inventory(revision_id)
109
113
        if file_id in this_inv:
110
114
            this_ie = this_inv[file_id]
111
115
            this_path = this_inv.id2path(file_id)
304
308
 
305
309
 
306
310
class Logger(object):
307
 
    """An object the generates, formats and displays a log."""
 
311
    """An object that generates, formats and displays a log."""
308
312
 
309
313
    def __init__(self, branch, rqst):
310
314
        """Create a Logger.
530
534
 
531
535
 
532
536
def _generate_all_revisions(branch, start_rev_id, end_rev_id, direction,
533
 
    delayed_graph_generation):
 
537
                            delayed_graph_generation):
534
538
    # On large trees, generating the merge graph can take 30-60 seconds
535
539
    # so we delay doing it until a merge is detected, incrementally
536
540
    # returning initial (non-merge) revisions while we can.
 
541
 
 
542
    # The above is only true for old formats (<= 0.92), for newer formats, a
 
543
    # couple of seconds only should be needed to load the whole graph and the
 
544
    # other graph operations needed are even faster than that -- vila 100201
537
545
    initial_revisions = []
538
546
    if delayed_graph_generation:
539
547
        try:
540
 
            for rev_id, revno, depth in \
541
 
                _linear_view_revisions(branch, start_rev_id, end_rev_id):
 
548
            for rev_id, revno, depth in  _linear_view_revisions(
 
549
                branch, start_rev_id, end_rev_id):
542
550
                if _has_merges(branch, rev_id):
 
551
                    # The end_rev_id can be nested down somewhere. We need an
 
552
                    # explicit ancestry check. There is an ambiguity here as we
 
553
                    # may not raise _StartNotLinearAncestor for a revision that
 
554
                    # is an ancestor but not a *linear* one. But since we have
 
555
                    # loaded the graph to do the check (or calculate a dotted
 
556
                    # revno), we may as well accept to show the log...  We need
 
557
                    # the check only if start_rev_id is not None as all
 
558
                    # revisions have _mod_revision.NULL_REVISION as an ancestor
 
559
                    # -- vila 20100319
 
560
                    graph = branch.repository.get_graph()
 
561
                    if (start_rev_id is not None
 
562
                        and not graph.is_ancestor(start_rev_id, end_rev_id)):
 
563
                        raise _StartNotLinearAncestor()
 
564
                    # Since we collected the revisions so far, we need to
 
565
                    # adjust end_rev_id.
543
566
                    end_rev_id = rev_id
544
567
                    break
545
568
                else:
558
581
            raise errors.BzrCommandError('Start revision not found in'
559
582
                ' history of end revision.')
560
583
 
 
584
    # We exit the loop above because we encounter a revision with merges, from
 
585
    # this revision, we need to switch to _graph_view_revisions.
 
586
 
561
587
    # A log including nested merges is required. If the direction is reverse,
562
588
    # we rebase the initial merge depths so that the development line is
563
589
    # shown naturally, i.e. just like it is for linear logging. We can easily
565
591
    # indented at the end seems slightly nicer in that case.
566
592
    view_revisions = chain(iter(initial_revisions),
567
593
        _graph_view_revisions(branch, start_rev_id, end_rev_id,
568
 
        rebase_initial_depths=direction == 'reverse'))
 
594
                              rebase_initial_depths=(direction == 'reverse')))
569
595
    if direction == 'reverse':
570
596
        return view_revisions
571
597
    elif direction == 'forward':
597
623
        else:
598
624
            # not obvious
599
625
            return False
 
626
    # if either start or end is not specified then we use either the first or
 
627
    # the last revision and *they* are obvious ancestors.
600
628
    return True
601
629
 
602
630
 
635
663
 
636
664
 
637
665
def _graph_view_revisions(branch, start_rev_id, end_rev_id,
638
 
    rebase_initial_depths=True):
 
666
                          rebase_initial_depths=True):
639
667
    """Calculate revisions to view including merges, newest to oldest.
640
668
 
641
669
    :param branch: the branch
664
692
                depth_adjustment = merge_depth
665
693
            if depth_adjustment:
666
694
                if merge_depth < depth_adjustment:
 
695
                    # From now on we reduce the depth adjustement, this can be
 
696
                    # surprising for users. The alternative requires two passes
 
697
                    # which breaks the fast display of the first revision
 
698
                    # though.
667
699
                    depth_adjustment = merge_depth
668
700
                merge_depth -= depth_adjustment
669
701
            yield rev_id, '.'.join(map(str, revno)), merge_depth
670
702
 
671
703
 
 
704
@deprecated_function(deprecated_in((2, 2, 0)))
672
705
def calculate_view_revisions(branch, start_revision, end_revision, direction,
673
706
        specific_fileid, generate_merge_revisions):
674
707
    """Calculate the revisions to view.
676
709
    :return: An iterator of (revision_id, dotted_revno, merge_depth) tuples OR
677
710
             a list of the same tuples.
678
711
    """
679
 
    # This method is no longer called by the main code path.
680
 
    # It is retained for API compatibility and may be deprecated
681
 
    # soon. IGC 20090116
682
712
    start_rev_id, end_rev_id = _get_revision_limits(branch, start_revision,
683
713
        end_revision)
684
714
    view_revisions = list(_calc_view_revisions(branch, start_rev_id, end_rev_id,
1034
1064
    return mainline_revs, rev_nos, start_rev_id, end_rev_id
1035
1065
 
1036
1066
 
 
1067
@deprecated_function(deprecated_in((2, 2, 0)))
1037
1068
def _filter_revision_range(view_revisions, start_rev_id, end_rev_id):
1038
1069
    """Filter view_revisions based on revision ranges.
1039
1070
 
1048
1079
 
1049
1080
    :return: The filtered view_revisions.
1050
1081
    """
1051
 
    # This method is no longer called by the main code path.
1052
 
    # It may be removed soon. IGC 20090127
1053
1082
    if start_rev_id or end_rev_id:
1054
1083
        revision_ids = [r for r, n, d in view_revisions]
1055
1084
        if start_rev_id:
1161
1190
    return result
1162
1191
 
1163
1192
 
 
1193
@deprecated_function(deprecated_in((2, 2, 0)))
1164
1194
def get_view_revisions(mainline_revs, rev_nos, branch, direction,
1165
1195
                       include_merges=True):
1166
1196
    """Produce an iterator of revisions to show
1167
1197
    :return: an iterator of (revision_id, revno, merge_depth)
1168
1198
    (if there is no revno for a revision, None is supplied)
1169
1199
    """
1170
 
    # This method is no longer called by the main code path.
1171
 
    # It is retained for API compatibility and may be deprecated
1172
 
    # soon. IGC 20090127
1173
1200
    if not include_merges:
1174
1201
        revision_ids = mainline_revs[1:]
1175
1202
        if direction == 'reverse':
1293
1320
    preferred_levels = 0
1294
1321
 
1295
1322
    def __init__(self, to_file, show_ids=False, show_timezone='original',
1296
 
            delta_format=None, levels=None, show_advice=False,
1297
 
            to_exact_file=None):
 
1323
                 delta_format=None, levels=None, show_advice=False,
 
1324
                 to_exact_file=None):
1298
1325
        """Create a LogFormatter.
1299
1326
 
1300
1327
        :param to_file: the file to output to
1405
1432
        """
1406
1433
        # Revision comes directly from a foreign repository
1407
1434
        if isinstance(rev, foreign.ForeignRevision):
1408
 
            return self._format_properties(rev.mapping.vcs.show_foreign_revid(rev.foreign_revid))
 
1435
            return self._format_properties(
 
1436
                rev.mapping.vcs.show_foreign_revid(rev.foreign_revid))
1409
1437
 
1410
1438
        # Imported foreign revision revision ids always contain :
1411
1439
        if not ":" in rev.revision_id:
1498
1526
        to_file = self.to_file
1499
1527
        to_file.write("%s%s\n" % (indent, ('\n' + indent).join(lines)))
1500
1528
        if revision.delta is not None:
1501
 
            # We don't respect delta_format for compatibility
1502
 
            revision.delta.show(to_file, self.show_ids, indent=indent,
1503
 
                                short_status=False)
 
1529
            # Use the standard status output to display changes
 
1530
            from bzrlib.delta import report_delta
 
1531
            report_delta(to_file, revision.delta, short_status=False, 
 
1532
                         show_ids=self.show_ids, indent=indent)
1504
1533
        if revision.diff is not None:
1505
1534
            to_file.write(indent + 'diff:\n')
1506
1535
            to_file.flush()
1569
1598
                to_file.write(indent + offset + '%s\n' % (l,))
1570
1599
 
1571
1600
        if revision.delta is not None:
1572
 
            revision.delta.show(to_file, self.show_ids, indent=indent + offset,
1573
 
                                short_status=self.delta_format==1)
 
1601
            # Use the standard status output to display changes
 
1602
            from bzrlib.delta import report_delta
 
1603
            report_delta(to_file, revision.delta, 
 
1604
                         short_status=self.delta_format==1, 
 
1605
                         show_ids=self.show_ids, indent=indent + offset)
1574
1606
        if revision.diff is not None:
1575
1607
            self.show_diff(self.to_exact_file, revision.diff, '      ')
1576
1608
        to_file.write('\n')
1651
1683
                               self.show_timezone,
1652
1684
                               date_fmt='%Y-%m-%d',
1653
1685
                               show_offset=False)
1654
 
        committer_str = revision.rev.committer.replace (' <', '  <')
 
1686
        committer_str = revision.rev.get_apparent_authors()[0].replace (' <', '  <')
1655
1687
        to_file.write('%s  %s\n\n' % (date_str,committer_str))
1656
1688
 
1657
1689
        if revision.delta is not None and revision.delta.has_changed():
1987
2019
        bug_rows = [line.split(' ', 1) for line in bug_lines]
1988
2020
        fixed_bug_urls = [row[0] for row in bug_rows if
1989
2021
                          len(row) > 1 and row[1] == 'fixed']
1990
 
        
 
2022
 
1991
2023
        if fixed_bug_urls:
1992
2024
            return {'fixes bug(s)': ' '.join(fixed_bug_urls)}
1993
2025
    return {}