310
306
class Logger(object):
311
"""An object that generates, formats and displays a log."""
307
"""An object the generates, formats and displays a log."""
313
309
def __init__(self, branch, rqst):
314
310
"""Create a Logger.
536
532
def _generate_all_revisions(branch, start_rev_id, end_rev_id, direction,
537
delayed_graph_generation):
533
delayed_graph_generation):
538
534
# On large trees, generating the merge graph can take 30-60 seconds
539
535
# so we delay doing it until a merge is detected, incrementally
540
536
# returning initial (non-merge) revisions while we can.
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
545
537
initial_revisions = []
546
538
if delayed_graph_generation:
548
for rev_id, revno, depth in _linear_view_revisions(
549
branch, start_rev_id, end_rev_id):
540
for rev_id, revno, depth in \
541
_linear_view_revisions(branch, start_rev_id, end_rev_id):
550
542
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...
558
graph = branch.repository.get_graph()
559
if not graph.is_ancestor(start_rev_id, end_rev_id):
560
raise _StartNotLinearAncestor()
561
543
end_rev_id = rev_id
684
664
depth_adjustment = merge_depth
685
665
if depth_adjustment:
686
666
if merge_depth < depth_adjustment:
687
# From now on we reduce the depth adjustement, this can be
688
# surprising for users. The alternative requires two passes
689
# which breaks the fast display of the first revision
691
667
depth_adjustment = merge_depth
692
668
merge_depth -= depth_adjustment
693
669
yield rev_id, '.'.join(map(str, revno)), merge_depth
696
@deprecated_function(deprecated_in((2, 2, 0)))
697
672
def calculate_view_revisions(branch, start_revision, end_revision, direction,
698
673
specific_fileid, generate_merge_revisions):
699
674
"""Calculate the revisions to view.
701
676
:return: An iterator of (revision_id, dotted_revno, merge_depth) tuples OR
702
677
a list of the same tuples.
679
# This method is no longer called by the main code path.
680
# It is retained for API compatibility and may be deprecated
704
682
start_rev_id, end_rev_id = _get_revision_limits(branch, start_revision,
706
684
view_revisions = list(_calc_view_revisions(branch, start_rev_id, end_rev_id,
1056
1034
return mainline_revs, rev_nos, start_rev_id, end_rev_id
1059
@deprecated_function(deprecated_in((2, 2, 0)))
1060
1037
def _filter_revision_range(view_revisions, start_rev_id, end_rev_id):
1061
1038
"""Filter view_revisions based on revision ranges.
1072
1049
:return: The filtered view_revisions.
1051
# This method is no longer called by the main code path.
1052
# It may be removed soon. IGC 20090127
1074
1053
if start_rev_id or end_rev_id:
1075
1054
revision_ids = [r for r, n, d in view_revisions]
1076
1055
if start_rev_id:
1185
@deprecated_function(deprecated_in((2, 2, 0)))
1186
1164
def get_view_revisions(mainline_revs, rev_nos, branch, direction,
1187
1165
include_merges=True):
1188
1166
"""Produce an iterator of revisions to show
1189
1167
:return: an iterator of (revision_id, revno, merge_depth)
1190
1168
(if there is no revno for a revision, None is supplied)
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
1192
1173
if not include_merges:
1193
1174
revision_ids = mainline_revs[1:]
1194
1175
if direction == 'reverse':
1312
1293
preferred_levels = 0
1314
1295
def __init__(self, to_file, show_ids=False, show_timezone='original',
1315
delta_format=None, levels=None, show_advice=False,
1316
to_exact_file=None):
1296
delta_format=None, levels=None, show_advice=False,
1297
to_exact_file=None):
1317
1298
"""Create a LogFormatter.
1319
1300
:param to_file: the file to output to
2000
1981
properties_handler_registry = registry.Registry()
2002
# Use the properties handlers to print out bug information if available
2003
def _bugs_properties_handler(revision):
2004
if revision.properties.has_key('bugs'):
2005
bug_lines = revision.properties['bugs'].split('\n')
2006
bug_rows = [line.split(' ', 1) for line in bug_lines]
2007
fixed_bug_urls = [row[0] for row in bug_rows if
2008
len(row) > 1 and row[1] == 'fixed']
2011
return {'fixes bug(s)': ' '.join(fixed_bug_urls)}
2014
properties_handler_registry.register('bugs_properties_handler',
2015
_bugs_properties_handler)
2018
1984
# adapters which revision ids to log are filtered. When log is called, the
2019
1985
# log_rev_iterator is adapted through each of these factory methods.