~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/log.py

  • Committer: Martin Pool
  • Date: 2005-09-01 02:34:38 UTC
  • Revision ID: mbp@sourcefrog.net-20050901023437-bf791a0ef5edae8d
- old docs: clarify that this is not mainly descended from arch anymore

Show diffs side-by-side

added added

removed removed

Lines of Context:
50
50
"""
51
51
 
52
52
 
53
 
import bzrlib.errors as errors
54
53
from bzrlib.tree import EmptyTree
55
54
from bzrlib.delta import compare_trees
56
55
from bzrlib.trace import mutter
57
 
import re
 
56
from bzrlib.errors import InvalidRevisionNumber
58
57
 
59
58
 
60
59
def find_touching_revisions(branch, file_id):
111
110
    return rh
112
111
 
113
112
 
114
 
def _get_revision_delta(branch, revno):
115
 
    """Return the delta for a mainline revision.
116
 
    
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)
123
 
 
124
 
 
125
113
def show_log(branch,
126
114
             lf,
127
115
             specific_fileid=None,
152
140
    end_revision
153
141
        If not None, only show revisions <= end_revision
154
142
    """
155
 
    branch.lock_read()
156
 
    try:
157
 
        _show_log(branch, lf, specific_fileid, verbose, direction,
158
 
                  start_revision, end_revision, search)
159
 
    finally:
160
 
        branch.unlock()
161
 
    
162
 
def _show_log(branch,
163
 
             lf,
164
 
             specific_fileid=None,
165
 
             verbose=False,
166
 
             direction='reverse',
167
 
             start_revision=None,
168
 
             end_revision=None,
169
 
             search=None):
170
 
    """Worker function for show_log - see show_log."""
171
143
    from bzrlib.osutils import format_date
172
144
    from bzrlib.errors import BzrCheckError
173
145
    from bzrlib.textui import show_status
190
162
    
191
163
    if start_revision is None:
192
164
        start_revision = 1
193
 
    else:
194
 
        branch.check_real_revno(start_revision)
 
165
    elif start_revision < 1 or start_revision >= len(which_revs):
 
166
        raise InvalidRevisionNumber(start_revision)
195
167
    
196
168
    if end_revision is None:
197
169
        end_revision = len(which_revs)
198
 
    else:
199
 
        branch.check_real_revno(end_revision)
 
170
    elif end_revision < 1 or end_revision >= len(which_revs):
 
171
        raise InvalidRevisionNumber(end_revision)
200
172
 
201
173
    # list indexes are 0-based; revisions are 1-based
202
174
    cut_revs = which_revs[(start_revision-1):(end_revision)]
208
180
    else:
209
181
        raise ValueError('invalid direction %r' % direction)
210
182
 
211
 
    revision_history = branch.revision_history()
212
183
    for revno, rev_id in cut_revs:
213
184
        if verbose or specific_fileid:
214
 
            delta = _get_revision_delta(branch, revno)
 
185
            delta = branch.get_revision_delta(revno)
215
186
            
216
187
        if specific_fileid:
217
188
            if not delta.touches_file_id(specific_fileid):
228
199
                continue
229
200
 
230
201
        lf.show(revno, rev, delta)
231
 
        if hasattr(lf, 'show_merge'):
232
 
            if revno == 1:
233
 
                excludes = set()
234
 
            else:
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)
238
 
            while pending:
239
 
                rev_id = pending.pop()
240
 
                if rev_id in excludes:
241
 
                    continue
242
 
                # prevent showing merged revs twice if they multi-path.
243
 
                excludes.add(rev_id)
244
 
                try:
245
 
                    rev = branch.get_revision(rev_id)
246
 
                except errors.NoSuchRevision:
247
 
                    continue
248
 
                pending.extend(rev.parent_ids)
249
 
                lf.show_merge(rev)
 
202
 
250
203
 
251
204
 
252
205
def deltas_for_log_dummy(branch, which_revs):
341
294
 
342
295
    def show(self, revno, rev, delta):
343
296
        raise NotImplementedError('not implemented in abstract base')
344
 
 
345
 
    
 
297
        
 
298
 
 
299
 
 
300
 
 
301
 
 
302
 
346
303
class LongLogFormatter(LogFormatter):
347
304
    def show(self, revno, rev, delta):
348
305
        from osutils import format_date
354
311
        if self.show_ids:
355
312
            print >>to_file,  'revision-id:', rev.revision_id
356
313
 
357
 
            for parent_id in rev.parent_ids:
358
 
                print >>to_file, 'parent:', parent_id
 
314
            for parent in rev.parents:
 
315
                print >>to_file, 'parent:', parent.revision_id
359
316
            
360
317
        print >>to_file,  'committer:', rev.committer
361
318
 
374
331
        if delta != None:
375
332
            delta.show(to_file, self.show_ids)
376
333
 
377
 
    def show_merge(self, rev):
378
 
        from osutils import format_date
379
 
 
380
 
        to_file = self.to_file
381
 
 
382
 
        indent = '    '
383
 
 
384
 
        print >>to_file,  indent+'-' * 60
385
 
        print >>to_file,  indent+'merged:', rev.revision_id
386
 
        if self.show_ids:
387
 
            for parent_id in rev.parent_ids:
388
 
                print >>to_file, indent+'parent:', parent_id
389
 
            
390
 
        print >>to_file,  indent+'committer:', rev.committer
391
 
 
392
 
        date_str = format_date(rev.timestamp,
393
 
                               rev.timezone or 0,
394
 
                               self.show_timezone)
395
 
        print >>to_file,  indent+'timestamp: %s' % date_str
396
 
 
397
 
        print >>to_file,  indent+'message:'
398
 
        if not rev.message:
399
 
            print >>to_file,  indent+'  (no message)'
400
 
        else:
401
 
            for l in rev.message.split('\n'):
402
 
                print >>to_file,  indent+'  ' + l
403
334
 
404
335
 
405
336
class ShortLogFormatter(LogFormatter):
407
338
        from bzrlib.osutils import format_date
408
339
 
409
340
        to_file = self.to_file
410
 
        date_str = format_date(rev.timestamp, rev.timezone or 0,
411
 
                            self.show_timezone)
 
341
 
412
342
        print >>to_file, "%5d %s\t%s" % (revno, rev.committer,
413
343
                format_date(rev.timestamp, rev.timezone or 0,
414
344
                            self.show_timezone))
426
356
            delta.show(to_file, self.show_ids)
427
357
        print
428
358
 
429
 
class LineLogFormatter(LogFormatter):
430
 
    def truncate(self, str, max_len):
431
 
        if len(str) <= max_len:
432
 
            return str
433
 
        return str[:max_len-3]+'...'
434
 
 
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",
439
 
                           show_offset=False)
440
 
 
441
 
    def message(self, rev):
442
 
        if not rev.message:
443
 
            return '(no message)'
444
 
        else:
445
 
            return rev.message
446
 
 
447
 
    def short_committer(self, rev):
448
 
        return re.sub('<.*@.*>', '', rev.committer).strip(' ')
449
 
    
450
 
    def show(self, revno, rev, delta):
451
 
        print >> self.to_file, self.log_string(rev, 79) 
452
 
 
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)
458
 
 
459
 
def line_log(rev, max_chars):
460
 
    lf = LineLogFormatter(None)
461
 
    return lf.log_string(rev, max_chars)
 
359
 
462
360
 
463
361
FORMATTERS = {'long': LongLogFormatter,
464
362
              'short': ShortLogFormatter,
465
 
              'line': LineLogFormatter,
466
363
              }
467
364
 
468
365
 
469
366
def log_formatter(name, *args, **kwargs):
470
 
    """Construct a formatter from arguments.
471
 
 
472
 
    name -- Name of the formatter to construct; currently 'long', 'short' and
473
 
        'line' are supported.
474
 
    """
475
367
    from bzrlib.errors import BzrCommandError
 
368
    
476
369
    try:
477
370
        return FORMATTERS[name](*args, **kwargs)
478
371
    except IndexError: