/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/log.py

  • Committer: Robey Pointer
  • Date: 2006-07-01 19:03:33 UTC
  • mfrom: (1829 +trunk)
  • mto: This revision was merged to the branch mainline in revision 1830.
  • Revision ID: robey@lag.net-20060701190333-f58465aec4bd3412
merge from bzr.dev

Show diffs side-by-side

added added

removed removed

Lines of Context:
49
49
all the changes since the previous revision that touched hello.c.
50
50
"""
51
51
 
52
 
 
53
52
# TODO: option to show delta summaries for merged-in revisions
 
53
 
54
54
from itertools import izip
55
55
import re
56
56
 
57
 
from bzrlib.delta import compare_trees
58
57
import bzrlib.errors as errors
59
58
from bzrlib.trace import mutter
60
 
from bzrlib.tree import EmptyTree
61
59
from bzrlib.tsort import merge_sort
62
60
 
63
61
 
115
113
    return rh
116
114
 
117
115
 
118
 
def _get_revision_delta(branch, revno):
119
 
    """Return the delta for a mainline revision.
120
 
    
121
 
    This is used to show summaries in verbose logs, and also for finding 
122
 
    revisions which touch a given file."""
123
 
    # XXX: What are we supposed to do when showing a summary for something 
124
 
    # other than a mainline revision.  The delta to it's first parent, or
125
 
    # (more useful) the delta to a nominated other revision.
126
 
    return branch.get_revision_delta(revno)
127
 
 
128
 
 
129
116
def show_log(branch,
130
117
             lf,
131
118
             specific_fileid=None,
174
161
    """Worker function for show_log - see show_log."""
175
162
    from bzrlib.osutils import format_date
176
163
    from bzrlib.errors import BzrCheckError
177
 
    from bzrlib.textui import show_status
178
164
    
179
165
    from warnings import warn
180
166
 
206
192
    cut_revs = which_revs[(start_revision-1):(end_revision)]
207
193
    if not cut_revs:
208
194
        return
 
195
 
 
196
    # convert the revision history to a dictionary:
 
197
    rev_nos = dict((k, v) for v, k in cut_revs)
 
198
 
209
199
    # override the mainline to look like the revision history.
210
200
    mainline_revs = [revision_id for index, revision_id in cut_revs]
211
201
    if cut_revs[0][0] == 1:
212
202
        mainline_revs.insert(0, None)
213
203
    else:
214
204
        mainline_revs.insert(0, which_revs[start_revision-2][1])
215
 
 
216
 
    merge_sorted_revisions = merge_sort(
217
 
        branch.repository.get_revision_graph(mainline_revs[-1]),
218
 
        mainline_revs[-1],
219
 
        mainline_revs)
220
 
 
221
 
    if direction == 'reverse':
222
 
        cut_revs.reverse()
223
 
    elif direction == 'forward':
224
 
        # forward means oldest first.
225
 
        merge_sorted_revisions.reverse()
 
205
    if getattr(lf, 'show_merge', None) is not None:
 
206
        include_merges = True 
226
207
    else:
227
 
        raise ValueError('invalid direction %r' % direction)
228
 
 
229
 
    revision_history = branch.revision_history()
230
 
 
231
 
    # convert the revision history to a dictionary:
232
 
    rev_nos = {}
233
 
    for index, rev_id in cut_revs:
234
 
        rev_nos[rev_id] = index
 
208
        include_merges = False 
 
209
    view_revisions = list(get_view_revisions(mainline_revs, rev_nos, branch,
 
210
                          direction, include_merges=include_merges))
235
211
 
236
212
    def iter_revisions():
237
 
        revision_ids = [r for s, r, m, e in merge_sorted_revisions]
 
213
        # r = revision, n = revno, d = merge depth
 
214
        revision_ids = [r for r, n, d in view_revisions]
 
215
        zeros = set(r for r, n, d in view_revisions if d == 0)
238
216
        num = 9
 
217
        repository = branch.repository
239
218
        while revision_ids:
240
 
            revisions = branch.repository.get_revisions(revision_ids[:num])
 
219
            cur_deltas = {}
 
220
            revisions = repository.get_revisions(revision_ids[:num])
 
221
            if verbose or specific_fileid:
 
222
                delta_revisions = [r for r in revisions if
 
223
                                   r.revision_id in zeros]
 
224
                deltas = repository.get_deltas_for_revisions(delta_revisions)
 
225
                cur_deltas = dict(izip((r.revision_id for r in 
 
226
                                        delta_revisions), deltas))
241
227
            for revision in revisions:
242
 
                yield revision
 
228
                # The delta value will be None unless
 
229
                # 1. verbose or specific_fileid is specified, and
 
230
                # 2. the revision is a mainline revision
 
231
                yield revision, cur_deltas.get(revision.revision_id)
243
232
            revision_ids  = revision_ids[num:]
244
233
            num = int(num * 1.5)
245
234
            
246
 
        revisions = branch.repository.get_revisions()
247
 
        for revision in revisions:
248
 
            yield revision
249
235
    # now we just print all the revisions
250
 
    for ((sequence, rev_id, merge_depth, end_of_merge), rev) in \
251
 
        izip(merge_sorted_revisions, iter_revisions()):
 
236
    for ((rev_id, revno, merge_depth), (rev, delta)) in \
 
237
         izip(view_revisions, iter_revisions()):
252
238
 
253
239
        if searchRE:
254
240
            if not searchRE.search(rev.message):
256
242
 
257
243
        if merge_depth == 0:
258
244
            # a mainline revision.
259
 
            if verbose or specific_fileid:
260
 
                delta = _get_revision_delta(branch, rev_nos[rev_id])
261
245
                
262
246
            if specific_fileid:
263
247
                if not delta.touches_file_id(specific_fileid):
267
251
                # although we calculated it, throw it away without display
268
252
                delta = None
269
253
 
270
 
            lf.show(rev_nos[rev_id], rev, delta)
271
 
        elif hasattr(lf, 'show_merge'):
 
254
            lf.show(revno, rev, delta)
 
255
        else:
272
256
            lf.show_merge(rev, merge_depth)
273
257
 
274
258
 
275
 
def deltas_for_log_dummy(branch, which_revs):
276
 
    """Return all the revisions without intermediate deltas.
277
 
 
278
 
    Useful for log commands that won't need the delta information.
279
 
    """
280
 
    
281
 
    for revno, revision_id in which_revs:
282
 
        yield revno, branch.get_revision(revision_id), None
283
 
 
284
 
 
285
 
def deltas_for_log_reverse(branch, which_revs):
286
 
    """Compute deltas for display in latest-to-earliest order.
287
 
 
288
 
    branch
289
 
        Branch to traverse
290
 
 
291
 
    which_revs
292
 
        Sequence of (revno, revision_id) for the subset of history to examine
293
 
 
294
 
    returns 
295
 
        Sequence of (revno, rev, delta)
296
 
 
297
 
    The delta is from the given revision to the next one in the
298
 
    sequence, which makes sense if the log is being displayed from
299
 
    newest to oldest.
300
 
    """
301
 
    last_revno = last_revision_id = last_tree = None
302
 
    for revno, revision_id in which_revs:
303
 
        this_tree = branch.revision_tree(revision_id)
304
 
        this_revision = branch.get_revision(revision_id)
305
 
        
306
 
        if last_revno:
307
 
            yield last_revno, last_revision, compare_trees(this_tree, last_tree, False)
308
 
 
309
 
        this_tree = EmptyTree(branch.get_root_id())
310
 
 
311
 
        last_revno = revno
312
 
        last_revision = this_revision
313
 
        last_tree = this_tree
314
 
 
315
 
    if last_revno:
316
 
        if last_revno == 1:
317
 
            this_tree = EmptyTree(branch.get_root_id())
 
259
def get_view_revisions(mainline_revs, rev_nos, branch, direction,
 
260
                       include_merges=True):
 
261
    """Produce an iterator of revisions to show
 
262
    :return: an iterator of (revision_id, revno, merge_depth)
 
263
    (if there is no revno for a revision, None is supplied)
 
264
    """
 
265
    if include_merges is False:
 
266
        revision_ids = mainline_revs[1:]
 
267
        if direction == 'reverse':
 
268
            revision_ids.reverse()
 
269
        for revision_id in revision_ids:
 
270
            yield revision_id, rev_nos[revision_id], 0
 
271
        return
 
272
    merge_sorted_revisions = merge_sort(
 
273
        branch.repository.get_revision_graph(mainline_revs[-1]),
 
274
        mainline_revs[-1],
 
275
        mainline_revs)
 
276
 
 
277
    if direction == 'forward':
 
278
        # forward means oldest first.
 
279
        merge_sorted_revisions = reverse_by_depth(merge_sorted_revisions)
 
280
    elif direction != 'reverse':
 
281
        raise ValueError('invalid direction %r' % direction)
 
282
 
 
283
    revision_history = branch.revision_history()
 
284
 
 
285
    for sequence, rev_id, merge_depth, end_of_merge in merge_sorted_revisions:
 
286
        yield rev_id, rev_nos.get(rev_id), merge_depth
 
287
 
 
288
 
 
289
def reverse_by_depth(merge_sorted_revisions, _depth=0):
 
290
    """Reverse revisions by depth.
 
291
 
 
292
    Revisions with a different depth are sorted as a group with the previous
 
293
    revision of that depth.  There may be no topological justification for this,
 
294
    but it looks much nicer.
 
295
    """
 
296
    zd_revisions = []
 
297
    for val in merge_sorted_revisions:
 
298
        if val[2] == _depth:
 
299
            zd_revisions.append([val])
318
300
        else:
319
 
            this_revno = last_revno - 1
320
 
            this_revision_id = branch.revision_history()[this_revno]
321
 
            this_tree = branch.revision_tree(this_revision_id)
322
 
        yield last_revno, last_revision, compare_trees(this_tree, last_tree, False)
323
 
 
324
 
 
325
 
def deltas_for_log_forward(branch, which_revs):
326
 
    """Compute deltas for display in forward log.
327
 
 
328
 
    Given a sequence of (revno, revision_id) pairs, return
329
 
    (revno, rev, delta).
330
 
 
331
 
    The delta is from the given revision to the next one in the
332
 
    sequence, which makes sense if the log is being displayed from
333
 
    newest to oldest.
334
 
    """
335
 
    last_revno = last_revision_id = last_tree = None
336
 
    prev_tree = EmptyTree(branch.get_root_id())
337
 
 
338
 
    for revno, revision_id in which_revs:
339
 
        this_tree = branch.revision_tree(revision_id)
340
 
        this_revision = branch.get_revision(revision_id)
341
 
 
342
 
        if not last_revno:
343
 
            if revno == 1:
344
 
                last_tree = EmptyTree(branch.get_root_id())
345
 
            else:
346
 
                last_revno = revno - 1
347
 
                last_revision_id = branch.revision_history()[last_revno]
348
 
                last_tree = branch.revision_tree(last_revision_id)
349
 
 
350
 
        yield revno, this_revision, compare_trees(last_tree, this_tree, False)
351
 
 
352
 
        last_revno = revno
353
 
        last_revision = this_revision
354
 
        last_tree = this_tree
 
301
            assert val[2] > _depth
 
302
            zd_revisions[-1].append(val)
 
303
    for revisions in zd_revisions:
 
304
        if len(revisions) > 1:
 
305
            revisions[1:] = reverse_by_depth(revisions[1:], _depth + 1)
 
306
    zd_revisions.reverse()
 
307
    result = []
 
308
    for chunk in zd_revisions:
 
309
        result.extend(chunk)
 
310
    return result
355
311
 
356
312
 
357
313
class LogFormatter(object):