210
228
mainline_revs.insert(0, None)
212
230
mainline_revs.insert(0, which_revs[start_revision-2][1])
213
# how should we show merged revisions ?
214
# old api: show_merge. New api: show_merge_revno
215
show_merge_revno = getattr(lf, 'show_merge_revno', None)
216
show_merge = getattr(lf, 'show_merge', None)
217
if show_merge is None and show_merge_revno is None:
218
# no merged-revno support
219
include_merges = False
221
include_merges = True
222
if show_merge is not None and show_merge_revno is None:
231
legacy_lf = getattr(lf, 'log_revision', None) is None
233
# pre-0.17 formatters use show for mainline revisions.
234
# how should we show merged revisions ?
235
# pre-0.11 api: show_merge
236
# 0.11-0.16 api: show_merge_revno
237
show_merge_revno = getattr(lf, 'show_merge_revno', None)
238
show_merge = getattr(lf, 'show_merge', None)
239
if show_merge is None and show_merge_revno is None:
240
# no merged-revno support
241
generate_merge_revisions = False
243
generate_merge_revisions = True
223
244
# tell developers to update their code
224
symbol_versioning.warn('LogFormatters should provide show_merge_revno '
225
'instead of show_merge since bzr 0.11.',
245
symbol_versioning.warn('LogFormatters should provide log_revision '
246
'instead of show and show_merge_revno since bzr 0.17.',
226
247
DeprecationWarning, stacklevel=3)
249
generate_merge_revisions = getattr(lf, 'supports_merge_revisions',
227
251
view_revs_iter = get_view_revisions(mainline_revs, rev_nos, branch,
228
direction, include_merges=include_merges)
252
direction, include_merges=generate_merge_revisions)
229
253
if specific_fileid:
230
254
view_revisions = _get_revisions_touching_file_id(branch,
271
298
if not searchRE.search(rev.message):
276
lf.show(revno, rev, delta, rev_tag_dict.get(rev_id))
278
lf.show(revno, rev, delta)
302
lr = LogRevision(rev, revno, merge_depth, delta,
303
rev_tag_dict.get(rev_id))
280
if show_merge_revno is None:
281
lf.show_merge(rev, merge_depth)
306
# support for legacy (pre-0.17) LogFormatters
309
lf.show(revno, rev, delta, rev_tag_dict.get(rev_id))
311
lf.show(revno, rev, delta)
284
lf.show_merge_revno(rev, merge_depth, revno,
285
rev_tag_dict.get(rev_id))
313
if show_merge_revno is None:
314
lf.show_merge(rev, merge_depth)
287
lf.show_merge_revno(rev, merge_depth, revno)
317
lf.show_merge_revno(rev, merge_depth, revno,
318
rev_tag_dict.get(rev_id))
320
lf.show_merge_revno(rev, merge_depth, revno)
323
if log_count >= limit:
290
327
def _get_revisions_touching_file_id(branch, file_id, mainline_revisions,
438
class LogRevision(object):
439
"""A revision to be logged (by LogFormatter.log_revision).
441
A simple wrapper for the attributes of a revision to be logged.
442
The attributes may or may not be populated, as determined by the
443
logging options and the log formatter capabilities.
446
def __init__(self, rev=None, revno=None, merge_depth=0, delta=None,
450
self.merge_depth = merge_depth
401
455
class LogFormatter(object):
402
"""Abstract class to display log messages."""
456
"""Abstract class to display log messages.
458
At a minimum, a derived class must implement the log_revision method.
460
If the LogFormatter needs to be informed of the beginning or end of
461
a log it should implement the begin_log and/or end_log hook methods.
463
A LogFormatter should define the following supports_XXX flags
464
to indicate which LogRevision attributes it supports:
466
- supports_delta must be True if this log formatter supports delta.
467
Otherwise the delta attribute may not be populated.
468
- supports_merge_revisions must be True if this log formatter supports
469
merge revisions. If not, only revisions mainline revisions (those
470
with merge_depth == 0) will be passed to the formatter.
471
- supports_tags must be True if this log formatter supports tags.
472
Otherwise the tags attribute may not be populated.
404
475
def __init__(self, to_file, show_ids=False, show_timezone='original'):
405
476
self.to_file = to_file
406
477
self.show_ids = show_ids
407
478
self.show_timezone = show_timezone
480
# TODO: uncomment this block after show() has been removed.
481
# Until then defining log_revision would prevent _show_log calling show()
482
# in legacy formatters.
483
# def log_revision(self, revision):
486
# :param revision: The LogRevision to be logged.
488
# raise NotImplementedError('not implemented in abstract base')
490
@deprecated_method(zero_seventeen)
409
491
def show(self, revno, rev, delta):
410
492
raise NotImplementedError('not implemented in abstract base')
416
498
class LongLogFormatter(LogFormatter):
418
supports_tags = True # must exist and be True
419
# if this log formatter support tags.
420
# .show() and .show_merge_revno() must then accept
421
# the 'tags'-argument with list of tags
500
supports_merge_revisions = True
501
supports_delta = True
504
@deprecated_method(zero_seventeen)
423
505
def show(self, revno, rev, delta, tags=None):
424
return self._show_helper(revno=revno, rev=rev, delta=delta, tags=tags)
506
lr = LogRevision(rev, revno, 0, delta, tags)
507
return self.log_revision(lr)
426
509
@deprecated_method(zero_eleven)
427
510
def show_merge(self, rev, merge_depth):
428
return self._show_helper(rev=rev, indent=' '*merge_depth,
429
merged=True, delta=None)
511
lr = LogRevision(rev, merge_depth=merge_depth)
512
return self.log_revision(lr)
514
@deprecated_method(zero_seventeen)
431
515
def show_merge_revno(self, rev, merge_depth, revno, tags=None):
432
516
"""Show a merged revision rev, with merge_depth and a revno."""
433
return self._show_helper(rev=rev, revno=revno,
434
indent=' '*merge_depth, merged=True, delta=None, tags=tags)
517
lr = LogRevision(rev, revno, merge_depth, tags=tags)
518
return self.log_revision(lr)
436
def _show_helper(self, rev=None, revno=None, indent='', merged=False,
437
delta=None, tags=None):
438
"""Show a revision, either merged or not."""
520
def log_revision(self, revision):
521
"""Log a revision, either merged or not."""
439
522
from bzrlib.osutils import format_date
523
indent = ' '*revision.merge_depth
440
524
to_file = self.to_file
441
525
print >>to_file, indent+'-' * 60
442
if revno is not None:
443
print >>to_file, indent+'revno:', revno
445
print >>to_file, indent+'tags: %s' % (', '.join(tags))
447
print >>to_file, indent+'merged:', rev.revision_id
449
print >>to_file, indent+'revision-id:', rev.revision_id
526
if revision.revno is not None:
527
print >>to_file, indent+'revno:', revision.revno
529
print >>to_file, indent+'tags: %s' % (', '.join(revision.tags))
450
530
if self.show_ids:
451
for parent_id in rev.parent_ids:
531
print >>to_file, indent+'revision-id:', revision.rev.revision_id
532
for parent_id in revision.rev.parent_ids:
452
533
print >>to_file, indent+'parent:', parent_id
453
print >>to_file, indent+'committer:', rev.committer
534
print >>to_file, indent+'committer:', revision.rev.committer
456
537
print >>to_file, indent+'branch nick: %s' % \
457
rev.properties['branch-nick']
538
revision.rev.properties['branch-nick']
460
date_str = format_date(rev.timestamp,
541
date_str = format_date(revision.rev.timestamp,
542
revision.rev.timezone or 0,
462
543
self.show_timezone)
463
544
print >>to_file, indent+'timestamp: %s' % date_str
465
546
print >>to_file, indent+'message:'
547
if not revision.rev.message:
467
548
print >>to_file, indent+' (no message)'
469
message = rev.message.rstrip('\r\n')
550
message = revision.rev.message.rstrip('\r\n')
470
551
for l in message.split('\n'):
471
552
print >>to_file, indent+' ' + l
472
if delta is not None:
473
delta.show(to_file, self.show_ids)
553
if revision.delta is not None:
554
revision.delta.show(to_file, self.show_ids)
476
557
class ShortLogFormatter(LogFormatter):
559
supports_delta = True
561
@deprecated_method(zero_seventeen)
477
562
def show(self, revno, rev, delta):
563
lr = LogRevision(rev, revno, 0, delta)
564
return self.log_revision(lr)
566
def log_revision(self, revision):
478
567
from bzrlib.osutils import format_date
480
569
to_file = self.to_file
481
date_str = format_date(rev.timestamp, rev.timezone or 0,
483
print >>to_file, "%5s %s\t%s" % (revno, self.short_committer(rev),
484
format_date(rev.timestamp, rev.timezone or 0,
570
date_str = format_date(revision.rev.timestamp,
571
revision.rev.timezone or 0,
574
if len(revision.rev.parent_ids) > 1:
575
is_merge = ' [merge]'
576
print >>to_file, "%5s %s\t%s%s" % (revision.revno,
577
self.short_committer(revision.rev),
578
format_date(revision.rev.timestamp,
579
revision.rev.timezone or 0,
485
580
self.show_timezone, date_fmt="%Y-%m-%d",
487
583
if self.show_ids:
488
print >>to_file, ' revision-id:', rev.revision_id
584
print >>to_file, ' revision-id:', revision.rev.revision_id
585
if not revision.rev.message:
490
586
print >>to_file, ' (no message)'
492
message = rev.message.rstrip('\r\n')
588
message = revision.rev.message.rstrip('\r\n')
493
589
for l in message.split('\n'):
494
590
print >>to_file, ' ' + l
496
592
# TODO: Why not show the modified files in a shorter form as
497
593
# well? rewrap them single lines of appropriate length
498
if delta is not None:
499
delta.show(to_file, self.show_ids)
594
if revision.delta is not None:
595
revision.delta.show(to_file, self.show_ids)
500
596
print >>to_file, ''
503
599
class LineLogFormatter(LogFormatter):
601
def __init__(self, *args, **kwargs):
602
from bzrlib.osutils import terminal_width
603
super(LineLogFormatter, self).__init__(*args, **kwargs)
604
self._max_chars = terminal_width() - 1
504
606
def truncate(self, str, max_len):
505
607
if len(str) <= max_len: