/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to breezy/log.py

  • Committer: Jelmer Vernooij
  • Date: 2018-11-11 04:08:32 UTC
  • mto: (7143.16.20 even-more-cleanups)
  • mto: This revision was merged to the branch mainline in revision 7175.
  • Revision ID: jelmer@jelmer.uk-20181111040832-nsljjynzzwmznf3h
Run autopep8.

Show diffs side-by-side

added added

removed removed

Lines of Context:
213
213
 
214
214
    # Build the request and execute it
215
215
    rqst = make_log_request_dict(direction=direction, specific_fileids=file_ids,
216
 
        start_revision=start_revision, end_revision=end_revision,
217
 
        limit=limit, message_search=search,
218
 
        delta_type=delta_type, diff_type=diff_type)
 
216
                                 start_revision=start_revision, end_revision=end_revision,
 
217
                                 limit=limit, message_search=search,
 
218
                                 delta_type=delta_type, diff_type=diff_type)
219
219
    Logger(branch, rqst).show(lf)
220
220
 
221
221
 
304
304
            else:
305
305
                match['message'] = [message_search]
306
306
        else:
307
 
            match= {'message': [message_search]}
 
307
            match = {'message': [message_search]}
308
308
    return {
309
309
        'direction': direction,
310
310
        'specific_fileids': specific_fileids,
420
420
                lf.log_revision(lr)
421
421
        except errors.GhostRevisionUnusableHere:
422
422
            raise errors.BzrCommandError(
423
 
                    gettext('Further revision history missing.'))
 
423
                gettext('Further revision history missing.'))
424
424
        lf.show_advice()
425
425
 
426
426
    def _generator_factory(self, branch, rqst):
477
477
                else:
478
478
                    signature = None
479
479
                yield LogRevision(rev, revno, merge_depth, delta,
480
 
                    self.rev_tag_dict.get(rev_id), diff, signature)
 
480
                                  self.rev_tag_dict.get(rev_id), diff, signature)
481
481
                if limit:
482
482
                    log_count += 1
483
483
                    if log_count >= limit:
499
499
        s = BytesIO()
500
500
        path_encoding = get_diff_header_encoding()
501
501
        diff.show_diff_trees(tree_1, tree_2, s, specific_files, old_label='',
502
 
            new_label='', path_encoding=path_encoding)
 
502
                             new_label='', path_encoding=path_encoding)
503
503
        return s.getvalue()
504
504
 
505
505
    def _create_log_revision_iterator(self):
520
520
            file_count = len(self.rqst.get('specific_fileids'))
521
521
            if file_count != 1:
522
522
                raise BzrError("illegal LogRequest: must match-using-deltas "
523
 
                    "when logging %d files" % file_count)
 
523
                               "when logging %d files" % file_count)
524
524
            return self._log_revision_iterator_using_per_file_graph()
525
525
 
526
526
    def _log_revision_iterator_using_delta_matching(self):
528
528
        rqst = self.rqst
529
529
        generate_merge_revisions = rqst.get('levels') != 1
530
530
        delayed_graph_generation = not rqst.get('specific_fileids') and (
531
 
                rqst.get('limit') or self.start_rev_id or self.end_rev_id)
 
531
            rqst.get('limit') or self.start_rev_id or self.end_rev_id)
532
532
        view_revisions = _calc_view_revisions(
533
533
            self.branch, self.start_rev_id, self.end_rev_id,
534
534
            rqst.get('direction'),
538
538
 
539
539
        # Apply the other filters
540
540
        return make_log_rev_iterator(self.branch, view_revisions,
541
 
            rqst.get('delta_type'), rqst.get('match'),
542
 
            file_ids=rqst.get('specific_fileids'),
543
 
            direction=rqst.get('direction'))
 
541
                                     rqst.get('delta_type'), rqst.get('match'),
 
542
                                     file_ids=rqst.get('specific_fileids'),
 
543
                                     direction=rqst.get('direction'))
544
544
 
545
545
    def _log_revision_iterator_using_per_file_graph(self):
546
546
        # Get the base revisions, filtering by the revision range.
554
554
        if not isinstance(view_revisions, list):
555
555
            view_revisions = list(view_revisions)
556
556
        view_revisions = _filter_revisions_touching_file_id(self.branch,
557
 
            rqst.get('specific_fileids')[0], view_revisions,
558
 
            include_merges=rqst.get('levels') != 1)
 
557
                                                            rqst.get('specific_fileids')[
 
558
                                                                0], view_revisions,
 
559
                                                            include_merges=rqst.get('levels') != 1)
559
560
        return make_log_rev_iterator(self.branch, view_revisions,
560
 
            rqst.get('delta_type'), rqst.get('match'))
 
561
                                     rqst.get('delta_type'), rqst.get('match'))
561
562
 
562
563
 
563
564
def _calc_view_revisions(branch, start_rev_id, end_rev_id, direction,
581
582
 
582
583
    if (end_rev_id and start_rev_id == end_rev_id
583
584
        and (not generate_merge_revisions
584
 
             or not _has_merges(branch, end_rev_id))):
 
585
         or not _has_merges(branch, end_rev_id))):
585
586
        # If a single revision is requested, check we can handle it
586
 
        return  _generate_one_revision(branch, end_rev_id, br_rev_id,
587
 
                                       branch.revno())
 
587
        return _generate_one_revision(branch, end_rev_id, br_rev_id,
 
588
                                      branch.revno())
588
589
    if not generate_merge_revisions:
589
590
        try:
590
591
            # If we only want to see linear revisions, we can iterate ...
595
596
            # ancestor of the end limit, check it before outputting anything
596
597
            if (direction == 'forward'
597
598
                or (start_rev_id and not _is_obvious_ancestor(
598
 
                        branch, start_rev_id, end_rev_id))):
599
 
                    iter_revs = list(iter_revs)
 
599
                    branch, start_rev_id, end_rev_id))):
 
600
                iter_revs = list(iter_revs)
600
601
            if direction == 'forward':
601
602
                iter_revs = reversed(iter_revs)
602
603
            return iter_revs
634
635
    initial_revisions = []
635
636
    if delayed_graph_generation:
636
637
        try:
637
 
            for rev_id, revno, depth in  _linear_view_revisions(
638
 
                branch, start_rev_id, end_rev_id, exclude_common_ancestry):
 
638
            for rev_id, revno, depth in _linear_view_revisions(
 
639
                    branch, start_rev_id, end_rev_id, exclude_common_ancestry):
639
640
                if _has_merges(branch, rev_id):
640
641
                    # The end_rev_id can be nested down somewhere. We need an
641
642
                    # explicit ancestry check. There is an ambiguity here as we
648
649
                    # -- vila 20100319
649
650
                    graph = branch.repository.get_graph()
650
651
                    if (start_rev_id is not None
651
 
                        and not graph.is_ancestor(start_rev_id, end_rev_id)):
 
652
                            and not graph.is_ancestor(start_rev_id, end_rev_id)):
652
653
                        raise _StartNotLinearAncestor()
653
654
                    # Since we collected the revisions so far, we need to
654
655
                    # adjust end_rev_id.
663
664
            # A merge was never detected so the lower revision limit can't
664
665
            # be nested down somewhere
665
666
            raise errors.BzrCommandError(gettext('Start revision not found in'
666
 
                ' history of end revision.'))
 
667
                                                 ' history of end revision.'))
667
668
 
668
669
    # We exit the loop above because we encounter a revision with merges, from
669
670
    # this revision, we need to switch to _graph_view_revisions.
674
675
    # make forward the exact opposite display, but showing the merge revisions
675
676
    # indented at the end seems slightly nicer in that case.
676
677
    view_revisions = itertools.chain(iter(initial_revisions),
677
 
        _graph_view_revisions(branch, start_rev_id, end_rev_id,
678
 
                              rebase_initial_depths=(direction == 'reverse'),
679
 
                              exclude_common_ancestry=exclude_common_ancestry))
 
678
                                     _graph_view_revisions(branch, start_rev_id, end_rev_id,
 
679
                                                           rebase_initial_depths=(
 
680
                                                               direction == 'reverse'),
 
681
                                                           exclude_common_ancestry=exclude_common_ancestry))
680
682
    return view_revisions
681
683
 
682
684
 
714
716
            # both on mainline
715
717
            return start_dotted[0] <= end_dotted[0]
716
718
        elif (len(start_dotted) == 3 and len(end_dotted) == 3 and
717
 
            start_dotted[0:1] == end_dotted[0:1]):
 
719
              start_dotted[0:1] == end_dotted[0:1]):
718
720
            # both on same development line
719
721
            return start_dotted[2] <= end_dotted[2]
720
722
        else:
749
751
        else:
750
752
            cur_revno = br_revno
751
753
        graph_iter = graph.iter_lefthand_ancestry(br_rev_id,
752
 
            (_mod_revision.NULL_REVISION,))
 
754
                                                  (_mod_revision.NULL_REVISION,))
753
755
        while True:
754
756
            try:
755
757
                revision_id = next(graph_iter)
769
771
            end_rev_id = br_rev_id
770
772
        found_start = start_rev_id is None
771
773
        graph_iter = graph.iter_lefthand_ancestry(end_rev_id,
772
 
            (_mod_revision.NULL_REVISION,))
 
774
                                                  (_mod_revision.NULL_REVISION,))
773
775
        while True:
774
776
            try:
775
777
                revision_id = next(graph_iter)
842
844
    if view_revisions and view_revisions[0][2] and view_revisions[-1][2]:
843
845
        min_depth = min([d for r, n, d in view_revisions])
844
846
        if min_depth != 0:
845
 
            view_revisions = [(r, n, d-min_depth) for r, n, d in view_revisions]
 
847
            view_revisions = [(r, n, d - min_depth)
 
848
                              for r, n, d in view_revisions]
846
849
    return view_revisions
847
850
 
848
851
 
849
852
def make_log_rev_iterator(branch, view_revisions, generate_delta, search,
850
 
        file_ids=None, direction='reverse'):
 
853
                          file_ids=None, direction='reverse'):
851
854
    """Create a revision iterator for log.
852
855
 
853
856
    :param branch: The branch being logged.
878
881
        # with custom parameters. This will do for now. IGC 20090127
879
882
        if adapter == _make_delta_filter:
880
883
            log_rev_iterator = adapter(branch, generate_delta,
881
 
                search, log_rev_iterator, file_ids, direction)
 
884
                                       search, log_rev_iterator, file_ids, direction)
882
885
        else:
883
886
            log_rev_iterator = adapter(branch, generate_delta,
884
 
                search, log_rev_iterator)
 
887
                                       search, log_rev_iterator)
885
888
    return log_rev_iterator
886
889
 
887
890
 
912
915
        if new_revs:
913
916
            yield new_revs
914
917
 
 
918
 
915
919
def _match_filter(searchRE, rev):
916
920
    strings = {
917
 
               'message': (rev.message,),
918
 
               'committer': (rev.committer,),
919
 
               'author': (rev.get_apparent_authors()),
920
 
               'bugs': list(rev.iter_bugs())
921
 
               }
 
921
        'message': (rev.message,),
 
922
        'committer': (rev.committer,),
 
923
        'author': (rev.get_apparent_authors()),
 
924
        'bugs': list(rev.iter_bugs())
 
925
        }
922
926
    strings[''] = [item for inner_list in strings.values()
923
927
                   for item in inner_list]
924
928
    for (k, v) in searchRE:
926
930
            return False
927
931
    return True
928
932
 
 
933
 
929
934
def _match_any_filter(strings, res):
930
935
    return any(re.search(s) for re in res for s in strings)
931
936
 
 
937
 
932
938
def _make_delta_filter(branch, generate_delta, search, log_rev_iterator,
933
 
    fileids=None, direction='reverse'):
 
939
                       fileids=None, direction='reverse'):
934
940
    """Add revision deltas to a log iterator if needed.
935
941
 
936
942
    :param branch: The branch being logged.
948
954
    if not generate_delta and not fileids:
949
955
        return log_rev_iterator
950
956
    return _generate_deltas(branch.repository, log_rev_iterator,
951
 
        generate_delta, fileids, direction)
 
957
                            generate_delta, fileids, direction)
952
958
 
953
959
 
954
960
def _generate_deltas(repository, log_rev_iterator, delta_type, fileids,
955
 
    direction):
 
961
                     direction):
956
962
    """Create deltas for each batch of revisions in log_rev_iterator.
957
963
 
958
964
    If we're only generating deltas for the sake of filtering against
1101
1107
 
1102
1108
    if branch.last_revision() != _mod_revision.NULL_REVISION:
1103
1109
        if (start_rev_id == _mod_revision.NULL_REVISION
1104
 
            or end_rev_id == _mod_revision.NULL_REVISION):
1105
 
            raise errors.BzrCommandError(gettext('Logging revision 0 is invalid.'))
 
1110
                or end_rev_id == _mod_revision.NULL_REVISION):
 
1111
            raise errors.BzrCommandError(
 
1112
                gettext('Logging revision 0 is invalid.'))
1106
1113
        if end_revno is not None and start_revno > end_revno:
1107
1114
            raise errors.BzrCommandError(gettext("Start revision must be "
1108
 
                                         "older than the end revision."))
 
1115
                                                 "older than the end revision."))
1109
1116
    return (start_rev_id, end_rev_id)
1110
1117
 
1111
1118
 
1159
1166
            end_revno = end_revision
1160
1167
 
1161
1168
    if ((start_rev_id == _mod_revision.NULL_REVISION)
1162
 
        or (end_rev_id == _mod_revision.NULL_REVISION)):
 
1169
            or (end_rev_id == _mod_revision.NULL_REVISION)):
1163
1170
        raise errors.BzrCommandError(gettext('Logging revision 0 is invalid.'))
1164
1171
    if start_revno > end_revno:
1165
1172
        raise errors.BzrCommandError(gettext("Start revision must be older "
1166
 
                                     "than the end revision."))
 
1173
                                             "than the end revision."))
1167
1174
 
1168
1175
    if end_revno < start_revno:
1169
1176
        return None, None, None, None
1193
1200
 
1194
1201
 
1195
1202
def _filter_revisions_touching_file_id(branch, file_id, view_revisions,
1196
 
    include_merges=True):
 
1203
                                       include_merges=True):
1197
1204
    r"""Return the list of revision ids which touch a given file id.
1198
1205
 
1199
1206
    The function filters view_revisions and returns a subset.
1405
1412
        self.show_timezone = show_timezone
1406
1413
        if delta_format is None:
1407
1414
            # Ensures backward compatibility
1408
 
            delta_format = 2 # long format
 
1415
            delta_format = 2  # long format
1409
1416
        self.delta_format = delta_format
1410
1417
        self.levels = levels
1411
1418
        self._show_advice = show_advice
1574
1581
 
1575
1582
    def _date_string_original_timezone(self, rev):
1576
1583
        return format_date_with_offset_in_original_timezone(rev.timestamp,
1577
 
            rev.timezone or 0)
 
1584
                                                            rev.timezone or 0)
1578
1585
 
1579
1586
    def log_revision(self, revision):
1580
1587
        """Log a revision, either merged or not."""
1582
1589
        lines = [_LONG_SEP]
1583
1590
        if revision.revno is not None:
1584
1591
            lines.append('revno: %s%s' % (revision.revno,
1585
 
                self.merge_marker(revision)))
 
1592
                                          self.merge_marker(revision)))
1586
1593
        if revision.tags:
1587
1594
            lines.append('tags: %s' % (', '.join(sorted(revision.tags))))
1588
1595
        if self.show_ids or revision.revno is None:
1589
 
            lines.append('revision-id: %s' % (revision.rev.revision_id.decode('utf-8'),))
 
1596
            lines.append('revision-id: %s' %
 
1597
                         (revision.rev.revision_id.decode('utf-8'),))
1590
1598
        if self.show_ids:
1591
1599
            for parent_id in revision.rev.parent_ids:
1592
1600
                lines.append('parent: %s' % (parent_id.decode('utf-8'),))
1673
1681
        if revision.tags:
1674
1682
            tags = ' {%s}' % (', '.join(sorted(revision.tags)))
1675
1683
        to_file.write(indent + "%*s %s\t%s%s%s\n" % (revno_width,
1676
 
                revision.revno or "", self.short_author(revision.rev),
1677
 
                format_date(revision.rev.timestamp,
1678
 
                            revision.rev.timezone or 0,
1679
 
                            self.show_timezone, date_fmt="%Y-%m-%d",
1680
 
                            show_offset=False),
1681
 
                tags, self.merge_marker(revision)))
1682
 
        self.show_properties(revision.rev, indent+offset)
 
1684
                                                     revision.revno or "", self.short_author(
 
1685
                                                         revision.rev),
 
1686
                                                     format_date(revision.rev.timestamp,
 
1687
                                                                 revision.rev.timezone or 0,
 
1688
                                                                 self.show_timezone, date_fmt="%Y-%m-%d",
 
1689
                                                                 show_offset=False),
 
1690
                                                     tags, self.merge_marker(revision)))
 
1691
        self.show_properties(revision.rev, indent + offset)
1683
1692
        if self.show_ids or revision.revno is None:
1684
1693
            to_file.write(indent + offset + 'revision-id:%s\n'
1685
1694
                          % (revision.rev.revision_id.decode('utf-8'),))
1694
1703
            # Use the standard status output to display changes
1695
1704
            from breezy.delta import report_delta
1696
1705
            report_delta(to_file, revision.delta,
1697
 
                         short_status=self.delta_format==1,
 
1706
                         short_status=self.delta_format == 1,
1698
1707
                         show_ids=self.show_ids, indent=indent + offset)
1699
1708
        if revision.diff is not None:
1700
1709
            self.show_diff(self.to_exact_file, revision.diff, '      ')
1718
1727
    def truncate(self, str, max_len):
1719
1728
        if max_len is None or len(str) <= max_len:
1720
1729
            return str
1721
 
        return str[:max_len-3] + '...'
 
1730
        return str[:max_len - 3] + '...'
1722
1731
 
1723
1732
    def date_string(self, rev):
1724
1733
        return format_date(rev.timestamp, rev.timezone or 0,
1734
1743
    def log_revision(self, revision):
1735
1744
        indent = '  ' * revision.merge_depth
1736
1745
        self.to_file.write(self.log_string(revision.revno, revision.rev,
1737
 
            self._max_chars, revision.tags, indent))
 
1746
                                           self._max_chars, revision.tags, indent))
1738
1747
        self.to_file.write('\n')
1739
1748
 
1740
1749
    def log_string(self, revno, rev, max_chars, tags=None, prefix=''):
1753
1762
            # show revno only when is not None
1754
1763
            out.append("%s:" % revno)
1755
1764
        if max_chars is not None:
1756
 
            out.append(self.truncate(self.short_author(rev), (max_chars+3)//4))
 
1765
            out.append(self.truncate(
 
1766
                self.short_author(rev), (max_chars + 3) // 4))
1757
1767
        else:
1758
1768
            out.append(self.short_author(rev))
1759
1769
        out.append(self.date_string(rev))
1850
1860
    try:
1851
1861
        return log_formatter_registry.make_formatter(name, *args, **kwargs)
1852
1862
    except KeyError:
1853
 
        raise errors.BzrCommandError(gettext("unknown log formatter: %r") % name)
 
1863
        raise errors.BzrCommandError(
 
1864
            gettext("unknown log formatter: %r") % name)
1854
1865
 
1855
1866
 
1856
1867
def author_list_all(rev):
1892
1903
    """
1893
1904
    if to_file is None:
1894
1905
        to_file = codecs.getwriter(get_terminal_encoding())(sys.stdout,
1895
 
            errors='replace')
 
1906
                                                            errors='replace')
1896
1907
    lf = log_formatter(log_format,
1897
1908
                       show_ids=False,
1898
1909
                       to_file=to_file,
1904
1915
    for i in range(max(len(new_rh), len(old_rh))):
1905
1916
        if (len(new_rh) <= i
1906
1917
            or len(old_rh) <= i
1907
 
            or new_rh[i] != old_rh[i]):
 
1918
                or new_rh[i] != old_rh[i]):
1908
1919
            base_idx = i
1909
1920
            break
1910
1921
 
1911
1922
    if base_idx is None:
1912
1923
        to_file.write('Nothing seems to have changed\n')
1913
1924
        return
1914
 
    ## TODO: It might be nice to do something like show_log
1915
 
    ##       and show the merged entries. But since this is the
1916
 
    ##       removed revisions, it shouldn't be as important
 
1925
    # TODO: It might be nice to do something like show_log
 
1926
    # and show the merged entries. But since this is the
 
1927
    # removed revisions, it shouldn't be as important
1917
1928
    if base_idx < len(old_rh):
1918
 
        to_file.write('*'*60)
 
1929
        to_file.write('*' * 60)
1919
1930
        to_file.write('\nRemoved Revisions:\n')
1920
1931
        for i in range(base_idx, len(old_rh)):
1921
1932
            rev = branch.repository.get_revision(old_rh[i])
1922
 
            lr = LogRevision(rev, i+1, 0, None)
 
1933
            lr = LogRevision(rev, i + 1, 0, None)
1923
1934
            lf.log_revision(lr)
1924
 
        to_file.write('*'*60)
 
1935
        to_file.write('*' * 60)
1925
1936
        to_file.write('\n\n')
1926
1937
    if base_idx < len(new_rh):
1927
1938
        to_file.write('Added Revisions:\n')
1930
1941
                 None,
1931
1942
                 verbose=False,
1932
1943
                 direction='forward',
1933
 
                 start_revision=base_idx+1,
 
1944
                 start_revision=base_idx + 1,
1934
1945
                 end_revision=len(new_rh),
1935
1946
                 search=None)
1936
1947
 
2004
2015
    log_format = log_formatter_registry.get_default(branch)
2005
2016
    lf = log_format(show_ids=False, to_file=output, show_timezone='original')
2006
2017
    if old_history != []:
2007
 
        output.write('*'*60)
 
2018
        output.write('*' * 60)
2008
2019
        output.write('\nRemoved Revisions:\n')
2009
2020
        show_flat_log(branch.repository, old_history, old_revno, lf)
2010
 
        output.write('*'*60)
 
2021
        output.write('*' * 60)
2011
2022
        output.write('\n\n')
2012
2023
    if new_history != []:
2013
2024
        output.write('Added Revisions:\n')
2066
2077
        relpaths = [path] + file_list[1:]
2067
2078
    info_list = []
2068
2079
    start_rev_info, end_rev_info = _get_revision_range(revisionspec_list, b,
2069
 
        "log")
 
2080
                                                       "log")
2070
2081
    if relpaths in ([], [u'']):
2071
2082
        return b, [], start_rev_info, end_rev_info
2072
2083
    if start_rev_info is None and end_rev_info is None:
2137
2148
properties_handler_registry = registry.Registry()
2138
2149
 
2139
2150
# Use the properties handlers to print out bug information if available
 
2151
 
 
2152
 
2140
2153
def _bugs_properties_handler(revision):
2141
2154
    if 'bugs' in revision.properties:
2142
2155
        bug_lines = revision.properties['bugs'].split('\n')
2145
2158
                          len(row) > 1 and row[1] == 'fixed']
2146
2159
 
2147
2160
        if fixed_bug_urls:
2148
 
            return {ngettext('fixes bug', 'fixes bugs', len(fixed_bug_urls)):\
 
2161
            return {ngettext('fixes bug', 'fixes bugs', len(fixed_bug_urls)):
2149
2162
                    ' '.join(fixed_bug_urls)}
2150
2163
    return {}
2151
2164
 
 
2165
 
2152
2166
properties_handler_registry.register('bugs_properties_handler',
2153
2167
                                     _bugs_properties_handler)
2154
2168