114
def _get_revision_delta(branch, revno):
115
"""Return the delta for a mainline revision.
117
This is used to show summaries in verbose logs, and also for finding
118
revisions which touch a given file."""
119
# XXX: What are we supposed to do when showing a summary for something
120
# other than a mainline revision. The delta to it's first parent, or
121
# (more useful) the delta to a nominated other revision.
122
return branch.get_revision_delta(revno)
112
125
def show_log(branch,
114
127
specific_fileid=None,
140
153
If not None, only show revisions <= end_revision
157
_show_log(branch, lf, specific_fileid, verbose, direction,
158
start_revision, end_revision, search)
162
def _show_log(branch,
164
specific_fileid=None,
170
"""Worker function for show_log - see show_log."""
142
171
from bzrlib.osutils import format_date
143
172
from bzrlib.errors import BzrCheckError
144
173
from bzrlib.textui import show_status
200
230
lf.show(revno, rev, delta)
231
if hasattr(lf, 'show_merge'):
235
# revno is 1 based, so -2 to get back 1 less.
236
excludes = set(branch.get_ancestry(revision_history[revno - 2]))
237
pending = list(rev.parent_ids)
239
rev_id = pending.pop()
240
if rev_id in excludes:
242
# prevent showing merged revs twice if they multi-path.
245
rev = branch.get_revision(rev_id)
246
except errors.NoSuchRevision:
248
pending.extend(rev.parent_ids)
204
252
def deltas_for_log_dummy(branch, which_revs):
294
342
def show(self, revno, rev, delta):
295
343
raise NotImplementedError('not implemented in abstract base')
345
def short_committer(self, rev):
346
return re.sub('<.*@.*>', '', rev.committer).strip(' ')
302
349
class LongLogFormatter(LogFormatter):
303
350
def show(self, revno, rev, delta):
351
return self._show_helper(revno=revno, rev=rev)
353
def show_merge(self, rev):
354
return self._show_helper(rev=rev, indent=' ', merged=True)
356
def _show_helper(self, rev=None, revno=None, indent='', merged=False):
304
357
from osutils import format_date
306
359
to_file = self.to_file
308
print >>to_file, '-' * 60
309
print >>to_file, 'revno:', revno
362
print >>to_file, indent+'-' * 60
363
if revno is not None:
364
print >>to_file, 'revno:', revno
366
print >>to_file, indent+'merged:', rev.revision_id
368
print >>to_file, indent+'revision-id:', rev.revision_id
310
369
if self.show_ids:
311
print >>to_file, 'revision-id:', rev.revision_id
313
for parent in rev.parents:
314
print >>to_file, 'parent:', parent.revision_id
370
for parent_id in rev.parent_ids:
371
print >>to_file, indent+'parent:', parent_id
316
print >>to_file, 'committer:', rev.committer
373
print >>to_file, indent+'committer:', rev.committer
375
print >>to_file, indent+'branch nick: %s' % \
376
rev.properties['branch-nick']
318
380
date_str = format_date(rev.timestamp,
319
381
rev.timezone or 0,
320
382
self.show_timezone)
321
print >>to_file, 'timestamp: %s' % date_str
383
print >>to_file, indent+'timestamp: %s' % date_str
323
print >>to_file, 'message:'
385
print >>to_file, indent+'message:'
324
386
if not rev.message:
325
print >>to_file, ' (no message)'
387
print >>to_file, indent+' (no message)'
327
389
for l in rev.message.split('\n'):
328
print >>to_file, ' ' + l
331
delta.show(to_file, self.show_ids)
390
print >>to_file, indent+' ' + l
335
393
class ShortLogFormatter(LogFormatter):
337
395
from bzrlib.osutils import format_date
339
397
to_file = self.to_file
341
print >>to_file, "%5d %s\t%s" % (revno, rev.committer,
398
date_str = format_date(rev.timestamp, rev.timezone or 0,
400
print >>to_file, "%5d %s\t%s" % (revno, self.short_committer(rev),
342
401
format_date(rev.timestamp, rev.timezone or 0,
402
self.show_timezone, date_fmt="%Y-%m-%d",
344
404
if self.show_ids:
345
405
print >>to_file, ' revision-id:', rev.revision_id
346
406
if not rev.message:
355
415
delta.show(to_file, self.show_ids)
418
class LineLogFormatter(LogFormatter):
419
def truncate(self, str, max_len):
420
if len(str) <= max_len:
422
return str[:max_len-3]+'...'
424
def date_string(self, rev):
425
from bzrlib.osutils import format_date
426
return format_date(rev.timestamp, rev.timezone or 0,
427
self.show_timezone, date_fmt="%Y-%m-%d",
430
def message(self, rev):
432
return '(no message)'
436
def show(self, revno, rev, delta):
437
print >> self.to_file, self.log_string(rev, 79)
439
def log_string(self, rev, max_chars):
440
out = [self.truncate(self.short_committer(rev), 20)]
441
out.append(self.date_string(rev))
442
out.append(self.message(rev).replace('\n', ' '))
443
return self.truncate(" ".join(out).rstrip('\n'), max_chars)
445
def line_log(rev, max_chars):
446
lf = LineLogFormatter(None)
447
return lf.log_string(rev, max_chars)
360
449
FORMATTERS = {'long': LongLogFormatter,
361
450
'short': ShortLogFormatter,
451
'line': LineLogFormatter,
365
455
def log_formatter(name, *args, **kwargs):
456
"""Construct a formatter from arguments.
458
name -- Name of the formatter to construct; currently 'long', 'short' and
459
'line' are supported.
366
461
from bzrlib.errors import BzrCommandError
369
463
return FORMATTERS[name](*args, **kwargs)
370
464
except IndexError:
374
468
# deprecated; for compatability
375
469
lf = LongLogFormatter(to_file=to_file, show_timezone=show_timezone)
376
470
lf.show(revno, rev, delta)
472
def show_changed_revisions(branch, old_rh, new_rh, to_file=None, log_format='long'):
473
"""Show the change in revision history comparing the old revision history to the new one.
475
:param branch: The branch where the revisions exist
476
:param old_rh: The old revision history
477
:param new_rh: The new revision history
478
:param to_file: A file to write the results to. If None, stdout will be used
484
to_file = codecs.getwriter(bzrlib.user_encoding)(sys.stdout, errors='replace')
485
lf = log_formatter(log_format,
488
show_timezone='original')
490
# This is the first index which is different between
493
for i in xrange(max(len(new_rh),
497
or new_rh[i] != old_rh[i]):
502
to_file.write('Nothing seems to have changed\n')
504
## TODO: It might be nice to do something like show_log
505
## and show the merged entries. But since this is the
506
## removed revisions, it shouldn't be as important
507
if base_idx < len(old_rh):
508
to_file.write('*'*60)
509
to_file.write('\nRemoved Revisions:\n')
510
for i in range(base_idx, len(old_rh)):
511
rev = branch.get_revision(old_rh[i])
512
lf.show(i+1, rev, None)
513
to_file.write('*'*60)
514
to_file.write('\n\n')
515
if base_idx < len(new_rh):
516
to_file.write('Added Revisions:\n')
522
start_revision=base_idx+1,
523
end_revision=len(new_rh),