53
import bzrlib.errors as errors
53
54
from bzrlib.tree import EmptyTree
54
55
from bzrlib.delta import compare_trees
55
56
from bzrlib.trace import mutter
58
60
def find_touching_revisions(branch, file_id):
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
180
209
raise ValueError('invalid direction %r' % direction)
211
revision_history = branch.revision_history()
182
212
for revno, rev_id in cut_revs:
183
213
if verbose or specific_fileid:
184
delta = branch.get_revision_delta(revno)
214
delta = _get_revision_delta(branch, revno)
186
216
if specific_fileid:
187
217
if not delta.touches_file_id(specific_fileid):
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')
302
346
class LongLogFormatter(LogFormatter):
303
347
def show(self, revno, rev, delta):
304
348
from osutils import format_date
310
354
if self.show_ids:
311
355
print >>to_file, 'revision-id:', rev.revision_id
313
for parent in rev.parents:
314
print >>to_file, 'parent:', parent.revision_id
357
for parent_id in rev.parent_ids:
358
print >>to_file, 'parent:', parent_id
316
360
print >>to_file, 'committer:', rev.committer
330
374
if delta != None:
331
375
delta.show(to_file, self.show_ids)
377
def show_merge(self, rev):
378
from osutils import format_date
380
to_file = self.to_file
384
print >>to_file, indent+'-' * 60
385
print >>to_file, indent+'merged:', rev.revision_id
387
for parent_id in rev.parent_ids:
388
print >>to_file, indent+'parent:', parent_id
390
print >>to_file, indent+'committer:', rev.committer
392
date_str = format_date(rev.timestamp,
395
print >>to_file, indent+'timestamp: %s' % date_str
397
print >>to_file, indent+'message:'
399
print >>to_file, indent+' (no message)'
401
for l in rev.message.split('\n'):
402
print >>to_file, indent+' ' + l
335
405
class ShortLogFormatter(LogFormatter):
337
407
from bzrlib.osutils import format_date
339
409
to_file = self.to_file
410
date_str = format_date(rev.timestamp, rev.timezone or 0,
341
412
print >>to_file, "%5d %s\t%s" % (revno, rev.committer,
342
413
format_date(rev.timestamp, rev.timezone or 0,
343
414
self.show_timezone))
355
426
delta.show(to_file, self.show_ids)
429
class LineLogFormatter(LogFormatter):
430
def truncate(self, str, max_len):
431
if len(str) <= max_len:
433
return str[:max_len-3]+'...'
435
def date_string(self, rev):
436
from bzrlib.osutils import format_date
437
return format_date(rev.timestamp, rev.timezone or 0,
438
self.show_timezone, date_fmt="%Y-%m-%d",
441
def message(self, rev):
443
return '(no message)'
447
def short_committer(self, rev):
448
return re.sub('<.*@.*>', '', rev.committer).strip(' ')
450
def show(self, revno, rev, delta):
451
print >> self.to_file, self.log_string(rev, 79)
453
def log_string(self, rev, max_chars):
454
out = [self.truncate(self.short_committer(rev), 20)]
455
out.append(self.date_string(rev))
456
out.append(self.message(rev).replace('\n', ' '))
457
return self.truncate(" ".join(out).rstrip('\n'), max_chars)
459
def line_log(rev, max_chars):
460
lf = LineLogFormatter(None)
461
return lf.log_string(rev, max_chars)
360
463
FORMATTERS = {'long': LongLogFormatter,
361
464
'short': ShortLogFormatter,
465
'line': LineLogFormatter,
365
469
def log_formatter(name, *args, **kwargs):
470
"""Construct a formatter from arguments.
472
name -- Name of the formatter to construct; currently 'long', 'short' and
473
'line' are supported.
366
475
from bzrlib.errors import BzrCommandError
369
477
return FORMATTERS[name](*args, **kwargs)
370
478
except IndexError: