203
203
if specific_fileid:
204
204
trace.mutter('get log for file_id %r', specific_fileid)
205
generate_merge_revisions = getattr(lf, 'supports_merge_revisions', False)
206
allow_single_merge_revision = getattr(lf,
207
'supports_single_merge_revision', False)
205
levels_to_display = lf.get_levels()
206
generate_merge_revisions = levels_to_display != 1
207
allow_single_merge_revision = True
208
if not getattr(lf, 'supports_merge_revisions', False):
209
allow_single_merge_revision = getattr(lf,
210
'supports_single_merge_revision', False)
208
211
view_revisions = calculate_view_revisions(branch, start_revision,
209
212
end_revision, direction,
226
229
generate_delta, search)
227
230
for revs in revision_iterator:
228
231
for (rev_id, revno, merge_depth), rev, delta in revs:
232
# Note: 0 levels means show everything; merge_depth counts from 0
233
if levels_to_display != 0 and merge_depth >= levels_to_display:
229
235
if generate_diff:
230
236
diff = _format_diff(repo, rev, rev_id, specific_fileid)
753
759
also not True, then only mainline revisions will be passed to the
762
- preferred_levels is the number of levels this formatter defaults to.
763
The default value is zero meaning display all levels.
764
This value is only relevant if supports_merge_revisions is True.
756
766
- supports_single_merge_revision must be True if this log formatter
757
767
supports logging only a single merge revision. This flag is
758
768
only relevant if supports_merge_revisions is not True.
770
780
# code that returns a dict {'name':'value'} of the properties
774
785
def __init__(self, to_file, show_ids=False, show_timezone='original',
786
delta_format=None, levels=None):
787
"""Create a LogFormatter.
789
:param to_file: the file to output to
790
:param show_ids: if True, revision-ids are to be displayed
791
:param show_timezone: the timezone to use
792
:param delta_format: the level of delta information to display
793
or None to leave it u to the formatter to decide
794
:param levels: the number of levels to display; None or -1 to
795
let the log formatter decide.
776
797
self.to_file = to_file
777
798
self.show_ids = show_ids
778
799
self.show_timezone = show_timezone
780
801
# Ensures backward compatibility
781
802
delta_format = 2 # long format
782
803
self.delta_format = delta_format
784
# TODO: uncomment this block after show() has been removed.
785
# Until then defining log_revision would prevent _show_log calling show()
786
# in legacy formatters.
787
# def log_revision(self, revision):
790
# :param revision: The LogRevision to be logged.
792
# raise NotImplementedError('not implemented in abstract base')
806
def get_levels(self):
807
"""Get the number of levels to display or 0 for all."""
808
if getattr(self, 'supports_merge_revisions', False):
809
if self.levels is None or self.levels == -1:
810
return self.preferred_levels
815
def log_revision(self, revision):
818
:param revision: The LogRevision to be logged.
820
raise NotImplementedError('not implemented in abstract base')
794
822
def short_committer(self, rev):
795
823
name, address = config.parse_username(rev.committer)
875
903
class ShortLogFormatter(LogFormatter):
905
supports_merge_revisions = True
877
907
supports_delta = True
878
908
supports_tags = True
879
supports_single_merge_revision = True
880
909
supports_diff = True
911
def __init__(self, *args, **kwargs):
912
super(ShortLogFormatter, self).__init__(*args, **kwargs)
913
self.revno_width_by_depth = {}
882
915
def log_revision(self, revision):
916
# We need two indents: one per depth and one for the information
917
# relative to that indent. Most mainline revnos are 5 chars or
918
# less while dotted revnos are typically 11 chars or less. Once
919
# calculated, we need to remember the offset for a given depth
920
# as we might be starting from a dotted revno in the first column
921
# and we want subsequent mainline revisions to line up.
922
depth = revision.merge_depth
924
revno_width = self.revno_width_by_depth.get(depth)
925
if revno_width is None:
926
if revision.revno.find('.') == -1:
927
# mainline revno, e.g. 12345
930
# dotted revno, e.g. 12345.10.55
932
self.revno_width_by_depth[depth] = revno_width
933
offset = ' ' * (revno_width + 1)
883
935
to_file = self.to_file
885
937
if len(revision.rev.parent_ids) > 1:
888
940
if revision.tags:
889
941
tags = ' {%s}' % (', '.join(revision.tags))
891
to_file.write("%5s %s\t%s%s%s\n" % (revision.revno,
892
self.short_author(revision.rev),
942
to_file.write(indent + "%*s %s\t%s%s%s\n" % (revno_width,
943
revision.revno, self.short_author(revision.rev),
893
944
format_date(revision.rev.timestamp,
894
945
revision.rev.timezone or 0,
895
946
self.show_timezone, date_fmt="%Y-%m-%d",
896
947
show_offset=False),
898
949
if self.show_ids:
899
to_file.write(' revision-id:%s\n'
950
to_file.write(indent + offset + 'revision-id:%s\n'
900
951
% (revision.rev.revision_id,))
901
952
if not revision.rev.message:
902
to_file.write(' (no message)\n')
953
to_file.write(indent + offset + '(no message)\n')
904
955
message = revision.rev.message.rstrip('\r\n')
905
956
for l in message.split('\n'):
906
to_file.write(' %s\n' % (l,))
957
to_file.write(indent + offset + '%s\n' % (l,))
908
959
if revision.delta is not None:
909
revision.delta.show(to_file, self.show_ids,
960
revision.delta.show(to_file, self.show_ids, indent=indent + offset,
910
961
short_status=self.delta_format==1)
911
962
if revision.diff is not None:
912
963
self.show_diff(to_file, revision.diff, ' ')
916
967
class LineLogFormatter(LogFormatter):
969
supports_merge_revisions = True
918
971
supports_tags = True
919
supports_single_merge_revision = True
921
973
def __init__(self, *args, **kwargs):
922
974
super(LineLogFormatter, self).__init__(*args, **kwargs)
939
991
return rev.message
941
993
def log_revision(self, revision):
994
indent = ' ' * revision.merge_depth
942
995
self.to_file.write(self.log_string(revision.revno, revision.rev,
943
self._max_chars, revision.tags))
996
self._max_chars, revision.tags, indent))
944
997
self.to_file.write('\n')
946
def log_string(self, revno, rev, max_chars, tags=None):
999
def log_string(self, revno, rev, max_chars, tags=None, prefix=''):
947
1000
"""Format log info into one string. Truncate tail of string
948
1001
:param revno: revision number or None.
949
1002
Revision numbers counts from 1.
950
1003
:param rev: revision object
951
1004
:param max_chars: maximum length of resulting string
952
1005
:param tags: list of tags or None
1006
:param prefix: string to prefix each line
953
1007
:return: formatted truncated string
962
1016
tag_str = '{%s}' % (', '.join(tags))
963
1017
out.append(tag_str)
964
1018
out.append(rev.get_summary())
965
return self.truncate(" ".join(out).rstrip('\n'), max_chars)
1019
return self.truncate(prefix + " ".join(out).rstrip('\n'), max_chars)
968
1022
def line_log(rev, max_chars):