~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/log.py

Added more docs

Show diffs side-by-side

added added

removed removed

Lines of Context:
51
51
 
52
52
 
53
53
# TODO: option to show delta summaries for merged-in revisions
54
 
import re
55
54
 
 
55
import bzrlib.errors as errors
 
56
from bzrlib.tree import EmptyTree
56
57
from bzrlib.delta import compare_trees
57
 
import bzrlib.errors as errors
58
58
from bzrlib.trace import mutter
59
 
from bzrlib.tree import EmptyTree
60
 
from bzrlib.tsort import merge_sort
 
59
import re
61
60
 
62
61
 
63
62
def find_touching_revisions(branch, file_id):
203
202
 
204
203
    # list indexes are 0-based; revisions are 1-based
205
204
    cut_revs = which_revs[(start_revision-1):(end_revision)]
206
 
    if not cut_revs:
207
 
        return
208
 
    # override the mainline to look like the revision history.
209
 
    mainline_revs = [revision_id for index, revision_id in cut_revs]
210
 
    if cut_revs[0][0] == 1:
211
 
        mainline_revs.insert(0, None)
212
 
    else:
213
 
        mainline_revs.insert(0, which_revs[start_revision-2][1])
214
 
 
215
 
    merge_sorted_revisions = merge_sort(
216
 
        branch.repository.get_revision_graph(mainline_revs[-1]),
217
 
        mainline_revs[-1],
218
 
        mainline_revs)
219
205
 
220
206
    if direction == 'reverse':
221
207
        cut_revs.reverse()
222
208
    elif direction == 'forward':
223
 
        # forward means oldest first.
224
 
        merge_sorted_revisions.reverse()
 
209
        pass
225
210
    else:
226
211
        raise ValueError('invalid direction %r' % direction)
227
212
 
228
213
    revision_history = branch.revision_history()
229
 
 
230
 
    # convert the revision history to a dictionary:
231
 
    rev_nos = {}
232
 
    for index, rev_id in cut_revs:
233
 
        rev_nos[rev_id] = index
234
 
 
235
 
    # now we just print all the revisions
236
 
    for sequence, rev_id, merge_depth, end_of_merge in merge_sorted_revisions:
 
214
    for revno, rev_id in cut_revs:
 
215
        if verbose or specific_fileid:
 
216
            delta = _get_revision_delta(branch, revno)
 
217
            
 
218
        if specific_fileid:
 
219
            if not delta.touches_file_id(specific_fileid):
 
220
                continue
 
221
 
 
222
        if not verbose:
 
223
            # although we calculated it, throw it away without display
 
224
            delta = None
 
225
 
237
226
        rev = branch.repository.get_revision(rev_id)
238
227
 
239
228
        if searchRE:
240
229
            if not searchRE.search(rev.message):
241
230
                continue
242
231
 
243
 
        if merge_depth == 0:
244
 
            # a mainline revision.
245
 
            if verbose or specific_fileid:
246
 
                delta = _get_revision_delta(branch, rev_nos[rev_id])
247
 
                
248
 
            if specific_fileid:
249
 
                if not delta.touches_file_id(specific_fileid):
250
 
                    continue
251
 
    
252
 
            if not verbose:
253
 
                # although we calculated it, throw it away without display
254
 
                delta = None
255
 
 
256
 
            lf.show(rev_nos[rev_id], rev, delta)
257
 
        elif hasattr(lf, 'show_merge'):
258
 
            lf.show_merge(rev, merge_depth)
 
232
        lf.show(revno, rev, delta)
 
233
        if hasattr(lf, 'show_merge'):
 
234
            if revno == 1:
 
235
                excludes = set()
 
236
            else:
 
237
                # revno is 1 based, so -2 to get back 1 less.
 
238
                repository = branch.repository
 
239
                excludes = repository.get_ancestry(revision_history[revno - 2])
 
240
                excludes = set(excludes)
 
241
            pending = list(rev.parent_ids)
 
242
            while pending:
 
243
                rev_id = pending.pop()
 
244
                if rev_id in excludes:
 
245
                    continue
 
246
                # prevent showing merged revs twice if they multi-path.
 
247
                excludes.add(rev_id)
 
248
                try:
 
249
                    rev = branch.repository.get_revision(rev_id)
 
250
                except errors.NoSuchRevision:
 
251
                    continue
 
252
                pending.extend(rev.parent_ids)
 
253
                lf.show_merge(rev)
259
254
 
260
255
 
261
256
def deltas_for_log_dummy(branch, which_revs):
342
337
 
343
338
class LogFormatter(object):
344
339
    """Abstract class to display log messages."""
345
 
 
346
340
    def __init__(self, to_file, show_ids=False, show_timezone='original'):
347
341
        self.to_file = to_file
348
342
        self.show_ids = show_ids
349
343
        self.show_timezone = show_timezone
350
344
 
 
345
 
351
346
    def show(self, revno, rev, delta):
352
347
        raise NotImplementedError('not implemented in abstract base')
353
348
 
359
354
    def show(self, revno, rev, delta):
360
355
        return self._show_helper(revno=revno, rev=rev, delta=delta)
361
356
 
362
 
    def show_merge(self, rev, merge_depth):
363
 
        return self._show_helper(rev=rev, indent='    '*merge_depth, merged=True, delta=None)
 
357
    def show_merge(self, rev):
 
358
        return self._show_helper(rev=rev, indent='    ', merged=True, delta=None)
364
359
 
365
360
    def _show_helper(self, rev=None, revno=None, indent='', merged=False, delta=None):
366
 
        """Show a revision, either merged or not."""
 
361
        """Show a revision, either merged or not."""
367
362
        from bzrlib.osutils import format_date
368
363
        to_file = self.to_file
369
364
        print >>to_file,  indent+'-' * 60
424
419
            delta.show(to_file, self.show_ids)
425
420
        print >>to_file, ''
426
421
 
427
 
 
428
422
class LineLogFormatter(LogFormatter):
429
423
    def truncate(self, str, max_len):
430
424
        if len(str) <= max_len:
444
438
            return rev.message
445
439
 
446
440
    def show(self, revno, rev, delta):
447
 
        from bzrlib.osutils import terminal_width
448
 
        print >> self.to_file, self.log_string(revno, rev, terminal_width()-1)
 
441
        print >> self.to_file, self.log_string(rev, 79) 
449
442
 
450
 
    def log_string(self, revno, rev, max_chars):
451
 
        """Format log info into one string. Truncate tail of string
452
 
        :param  revno:      revision number (int) or None.
453
 
                            Revision numbers counts from 1.
454
 
        :param  rev:        revision info object
455
 
        :param  max_chars:  maximum length of resulting string
456
 
        :return:            formatted truncated string
457
 
        """
458
 
        out = []
459
 
        if revno:
460
 
            # show revno only when is not None
461
 
            out.append("%d:" % revno)
462
 
        out.append(self.truncate(self.short_committer(rev), 20))
 
443
    def log_string(self, rev, max_chars):
 
444
        out = [self.truncate(self.short_committer(rev), 20)]
463
445
        out.append(self.date_string(rev))
464
446
        out.append(self.message(rev).replace('\n', ' '))
465
447
        return self.truncate(" ".join(out).rstrip('\n'), max_chars)
466
448
 
467
 
 
468
449
def line_log(rev, max_chars):
469
450
    lf = LineLogFormatter(None)
470
 
    return lf.log_string(None, rev, max_chars)
 
451
    return lf.log_string(rev, max_chars)
471
452
 
472
 
FORMATTERS = {
473
 
              'long': LongLogFormatter,
 
453
FORMATTERS = {'long': LongLogFormatter,
474
454
              'short': ShortLogFormatter,
475
455
              'line': LineLogFormatter,
476
456
              }
477
457
 
478
 
def register_formatter(name, formatter):
479
 
    FORMATTERS[name] = formatter
480
458
 
481
459
def log_formatter(name, *args, **kwargs):
482
460
    """Construct a formatter from arguments.
487
465
    from bzrlib.errors import BzrCommandError
488
466
    try:
489
467
        return FORMATTERS[name](*args, **kwargs)
490
 
    except KeyError:
 
468
    except IndexError:
491
469
        raise BzrCommandError("unknown log formatter: %r" % name)
492
470
 
493
471
def show_one_log(revno, rev, delta, verbose, to_file, show_timezone):