346
294
def show(self, revno, rev, delta):
347
295
raise NotImplementedError('not implemented in abstract base')
349
def short_committer(self, rev):
350
return re.sub('<.*@.*>', '', rev.committer).strip(' ')
353
302
class LongLogFormatter(LogFormatter):
354
303
def show(self, revno, rev, delta):
355
return self._show_helper(revno=revno, rev=rev, delta=delta)
357
def show_merge(self, rev):
358
return self._show_helper(rev=rev, indent=' ', merged=True, delta=None)
360
def _show_helper(self, rev=None, revno=None, indent='', merged=False, delta=None):
361
"""Show a revision, either merged or not."""
362
from bzrlib.osutils import format_date
304
from osutils import format_date
363
306
to_file = self.to_file
364
print >>to_file, indent+'-' * 60
365
if revno is not None:
366
print >>to_file, 'revno:', revno
368
print >>to_file, indent+'merged:', rev.revision_id
370
print >>to_file, indent+'revision-id:', rev.revision_id
308
print >>to_file, '-' * 60
309
print >>to_file, 'revno:', revno
371
310
if self.show_ids:
372
for parent_id in rev.parent_ids:
373
print >>to_file, indent+'parent:', parent_id
374
print >>to_file, indent+'committer:', rev.committer
376
print >>to_file, indent+'branch nick: %s' % \
377
rev.properties['branch-nick']
311
print >>to_file, 'revision-id:', rev.revision_id
313
for parent in rev.parents:
314
print >>to_file, 'parent:', parent.revision_id
316
print >>to_file, 'committer:', rev.committer
380
318
date_str = format_date(rev.timestamp,
381
319
rev.timezone or 0,
382
320
self.show_timezone)
383
print >>to_file, indent+'timestamp: %s' % date_str
321
print >>to_file, 'timestamp: %s' % date_str
385
print >>to_file, indent+'message:'
323
print >>to_file, 'message:'
386
324
if not rev.message:
387
print >>to_file, indent+' (no message)'
325
print >>to_file, ' (no message)'
389
message = rev.message.rstrip('\r\n')
390
for l in message.split('\n'):
391
print >>to_file, indent+' ' + l
327
for l in rev.message.split('\n'):
328
print >>to_file, ' ' + l
392
330
if delta != None:
393
331
delta.show(to_file, self.show_ids)
396
335
class ShortLogFormatter(LogFormatter):
397
336
def show(self, revno, rev, delta):
398
337
from bzrlib.osutils import format_date
400
339
to_file = self.to_file
401
date_str = format_date(rev.timestamp, rev.timezone or 0,
403
print >>to_file, "%5d %s\t%s" % (revno, self.short_committer(rev),
341
print >>to_file, "%5d %s\t%s" % (revno, rev.committer,
404
342
format_date(rev.timestamp, rev.timezone or 0,
405
self.show_timezone, date_fmt="%Y-%m-%d",
407
344
if self.show_ids:
408
345
print >>to_file, ' revision-id:', rev.revision_id
409
346
if not rev.message:
410
347
print >>to_file, ' (no message)'
412
message = rev.message.rstrip('\r\n')
413
for l in message.split('\n'):
349
for l in rev.message.split('\n'):
414
350
print >>to_file, ' ' + l
416
352
# TODO: Why not show the modified files in a shorter form as
417
353
# well? rewrap them single lines of appropriate length
418
354
if delta != None:
419
355
delta.show(to_file, self.show_ids)
422
class LineLogFormatter(LogFormatter):
423
def truncate(self, str, max_len):
424
if len(str) <= max_len:
426
return str[:max_len-3]+'...'
428
def date_string(self, rev):
429
from bzrlib.osutils import format_date
430
return format_date(rev.timestamp, rev.timezone or 0,
431
self.show_timezone, date_fmt="%Y-%m-%d",
434
def message(self, rev):
436
return '(no message)'
440
def show(self, revno, rev, delta):
441
print >> self.to_file, self.log_string(rev, 79)
443
def log_string(self, rev, max_chars):
444
out = [self.truncate(self.short_committer(rev), 20)]
445
out.append(self.date_string(rev))
446
out.append(self.message(rev).replace('\n', ' '))
447
return self.truncate(" ".join(out).rstrip('\n'), max_chars)
449
def line_log(rev, max_chars):
450
lf = LineLogFormatter(None)
451
return lf.log_string(rev, max_chars)
453
360
FORMATTERS = {'long': LongLogFormatter,
454
361
'short': ShortLogFormatter,
455
'line': LineLogFormatter,
459
365
def log_formatter(name, *args, **kwargs):
460
"""Construct a formatter from arguments.
462
name -- Name of the formatter to construct; currently 'long', 'short' and
463
'line' are supported.
465
366
from bzrlib.errors import BzrCommandError
467
369
return FORMATTERS[name](*args, **kwargs)
468
370
except IndexError:
472
374
# deprecated; for compatability
473
375
lf = LongLogFormatter(to_file=to_file, show_timezone=show_timezone)
474
376
lf.show(revno, rev, delta)
476
def show_changed_revisions(branch, old_rh, new_rh, to_file=None, log_format='long'):
477
"""Show the change in revision history comparing the old revision history to the new one.
479
:param branch: The branch where the revisions exist
480
:param old_rh: The old revision history
481
:param new_rh: The new revision history
482
:param to_file: A file to write the results to. If None, stdout will be used
488
to_file = codecs.getwriter(bzrlib.user_encoding)(sys.stdout, errors='replace')
489
lf = log_formatter(log_format,
492
show_timezone='original')
494
# This is the first index which is different between
497
for i in xrange(max(len(new_rh),
501
or new_rh[i] != old_rh[i]):
506
to_file.write('Nothing seems to have changed\n')
508
## TODO: It might be nice to do something like show_log
509
## and show the merged entries. But since this is the
510
## removed revisions, it shouldn't be as important
511
if base_idx < len(old_rh):
512
to_file.write('*'*60)
513
to_file.write('\nRemoved Revisions:\n')
514
for i in range(base_idx, len(old_rh)):
515
rev = branch.repository.get_revision(old_rh[i])
516
lf.show(i+1, rev, None)
517
to_file.write('*'*60)
518
to_file.write('\n\n')
519
if base_idx < len(new_rh):
520
to_file.write('Added Revisions:\n')
526
start_revision=base_idx+1,
527
end_revision=len(new_rh),