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