210
220
mainline_revs.insert(0, None)
212
222
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:
223
legacy_lf = getattr(lf, 'log_revision', None) is None
225
# pre-0.17 formatters use show for mainline revisions.
226
# how should we show merged revisions ?
227
# pre-0.11 api: show_merge
228
# 0.11-0.16 api: show_merge_revno
229
show_merge_revno = getattr(lf, 'show_merge_revno', None)
230
show_merge = getattr(lf, 'show_merge', None)
231
if show_merge is None and show_merge_revno is None:
232
# no merged-revno support
233
generate_merge_revisions = False
235
generate_merge_revisions = True
223
236
# 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.',
237
symbol_versioning.warn('LogFormatters should provide log_revision '
238
'instead of show and show_merge_revno since bzr 0.17.',
226
239
DeprecationWarning, stacklevel=3)
241
generate_merge_revisions = getattr(lf, 'supports_merge_revisions',
227
243
view_revs_iter = get_view_revisions(mainline_revs, rev_nos, branch,
228
direction, include_merges=include_merges)
244
direction, include_merges=generate_merge_revisions)
229
245
if specific_fileid:
230
246
view_revisions = _get_revisions_touching_file_id(branch,
271
289
if not searchRE.search(rev.message):
276
lf.show(revno, rev, delta, rev_tag_dict.get(rev_id))
278
lf.show(revno, rev, delta)
293
lr = LogRevision(rev, revno, merge_depth, delta,
294
rev_tag_dict.get(rev_id))
280
if show_merge_revno is None:
281
lf.show_merge(rev, merge_depth)
297
# support for legacy (pre-0.17) LogFormatters
300
lf.show(revno, rev, delta, rev_tag_dict.get(rev_id))
302
lf.show(revno, rev, delta)
284
lf.show_merge_revno(rev, merge_depth, revno,
285
rev_tag_dict.get(rev_id))
304
if show_merge_revno is None:
305
lf.show_merge(rev, merge_depth)
287
lf.show_merge_revno(rev, merge_depth, revno)
308
lf.show_merge_revno(rev, merge_depth, revno,
309
rev_tag_dict.get(rev_id))
311
lf.show_merge_revno(rev, merge_depth, revno)
290
314
def _get_revisions_touching_file_id(branch, file_id, mainline_revisions,
425
class LogRevision(object):
426
"""A revision to be logged (by LogFormatter.log_revision).
428
A simple wrapper for the attributes of a revision to be logged.
429
The attributes may or may not be populated, as determined by the
430
logging options and the log formatter capabilities.
433
def __init__(self, rev=None, revno=None, merge_depth=0, delta=None,
437
self.merge_depth = merge_depth
401
442
class LogFormatter(object):
402
"""Abstract class to display log messages."""
443
"""Abstract class to display log messages.
445
At a minimum, a derived class must implement the log_revision method.
447
If the LogFormatter needs to be informed of the beginning or end of
448
a log it should implement the begin_log and/or end_log hook methods.
450
A LogFormatter should define the following supports_XXX flags
451
to indicate which LogRevision attributes it supports:
453
- supports_delta must be True if this log formatter supports delta.
454
Otherwise the delta attribute may not be populated.
455
- supports_merge_revisions must be True if this log formatter supports
456
merge revisions. If not, only revisions mainline revisions (those
457
with merge_depth == 0) will be passed to the formatter.
458
- supports_tags must be True if this log formatter supports tags.
459
Otherwise the tags attribute may not be populated.
404
462
def __init__(self, to_file, show_ids=False, show_timezone='original'):
405
463
self.to_file = to_file
406
464
self.show_ids = show_ids
407
465
self.show_timezone = show_timezone
467
# TODO: uncomment this block after show() has been removed.
468
# Until then defining log_revision would prevent _show_log calling show()
469
# in legacy formatters.
470
# def log_revision(self, revision):
473
# :param revision: The LogRevision to be logged.
475
# raise NotImplementedError('not implemented in abstract base')
477
@deprecated_method(zero_seventeen)
409
478
def show(self, revno, rev, delta):
410
479
raise NotImplementedError('not implemented in abstract base')
416
485
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
487
supports_merge_revisions = True
488
supports_delta = True
491
@deprecated_method(zero_seventeen)
423
492
def show(self, revno, rev, delta, tags=None):
424
return self._show_helper(revno=revno, rev=rev, delta=delta, tags=tags)
493
lr = LogRevision(rev, revno, 0, delta, tags)
494
return self.log_revision(lr)
426
496
@deprecated_method(zero_eleven)
427
497
def show_merge(self, rev, merge_depth):
428
return self._show_helper(rev=rev, indent=' '*merge_depth,
429
merged=True, delta=None)
498
lr = LogRevision(rev, merge_depth=merge_depth)
499
return self.log_revision(lr)
501
@deprecated_method(zero_seventeen)
431
502
def show_merge_revno(self, rev, merge_depth, revno, tags=None):
432
503
"""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)
504
lr = LogRevision(rev, revno, merge_depth, tags=tags)
505
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."""
507
def log_revision(self, revision):
508
"""Log a revision, either merged or not."""
439
509
from bzrlib.osutils import format_date
510
indent = ' '*revision.merge_depth
440
511
to_file = self.to_file
441
512
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
513
if revision.revno is not None:
514
print >>to_file, indent+'revno:', revision.revno
516
print >>to_file, indent+'tags: %s' % (', '.join(revision.tags))
450
517
if self.show_ids:
451
for parent_id in rev.parent_ids:
518
print >>to_file, indent+'revision-id:', revision.rev.revision_id
519
for parent_id in revision.rev.parent_ids:
452
520
print >>to_file, indent+'parent:', parent_id
453
print >>to_file, indent+'committer:', rev.committer
521
print >>to_file, indent+'committer:', revision.rev.committer
456
524
print >>to_file, indent+'branch nick: %s' % \
457
rev.properties['branch-nick']
525
revision.rev.properties['branch-nick']
460
date_str = format_date(rev.timestamp,
528
date_str = format_date(revision.rev.timestamp,
529
revision.rev.timezone or 0,
462
530
self.show_timezone)
463
531
print >>to_file, indent+'timestamp: %s' % date_str
465
533
print >>to_file, indent+'message:'
534
if not revision.rev.message:
467
535
print >>to_file, indent+' (no message)'
469
message = rev.message.rstrip('\r\n')
537
message = revision.rev.message.rstrip('\r\n')
470
538
for l in message.split('\n'):
471
539
print >>to_file, indent+' ' + l
472
if delta is not None:
473
delta.show(to_file, self.show_ids)
540
if revision.delta is not None:
541
revision.delta.show(to_file, self.show_ids)
476
544
class ShortLogFormatter(LogFormatter):
546
supports_delta = True
548
@deprecated_method(zero_seventeen)
477
549
def show(self, revno, rev, delta):
550
lr = LogRevision(rev, revno, 0, delta)
551
return self.log_revision(lr)
553
def log_revision(self, revision):
478
554
from bzrlib.osutils import format_date
480
556
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,
557
date_str = format_date(revision.rev.timestamp,
558
revision.rev.timezone or 0,
560
print >>to_file, "%5s %s\t%s" % (revision.revno,
561
self.short_committer(revision.rev),
562
format_date(revision.rev.timestamp,
563
revision.rev.timezone or 0,
485
564
self.show_timezone, date_fmt="%Y-%m-%d",
487
566
if self.show_ids:
488
print >>to_file, ' revision-id:', rev.revision_id
567
print >>to_file, ' revision-id:', revision.rev.revision_id
568
if not revision.rev.message:
490
569
print >>to_file, ' (no message)'
492
message = rev.message.rstrip('\r\n')
571
message = revision.rev.message.rstrip('\r\n')
493
572
for l in message.split('\n'):
494
573
print >>to_file, ' ' + l
496
575
# TODO: Why not show the modified files in a shorter form as
497
576
# well? rewrap them single lines of appropriate length
498
if delta is not None:
499
delta.show(to_file, self.show_ids)
577
if revision.delta is not None:
578
revision.delta.show(to_file, self.show_ids)
500
579
print >>to_file, ''
503
582
class LineLogFormatter(LogFormatter):
584
def __init__(self, *args, **kwargs):
585
from bzrlib.osutils import terminal_width
586
super(LineLogFormatter, self).__init__(*args, **kwargs)
587
self._max_chars = terminal_width() - 1
504
589
def truncate(self, str, max_len):
505
590
if len(str) <= max_len: