~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/log.py

  • Committer: Jonathan Riddell
  • Date: 2011-09-14 16:31:57 UTC
  • mto: This revision was merged to the branch mainline in revision 6139.
  • Revision ID: jriddell@canonical.com-20110914163157-ee87lu1pqmq5b4r3
default _translations back to None so we can tell if it gets installed

Show diffs side-by-side

added added

removed removed

Lines of Context:
14
14
# along with this program; if not, write to the Free Software
15
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
16
 
 
17
 
 
18
 
17
19
"""Code to show logs of changes.
18
20
 
19
21
Various flavors of log can be produced:
47
49
all the changes since the previous revision that touched hello.c.
48
50
"""
49
51
 
50
 
from __future__ import absolute_import
51
 
 
52
52
import codecs
53
53
from cStringIO import StringIO
54
54
from itertools import (
65
65
lazy_import(globals(), """
66
66
 
67
67
from bzrlib import (
 
68
    bzrdir,
68
69
    config,
69
 
    controldir,
70
70
    diff,
71
71
    errors,
72
72
    foreign,
74
74
    revision as _mod_revision,
75
75
    revisionspec,
76
76
    tsort,
 
77
    i18n,
77
78
    )
78
 
from bzrlib.i18n import gettext, ngettext
79
79
""")
80
80
 
81
81
from bzrlib import (
105
105
    last_ie = None
106
106
    last_path = None
107
107
    revno = 1
108
 
    graph = branch.repository.get_graph()
109
 
    history = list(graph.iter_lefthand_ancestry(branch.last_revision(),
110
 
        [_mod_revision.NULL_REVISION]))
111
 
    for revision_id in reversed(history):
 
108
    for revision_id in branch.revision_history():
112
109
        this_inv = branch.repository.get_inventory(revision_id)
113
110
        if this_inv.has_id(file_id):
114
111
            this_ie = this_inv[file_id]
218
215
    Logger(branch, rqst).show(lf)
219
216
 
220
217
 
221
 
# Note: This needs to be kept in sync with the defaults in
 
218
# Note: This needs to be kept this in sync with the defaults in
222
219
# make_log_request_dict() below
223
220
_DEFAULT_REQUEST_PARAMS = {
224
221
    'direction': 'reverse',
235
232
                          delta_type=None,
236
233
                          diff_type=None, _match_using_deltas=True,
237
234
                          exclude_common_ancestry=False, match=None,
238
 
                          signature=False, omit_merges=False,
 
235
                          signature=False,
239
236
                          ):
240
237
    """Convenience function for making a logging request dictionary.
241
238
 
291
288
      revisions. Keys can be 'message', 'author', 'committer', 'bugs' or
292
289
      the empty string to match any of the preceding properties.
293
290
 
294
 
    :param omit_merges: If True, commits with more than one parent are
295
 
      omitted.
296
 
 
297
291
    """
298
292
    # Take care of old style message_search parameter
299
293
    if message_search:
317
311
        'exclude_common_ancestry': exclude_common_ancestry,
318
312
        'signature': signature,
319
313
        'match': match,
320
 
        'omit_merges': omit_merges,
321
314
        # Add 'private' attributes for features that may be deprecated
322
315
        '_match_using_deltas': _match_using_deltas,
323
316
    }
341
334
    from bzrlib import gpg
342
335
 
343
336
    gpg_strategy = gpg.GPGStrategy(None)
344
 
    result = repo.verify_revision_signature(rev_id, gpg_strategy)
 
337
    result = repo.verify_revision(rev_id, gpg_strategy)
345
338
    if result[0] == gpg.SIGNATURE_VALID:
346
339
        return "valid signature from {0}".format(result[1])
347
340
    if result[0] == gpg.SIGNATURE_KEY_MISSING:
454
447
        limit = rqst.get('limit')
455
448
        diff_type = rqst.get('diff_type')
456
449
        show_signature = rqst.get('signature')
457
 
        omit_merges = rqst.get('omit_merges')
458
450
        log_count = 0
459
451
        revision_iterator = self._create_log_revision_iterator()
460
452
        for revs in revision_iterator:
462
454
                # 0 levels means show everything; merge_depth counts from 0
463
455
                if levels != 0 and merge_depth >= levels:
464
456
                    continue
465
 
                if omit_merges and len(rev.parent_ids) > 1:
466
 
                    continue
467
457
                if diff_type is None:
468
458
                    diff = None
469
459
                else:
568
558
             a list of the same tuples.
569
559
    """
570
560
    if (exclude_common_ancestry and start_rev_id == end_rev_id):
571
 
        raise errors.BzrCommandError(gettext(
572
 
            '--exclude-common-ancestry requires two different revisions'))
 
561
        raise errors.BzrCommandError(
 
562
            '--exclude-common-ancestry requires two different revisions')
573
563
    if direction not in ('reverse', 'forward'):
574
 
        raise ValueError(gettext('invalid direction %r') % direction)
 
564
        raise ValueError('invalid direction %r' % direction)
575
565
    br_revno, br_rev_id = branch.last_revision_info()
576
566
    if br_revno == 0:
577
567
        return []
580
570
        and (not generate_merge_revisions
581
571
             or not _has_merges(branch, end_rev_id))):
582
572
        # If a single revision is requested, check we can handle it
583
 
        return  _generate_one_revision(branch, end_rev_id, br_rev_id,
584
 
                                       br_revno)
585
 
    if not generate_merge_revisions:
586
 
        try:
587
 
            # If we only want to see linear revisions, we can iterate ...
588
 
            iter_revs = _linear_view_revisions(
589
 
                branch, start_rev_id, end_rev_id,
590
 
                exclude_common_ancestry=exclude_common_ancestry)
591
 
            # If a start limit was given and it's not obviously an
592
 
            # ancestor of the end limit, check it before outputting anything
593
 
            if (direction == 'forward'
594
 
                or (start_rev_id and not _is_obvious_ancestor(
595
 
                        branch, start_rev_id, end_rev_id))):
596
 
                    iter_revs = list(iter_revs)
597
 
            if direction == 'forward':
598
 
                iter_revs = reversed(iter_revs)
599
 
            return iter_revs
600
 
        except _StartNotLinearAncestor:
601
 
            # Switch to the slower implementation that may be able to find a
602
 
            # non-obvious ancestor out of the left-hand history.
603
 
            pass
604
 
    iter_revs = _generate_all_revisions(branch, start_rev_id, end_rev_id,
605
 
                                        direction, delayed_graph_generation,
606
 
                                        exclude_common_ancestry)
607
 
    if direction == 'forward':
608
 
        iter_revs = _rebase_merge_depth(reverse_by_depth(list(iter_revs)))
 
573
        iter_revs = _generate_one_revision(branch, end_rev_id, br_rev_id,
 
574
                                           br_revno)
 
575
    elif not generate_merge_revisions:
 
576
        # If we only want to see linear revisions, we can iterate ...
 
577
        iter_revs = _generate_flat_revisions(branch, start_rev_id, end_rev_id,
 
578
                                             direction, exclude_common_ancestry)
 
579
        if direction == 'forward':
 
580
            iter_revs = reversed(iter_revs)
 
581
    else:
 
582
        iter_revs = _generate_all_revisions(branch, start_rev_id, end_rev_id,
 
583
                                            direction, delayed_graph_generation,
 
584
                                            exclude_common_ancestry)
 
585
        if direction == 'forward':
 
586
            iter_revs = _rebase_merge_depth(reverse_by_depth(list(iter_revs)))
609
587
    return iter_revs
610
588
 
611
589
 
618
596
        return [(rev_id, revno_str, 0)]
619
597
 
620
598
 
 
599
def _generate_flat_revisions(branch, start_rev_id, end_rev_id, direction,
 
600
                             exclude_common_ancestry=False):
 
601
    result = _linear_view_revisions(
 
602
        branch, start_rev_id, end_rev_id,
 
603
        exclude_common_ancestry=exclude_common_ancestry)
 
604
    # If a start limit was given and it's not obviously an
 
605
    # ancestor of the end limit, check it before outputting anything
 
606
    if direction == 'forward' or (start_rev_id
 
607
        and not _is_obvious_ancestor(branch, start_rev_id, end_rev_id)):
 
608
        try:
 
609
            result = list(result)
 
610
        except _StartNotLinearAncestor:
 
611
            raise errors.BzrCommandError('Start revision not found in'
 
612
                ' left-hand history of end revision.')
 
613
    return result
 
614
 
 
615
 
621
616
def _generate_all_revisions(branch, start_rev_id, end_rev_id, direction,
622
617
                            delayed_graph_generation,
623
618
                            exclude_common_ancestry=False):
659
654
        except _StartNotLinearAncestor:
660
655
            # A merge was never detected so the lower revision limit can't
661
656
            # be nested down somewhere
662
 
            raise errors.BzrCommandError(gettext('Start revision not found in'
663
 
                ' history of end revision.'))
 
657
            raise errors.BzrCommandError('Start revision not found in'
 
658
                ' history of end revision.')
664
659
 
665
660
    # We exit the loop above because we encounter a revision with merges, from
666
661
    # this revision, we need to switch to _graph_view_revisions.
1077
1072
    if branch_revno != 0:
1078
1073
        if (start_rev_id == _mod_revision.NULL_REVISION
1079
1074
            or end_rev_id == _mod_revision.NULL_REVISION):
1080
 
            raise errors.BzrCommandError(gettext('Logging revision 0 is invalid.'))
 
1075
            raise errors.BzrCommandError('Logging revision 0 is invalid.')
1081
1076
        if start_revno > end_revno:
1082
 
            raise errors.BzrCommandError(gettext("Start revision must be "
1083
 
                                         "older than the end revision."))
 
1077
            raise errors.BzrCommandError("Start revision must be older than "
 
1078
                                         "the end revision.")
1084
1079
    return (start_rev_id, end_rev_id)
1085
1080
 
1086
1081
 
1135
1130
 
1136
1131
    if ((start_rev_id == _mod_revision.NULL_REVISION)
1137
1132
        or (end_rev_id == _mod_revision.NULL_REVISION)):
1138
 
        raise errors.BzrCommandError(gettext('Logging revision 0 is invalid.'))
 
1133
        raise errors.BzrCommandError('Logging revision 0 is invalid.')
1139
1134
    if start_revno > end_revno:
1140
 
        raise errors.BzrCommandError(gettext("Start revision must be older "
1141
 
                                     "than the end revision."))
 
1135
        raise errors.BzrCommandError("Start revision must be older than "
 
1136
                                     "the end revision.")
1142
1137
 
1143
1138
    if end_revno < start_revno:
1144
1139
        return None, None, None, None
1410
1405
            if advice_sep:
1411
1406
                self.to_file.write(advice_sep)
1412
1407
            self.to_file.write(
1413
 
                "Use --include-merged or -n0 to see merged revisions.\n")
 
1408
                "Use --include-merges or -n0 to see merged revisions.\n")
1414
1409
 
1415
1410
    def get_advice_separator(self):
1416
1411
        """Get the text separating the log from the closing advice."""
1794
1789
        return self.get(name)(*args, **kwargs)
1795
1790
 
1796
1791
    def get_default(self, branch):
1797
 
        c = branch.get_config_stack()
1798
 
        return self.get(c.get('log_format'))
 
1792
        return self.get(branch.get_config().log_format())
1799
1793
 
1800
1794
 
1801
1795
log_formatter_registry = LogFormatterRegistry()
1802
1796
 
1803
1797
 
1804
1798
log_formatter_registry.register('short', ShortLogFormatter,
1805
 
                                'Moderately short log format.')
 
1799
                                'Moderately short log format')
1806
1800
log_formatter_registry.register('long', LongLogFormatter,
1807
 
                                'Detailed log format.')
 
1801
                                'Detailed log format')
1808
1802
log_formatter_registry.register('line', LineLogFormatter,
1809
 
                                'Log format with one line per revision.')
 
1803
                                'Log format with one line per revision')
1810
1804
log_formatter_registry.register('gnu-changelog', GnuChangelogLogFormatter,
1811
 
                                'Format used by GNU ChangeLog files.')
 
1805
                                'Format used by GNU ChangeLog files')
1812
1806
 
1813
1807
 
1814
1808
def register_formatter(name, formatter):
1824
1818
    try:
1825
1819
        return log_formatter_registry.make_formatter(name, *args, **kwargs)
1826
1820
    except KeyError:
1827
 
        raise errors.BzrCommandError(gettext("unknown log formatter: %r") % name)
 
1821
        raise errors.BzrCommandError("unknown log formatter: %r" % name)
1828
1822
 
1829
1823
 
1830
1824
def author_list_all(rev):
2023
2017
      kind is one of values 'directory', 'file', 'symlink', 'tree-reference'.
2024
2018
      branch will be read-locked.
2025
2019
    """
2026
 
    from bzrlib.builtins import _get_revision_range
2027
 
    tree, b, path = controldir.ControlDir.open_containing_tree_or_branch(
2028
 
        file_list[0])
 
2020
    from builtins import _get_revision_range
 
2021
    tree, b, path = bzrdir.BzrDir.open_containing_tree_or_branch(file_list[0])
2029
2022
    add_cleanup(b.lock_read().unlock)
2030
2023
    # XXX: It's damn messy converting a list of paths to relative paths when
2031
2024
    # those paths might be deleted ones, they might be on a case-insensitive
2120
2113
                          len(row) > 1 and row[1] == 'fixed']
2121
2114
 
2122
2115
        if fixed_bug_urls:
2123
 
            return {ngettext('fixes bug', 'fixes bugs', len(fixed_bug_urls)):\
2124
 
                    ' '.join(fixed_bug_urls)}
 
2116
            return {'fixes bug(s)': ' '.join(fixed_bug_urls)}
2125
2117
    return {}
2126
2118
 
2127
2119
properties_handler_registry.register('bugs_properties_handler',