~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/log.py

  • Committer: Robert Collins
  • Date: 2005-10-24 13:59:18 UTC
  • mfrom: (1185.20.1)
  • Revision ID: robertc@robertcollins.net-20051024135918-024629d7ee347b5c
fix upgrading of trees with no commits

Show diffs side-by-side

added added

removed removed

Lines of Context:
50
50
"""
51
51
 
52
52
 
 
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
56
 
from bzrlib.errors import InvalidRevisionNumber
 
57
import re
57
58
 
58
59
 
59
60
def find_touching_revisions(branch, file_id):
110
111
    return rh
111
112
 
112
113
 
 
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
 
113
125
def show_log(branch,
114
126
             lf,
115
127
             specific_fileid=None,
140
152
    end_revision
141
153
        If not None, only show revisions <= end_revision
142
154
    """
 
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."""
143
171
    from bzrlib.osutils import format_date
144
172
    from bzrlib.errors import BzrCheckError
145
173
    from bzrlib.textui import show_status
162
190
    
163
191
    if start_revision is None:
164
192
        start_revision = 1
165
 
    elif start_revision < 1 or start_revision >= len(which_revs):
166
 
        raise InvalidRevisionNumber(start_revision)
 
193
    else:
 
194
        branch.check_real_revno(start_revision)
167
195
    
168
196
    if end_revision is None:
169
197
        end_revision = len(which_revs)
170
 
    elif end_revision < 1 or end_revision >= len(which_revs):
171
 
        raise InvalidRevisionNumber(end_revision)
 
198
    else:
 
199
        branch.check_real_revno(end_revision)
172
200
 
173
201
    # list indexes are 0-based; revisions are 1-based
174
202
    cut_revs = which_revs[(start_revision-1):(end_revision)]
180
208
    else:
181
209
        raise ValueError('invalid direction %r' % direction)
182
210
 
 
211
    revision_history = branch.revision_history()
183
212
    for revno, rev_id in cut_revs:
184
213
        if verbose or specific_fileid:
185
 
            delta = branch.get_revision_delta(revno)
 
214
            delta = _get_revision_delta(branch, revno)
186
215
            
187
216
        if specific_fileid:
188
217
            if not delta.touches_file_id(specific_fileid):
199
228
                continue
200
229
 
201
230
        lf.show(revno, rev, delta)
202
 
 
 
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)
203
250
 
204
251
 
205
252
def deltas_for_log_dummy(branch, which_revs):
294
341
 
295
342
    def show(self, revno, rev, delta):
296
343
        raise NotImplementedError('not implemented in abstract base')
297
 
        
298
 
 
299
 
 
300
 
 
301
 
 
302
 
 
 
344
 
 
345
    
303
346
class LongLogFormatter(LogFormatter):
304
347
    def show(self, revno, rev, delta):
305
348
        from osutils import format_date
310
353
        print >>to_file,  'revno:', revno
311
354
        if self.show_ids:
312
355
            print >>to_file,  'revision-id:', rev.revision_id
 
356
 
 
357
            for parent_id in rev.parent_ids:
 
358
                print >>to_file, 'parent:', parent_id
 
359
            
313
360
        print >>to_file,  'committer:', rev.committer
314
361
 
315
362
        date_str = format_date(rev.timestamp,
327
374
        if delta != None:
328
375
            delta.show(to_file, self.show_ids)
329
376
 
 
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
330
403
 
331
404
 
332
405
class ShortLogFormatter(LogFormatter):
334
407
        from bzrlib.osutils import format_date
335
408
 
336
409
        to_file = self.to_file
337
 
 
 
410
        date_str = format_date(rev.timestamp, rev.timezone or 0,
 
411
                            self.show_timezone)
338
412
        print >>to_file, "%5d %s\t%s" % (revno, rev.committer,
339
413
                format_date(rev.timestamp, rev.timezone or 0,
340
414
                            self.show_timezone))
352
426
            delta.show(to_file, self.show_ids)
353
427
        print
354
428
 
355
 
 
 
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)
356
462
 
357
463
FORMATTERS = {'long': LongLogFormatter,
358
464
              'short': ShortLogFormatter,
 
465
              'line': LineLogFormatter,
359
466
              }
360
467
 
361
468
 
362
469
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
    """
363
475
    from bzrlib.errors import BzrCommandError
364
 
    
365
476
    try:
366
477
        return FORMATTERS[name](*args, **kwargs)
367
478
    except IndexError: