/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

Merge bzr.dev

Show diffs side-by-side

added added

removed removed

Lines of Context:
59
59
    symbol_versioning,
60
60
    )
61
61
import bzrlib.errors as errors
 
62
from bzrlib.revisionspec import(
 
63
    RevisionInfo
 
64
    )
62
65
from bzrlib.symbol_versioning import (
63
66
    deprecated_method,
64
67
    zero_eleven,
115
118
        revno += 1
116
119
 
117
120
 
118
 
 
119
121
def _enumerate_history(branch):
120
122
    rh = []
121
123
    revno = 1
202
204
    else:
203
205
        searchRE = None
204
206
 
205
 
    which_revs = _enumerate_history(branch)
206
 
    
207
 
    if start_revision is None:
208
 
        start_revision = 1
209
 
    else:
210
 
        branch.check_real_revno(start_revision)
211
 
    
212
 
    if end_revision is None:
213
 
        end_revision = len(which_revs)
214
 
    else:
215
 
        branch.check_real_revno(end_revision)
216
 
 
217
 
    # list indexes are 0-based; revisions are 1-based
218
 
    cut_revs = which_revs[(start_revision-1):(end_revision)]
219
 
    if not cut_revs:
 
207
    mainline_revs, rev_nos, start_rev_id, end_rev_id = \
 
208
        _get_mainline_revs(branch, start_revision, end_revision)
 
209
    if not mainline_revs:
220
210
        return
221
211
 
222
 
    # convert the revision history to a dictionary:
223
 
    rev_nos = dict((k, v) for v, k in cut_revs)
224
 
 
225
 
    # override the mainline to look like the revision history.
226
 
    mainline_revs = [revision_id for index, revision_id in cut_revs]
227
 
    if cut_revs[0][0] == 1:
228
 
        mainline_revs.insert(0, None)
229
 
    else:
230
 
        mainline_revs.insert(0, which_revs[start_revision-2][1])
 
212
    if direction == 'reverse':
 
213
        start_rev_id, end_rev_id = end_rev_id, start_rev_id
 
214
        
231
215
    legacy_lf = getattr(lf, 'log_revision', None) is None
232
216
    if legacy_lf:
233
217
        # pre-0.17 formatters use show for mainline revisions.
250
234
                                           False)
251
235
    view_revs_iter = get_view_revisions(mainline_revs, rev_nos, branch,
252
236
                          direction, include_merges=generate_merge_revisions)
 
237
    view_revisions = _filter_revision_range(list(view_revs_iter),
 
238
                                            start_rev_id,
 
239
                                            end_rev_id)
253
240
    if specific_fileid:
254
 
        view_revisions = _get_revisions_touching_file_id(branch,
 
241
        view_revisions = _filter_revisions_touching_file_id(branch,
255
242
                                                         specific_fileid,
256
243
                                                         mainline_revs,
257
 
                                                         view_revs_iter)
258
 
    else:
259
 
        view_revisions = list(view_revs_iter)
 
244
                                                         view_revisions)
260
245
 
261
246
    rev_tag_dict = {}
262
247
    generate_tags = getattr(lf, 'supports_tags', False)
269
254
    def iter_revisions():
270
255
        # r = revision, n = revno, d = merge depth
271
256
        revision_ids = [r for r, n, d in view_revisions]
272
 
        zeros = set(r for r, n, d in view_revisions if d == 0)
273
257
        num = 9
274
258
        repository = branch.repository
275
259
        while revision_ids:
276
260
            cur_deltas = {}
277
261
            revisions = repository.get_revisions(revision_ids[:num])
278
262
            if generate_delta:
279
 
                delta_revisions = [r for r in revisions if
280
 
                                   r.revision_id in zeros]
281
 
                deltas = repository.get_deltas_for_revisions(delta_revisions)
282
 
                cur_deltas = dict(izip((r.revision_id for r in 
283
 
                                        delta_revisions), deltas))
 
263
                deltas = repository.get_deltas_for_revisions(revisions)
 
264
                cur_deltas = dict(izip((r.revision_id for r in revisions),
 
265
                                       deltas))
284
266
            for revision in revisions:
285
 
                # The delta value will be None unless
286
 
                # 1. verbose is specified, and
287
 
                # 2. the revision is a mainline revision
288
267
                yield revision, cur_deltas.get(revision.revision_id)
289
268
            revision_ids  = revision_ids[num:]
290
269
            num = min(int(num * 1.5), 200)
324
303
                break
325
304
 
326
305
 
327
 
def _get_revisions_touching_file_id(branch, file_id, mainline_revisions,
328
 
                                    view_revs_iter):
 
306
def _get_mainline_revs(branch, start_revision, end_revision):
 
307
    """Get the mainline revisions from the branch.
 
308
    
 
309
    Generates the list of mainline revisions for the branch.
 
310
    
 
311
    :param  branch: The branch containing the revisions. 
 
312
 
 
313
    :param  start_revision: The first revision to be logged.
 
314
            For backwards compatibility this may be a mainline integer revno,
 
315
            but for merge revision support a RevisionInfo is expected.
 
316
 
 
317
    :param  end_revision: The last revision to be logged.
 
318
            For backwards compatibility this may be a mainline integer revno,
 
319
            but for merge revision support a RevisionInfo is expected.
 
320
 
 
321
    :return: A (mainline_revs, rev_nos, start_rev_id, end_rev_id) tuple.
 
322
    """
 
323
    which_revs = _enumerate_history(branch)
 
324
    if not which_revs:
 
325
        return None, None, None, None
 
326
 
 
327
    # For mainline generation, map start_revision and end_revision to 
 
328
    # mainline revnos. If the revision is not on the mainline choose the 
 
329
    # appropriate extreme of the mainline instead - the extra will be 
 
330
    # filtered later.
 
331
    # Also map the revisions to rev_ids, to be used in the later filtering
 
332
    # stage.
 
333
    start_rev_id = None 
 
334
    if start_revision is None:
 
335
        start_revno = 1
 
336
    else:
 
337
        if isinstance(start_revision,RevisionInfo):
 
338
            start_rev_id = start_revision.rev_id
 
339
            start_revno = start_revision.revno or 1
 
340
        else:
 
341
            branch.check_real_revno(start_revision)
 
342
            start_revno = start_revision
 
343
    
 
344
    end_rev_id = None
 
345
    if end_revision is None:
 
346
        end_revno = len(which_revs)
 
347
    else:
 
348
        if isinstance(end_revision,RevisionInfo):
 
349
            end_rev_id = end_revision.rev_id
 
350
            end_revno = end_revision.revno or len(which_revs)
 
351
        else:
 
352
            branch.check_real_revno(end_revision)
 
353
            end_revno = end_revision
 
354
 
 
355
    if start_revno > end_revno:
 
356
        from bzrlib.errors import BzrCommandError
 
357
        raise BzrCommandError("Start revision must be older than "
 
358
                              "the end revision.")
 
359
 
 
360
    # list indexes are 0-based; revisions are 1-based
 
361
    cut_revs = which_revs[(start_revno-1):(end_revno)]
 
362
    if not cut_revs:
 
363
        return None, None, None, None
 
364
 
 
365
    # convert the revision history to a dictionary:
 
366
    rev_nos = dict((k, v) for v, k in cut_revs)
 
367
 
 
368
    # override the mainline to look like the revision history.
 
369
    mainline_revs = [revision_id for index, revision_id in cut_revs]
 
370
    if cut_revs[0][0] == 1:
 
371
        mainline_revs.insert(0, None)
 
372
    else:
 
373
        mainline_revs.insert(0, which_revs[start_revno-2][1])
 
374
    return mainline_revs, rev_nos, start_rev_id, end_rev_id
 
375
 
 
376
 
 
377
def _filter_revision_range(view_revisions, start_rev_id, end_rev_id):
 
378
    """Filter view_revisions based on revision ranges.
 
379
 
 
380
    :param view_revisions: A list of (revision_id, dotted_revno, merge_depth) 
 
381
            tuples to be filtered.
 
382
 
 
383
    :param start_rev_id: If not NONE specifies the first revision to be logged.
 
384
            If NONE then all revisions up to the end_rev_id are logged.
 
385
 
 
386
    :param end_rev_id: If not NONE specifies the last revision to be logged.
 
387
            If NONE then all revisions up to the end of the log are logged.
 
388
 
 
389
    :return: The filtered view_revisions.
 
390
    """
 
391
    if start_rev_id or end_rev_id: 
 
392
        revision_ids = [r for r, n, d in view_revisions]
 
393
        if start_rev_id:
 
394
            start_index = revision_ids.index(start_rev_id)
 
395
        else:
 
396
            start_index = 0
 
397
        if start_rev_id == end_rev_id:
 
398
            end_index = start_index
 
399
        else:
 
400
            if end_rev_id:
 
401
                end_index = revision_ids.index(end_rev_id)
 
402
            else:
 
403
                end_index = len(view_revisions) - 1
 
404
        # To include the revisions merged into the last revision, 
 
405
        # extend end_rev_id down to, but not including, the next rev
 
406
        # with the same or lesser merge_depth
 
407
        end_merge_depth = view_revisions[end_index][2]
 
408
        try:
 
409
            for index in xrange(end_index+1, len(view_revisions)+1):
 
410
                if view_revisions[index][2] <= end_merge_depth:
 
411
                    end_index = index - 1
 
412
                    break
 
413
        except IndexError:
 
414
            # if the search falls off the end then log to the end as well
 
415
            end_index = len(view_revisions) - 1
 
416
        view_revisions = view_revisions[start_index:end_index+1]
 
417
    return view_revisions
 
418
 
 
419
 
 
420
def _filter_revisions_touching_file_id(branch, file_id, mainline_revisions,
 
421
                                       view_revs_iter):
329
422
    """Return the list of revision ids which touch a given file id.
330
423
 
 
424
    The function filters view_revisions and returns a subset.
331
425
    This includes the revisions which directly change the file id,
332
426
    and the revisions which merge these changes. So if the
333
427
    revision graph is::
551
645
            for l in message.split('\n'):
552
646
                print >>to_file,  indent+'  ' + l
553
647
        if revision.delta is not None:
554
 
            revision.delta.show(to_file, self.show_ids)
 
648
            revision.delta.show(to_file, self.show_ids, indent=indent)
555
649
 
556
650
 
557
651
class ShortLogFormatter(LogFormatter):