~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/log.py

  • Committer: Robert Collins
  • Date: 2005-10-11 07:21:00 UTC
  • mto: This revision was merged to the branch mainline in revision 1443.
  • Revision ID: robertc@robertcollins.net-20051011072100-16996b55c43ff24f
move editor into the config file too

Show diffs side-by-side

added added

removed removed

Lines of Context:
50
50
"""
51
51
 
52
52
 
53
 
# TODO: option to show delta summaries for merged-in revisions
54
 
 
55
53
import bzrlib.errors as errors
56
54
from bzrlib.tree import EmptyTree
57
55
from bzrlib.delta import compare_trees
58
56
from bzrlib.trace import mutter
59
 
import re
60
57
 
61
58
 
62
59
def find_touching_revisions(branch, file_id):
74
71
    last_path = None
75
72
    revno = 1
76
73
    for revision_id in branch.revision_history():
77
 
        this_inv = branch.repository.get_revision_inventory(revision_id)
 
74
        this_inv = branch.get_revision_inventory(revision_id)
78
75
        if file_id in this_inv:
79
76
            this_ie = this_inv[file_id]
80
77
            this_path = this_inv.id2path(file_id)
180
177
        warn("not a LogFormatter instance: %r" % lf)
181
178
 
182
179
    if specific_fileid:
183
 
        mutter('get log for file_id %r', specific_fileid)
 
180
        mutter('get log for file_id %r' % specific_fileid)
184
181
 
185
182
    if search is not None:
186
183
        import re
223
220
            # although we calculated it, throw it away without display
224
221
            delta = None
225
222
 
226
 
        rev = branch.repository.get_revision(rev_id)
 
223
        rev = branch.get_revision(rev_id)
227
224
 
228
225
        if searchRE:
229
226
            if not searchRE.search(rev.message):
230
227
                continue
231
228
 
232
229
        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)
 
230
        if revno == 1:
 
231
            excludes = set()
 
232
        else:
 
233
            # revno is 1 based, so -2 to get back 1 less.
 
234
            excludes = set(branch.get_ancestry(revision_history[revno - 2]))
 
235
        pending = list(rev.parent_ids)
 
236
        while pending:
 
237
            rev_id = pending.pop()
 
238
            if rev_id in excludes:
 
239
                continue
 
240
            # prevent showing merged revs twice if they multi-path.
 
241
            excludes.add(rev_id)
 
242
            try:
 
243
                rev = branch.get_revision(rev_id)
 
244
            except errors.NoSuchRevision:
 
245
                continue
 
246
            pending.extend(rev.parent_ids)
 
247
            lf.show_merge(rev)
254
248
 
255
249
 
256
250
def deltas_for_log_dummy(branch, which_revs):
346
340
    def show(self, revno, rev, delta):
347
341
        raise NotImplementedError('not implemented in abstract base')
348
342
 
349
 
    def short_committer(self, rev):
350
 
        return re.sub('<.*@.*>', '', rev.committer).strip(' ')
351
 
    
 
343
    def show_merge(self, rev):
 
344
        pass
 
345
 
352
346
    
353
347
class LongLogFormatter(LogFormatter):
354
348
    def show(self, revno, rev, delta):
355
 
        return self._show_helper(revno=revno, rev=rev, delta=delta)
 
349
        from osutils import format_date
 
350
 
 
351
        to_file = self.to_file
 
352
 
 
353
        print >>to_file,  '-' * 60
 
354
        print >>to_file,  'revno:', revno
 
355
        if self.show_ids:
 
356
            print >>to_file,  'revision-id:', rev.revision_id
 
357
 
 
358
            for parent_id in rev.parent_ids:
 
359
                print >>to_file, 'parent:', parent_id
 
360
            
 
361
        print >>to_file,  'committer:', rev.committer
 
362
 
 
363
        date_str = format_date(rev.timestamp,
 
364
                               rev.timezone or 0,
 
365
                               self.show_timezone)
 
366
        print >>to_file,  'timestamp: %s' % date_str
 
367
 
 
368
        print >>to_file,  'message:'
 
369
        if not rev.message:
 
370
            print >>to_file,  '  (no message)'
 
371
        else:
 
372
            for l in rev.message.split('\n'):
 
373
                print >>to_file,  '  ' + l
 
374
 
 
375
        if delta != None:
 
376
            delta.show(to_file, self.show_ids)
356
377
 
357
378
    def show_merge(self, rev):
358
 
        return self._show_helper(rev=rev, indent='    ', merged=True, delta=None)
 
379
        from osutils import format_date
359
380
 
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
363
381
        to_file = self.to_file
 
382
 
 
383
        indent = '    '
 
384
 
364
385
        print >>to_file,  indent+'-' * 60
365
 
        if revno is not None:
366
 
            print >>to_file,  'revno:', revno
367
 
        if merged:
368
 
            print >>to_file,  indent+'merged:', rev.revision_id
369
 
        elif self.show_ids:
370
 
            print >>to_file,  indent+'revision-id:', rev.revision_id
 
386
        print >>to_file,  indent+'merged:', rev.revision_id
371
387
        if self.show_ids:
372
388
            for parent_id in rev.parent_ids:
373
389
                print >>to_file, indent+'parent:', parent_id
 
390
            
374
391
        print >>to_file,  indent+'committer:', rev.committer
375
 
        try:
376
 
            print >>to_file, indent+'branch nick: %s' % \
377
 
                rev.properties['branch-nick']
378
 
        except KeyError:
379
 
            pass
 
392
 
380
393
        date_str = format_date(rev.timestamp,
381
394
                               rev.timezone or 0,
382
395
                               self.show_timezone)
386
399
        if not rev.message:
387
400
            print >>to_file,  indent+'  (no message)'
388
401
        else:
389
 
            message = rev.message.rstrip('\r\n')
390
 
            for l in message.split('\n'):
 
402
            for l in rev.message.split('\n'):
391
403
                print >>to_file,  indent+'  ' + l
392
 
        if delta != None:
393
 
            delta.show(to_file, self.show_ids)
394
404
 
395
405
 
396
406
class ShortLogFormatter(LogFormatter):
398
408
        from bzrlib.osutils import format_date
399
409
 
400
410
        to_file = self.to_file
401
 
        date_str = format_date(rev.timestamp, rev.timezone or 0,
402
 
                            self.show_timezone)
403
 
        print >>to_file, "%5d %s\t%s" % (revno, self.short_committer(rev),
 
411
 
 
412
        print >>to_file, "%5d %s\t%s" % (revno, rev.committer,
404
413
                format_date(rev.timestamp, rev.timezone or 0,
405
 
                            self.show_timezone, date_fmt="%Y-%m-%d",
406
 
                           show_offset=False))
 
414
                            self.show_timezone))
407
415
        if self.show_ids:
408
416
            print >>to_file,  '      revision-id:', rev.revision_id
409
417
        if not rev.message:
410
418
            print >>to_file,  '      (no message)'
411
419
        else:
412
 
            message = rev.message.rstrip('\r\n')
413
 
            for l in message.split('\n'):
 
420
            for l in rev.message.split('\n'):
414
421
                print >>to_file,  '      ' + l
415
422
 
416
423
        # TODO: Why not show the modified files in a shorter form as
417
424
        # well? rewrap them single lines of appropriate length
418
425
        if delta != None:
419
426
            delta.show(to_file, self.show_ids)
420
 
        print >>to_file, ''
421
 
 
422
 
class LineLogFormatter(LogFormatter):
423
 
    def truncate(self, str, max_len):
424
 
        if len(str) <= max_len:
425
 
            return str
426
 
        return str[:max_len-3]+'...'
427
 
 
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",
432
 
                           show_offset=False)
433
 
 
434
 
    def message(self, rev):
435
 
        if not rev.message:
436
 
            return '(no message)'
437
 
        else:
438
 
            return rev.message
439
 
 
440
 
    def show(self, revno, rev, delta):
441
 
        print >> self.to_file, self.log_string(rev, 79) 
442
 
 
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)
448
 
 
449
 
def line_log(rev, max_chars):
450
 
    lf = LineLogFormatter(None)
451
 
    return lf.log_string(rev, max_chars)
 
427
        print
 
428
 
 
429
 
452
430
 
453
431
FORMATTERS = {'long': LongLogFormatter,
454
432
              'short': ShortLogFormatter,
455
 
              'line': LineLogFormatter,
456
433
              }
457
434
 
458
435
 
459
436
def log_formatter(name, *args, **kwargs):
460
437
    """Construct a formatter from arguments.
461
438
 
462
 
    name -- Name of the formatter to construct; currently 'long', 'short' and
463
 
        'line' are supported.
 
439
    name -- Name of the formatter to construct; currently 'long' and
 
440
        'short' are supported.
464
441
    """
465
442
    from bzrlib.errors import BzrCommandError
466
443
    try:
472
449
    # deprecated; for compatability
473
450
    lf = LongLogFormatter(to_file=to_file, show_timezone=show_timezone)
474
451
    lf.show(revno, rev, delta)
475
 
 
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.
478
 
 
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
483
 
    """
484
 
    if to_file is None:
485
 
        import sys
486
 
        import codecs
487
 
        import bzrlib
488
 
        to_file = codecs.getwriter(bzrlib.user_encoding)(sys.stdout, errors='replace')
489
 
    lf = log_formatter(log_format,
490
 
                       show_ids=False,
491
 
                       to_file=to_file,
492
 
                       show_timezone='original')
493
 
 
494
 
    # This is the first index which is different between
495
 
    # old and new
496
 
    base_idx = None
497
 
    for i in xrange(max(len(new_rh),
498
 
                        len(old_rh))):
499
 
        if (len(new_rh) <= i
500
 
            or len(old_rh) <= i
501
 
            or new_rh[i] != old_rh[i]):
502
 
            base_idx = i
503
 
            break
504
 
 
505
 
    if base_idx is None:
506
 
        to_file.write('Nothing seems to have changed\n')
507
 
        return
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')
521
 
        show_log(branch,
522
 
                 lf,
523
 
                 None,
524
 
                 verbose=True,
525
 
                 direction='forward',
526
 
                 start_revision=base_idx+1,
527
 
                 end_revision=len(new_rh),
528
 
                 search=None)
529