191
which_revs = _enumerate_history(branch)
193
if start_revision is None:
196
branch.check_real_revno(start_revision)
198
if end_revision is None:
199
end_revision = len(which_revs)
201
branch.check_real_revno(end_revision)
203
# list indexes are 0-based; revisions are 1-based
204
cut_revs = which_revs[(start_revision-1):(end_revision)]
194
mainline_revs, rev_nos, start_rev_id, end_rev_id = \
195
_get_mainline_revs(branch, start_revision, end_revision)
196
if not mainline_revs:
208
# convert the revision history to a dictionary:
209
rev_nos = dict((k, v) for v, k in cut_revs)
211
# override the mainline to look like the revision history.
212
mainline_revs = [revision_id for index, revision_id in cut_revs]
213
if cut_revs[0][0] == 1:
214
mainline_revs.insert(0, None)
216
mainline_revs.insert(0, which_revs[start_revision-2][1])
199
if direction == 'reverse':
200
start_rev_id, end_rev_id = end_rev_id, start_rev_id
217
202
legacy_lf = not getattr(lf,'log_revision',None)
219
204
# pre-0.17 formatters use show for mainline revisions.
313
def _get_revisions_touching_file_id(branch, file_id, mainline_revisions,
299
def _get_mainline_revs(branch, start_revision, end_revision):
300
"""Get the mainline revisions from the branch.
302
Generates the list of mainline revisions for the branch.
304
:param branch: The branch containing the revisions.
306
:param start_revision: The first revision to be logged.
307
For backwards compatibility this may be a mainline integer revno,
308
but for merge revision support a RevisionInfo is expected.
310
:param end_revision: The last revision to be logged.
311
For backwards compatibility this may be a mainline integer revno,
312
but for merge revision support a RevisionInfo is expected.
314
:return: A (mainline_revs, rev_nos, start_rev_id, end_rev_id) tuple.
316
which_revs = _enumerate_history(branch)
318
return None, None, None, None
320
# For mainline generation, map start_revision and end_revision to
321
# mainline revnos. If the revision is not on the mainline choose the
322
# appropriate extreme of the mainline instead - the extra will be
324
# Also map the revisions to rev_ids, to be used in the later filtering
327
if start_revision is None:
330
if isinstance(start_revision,RevisionInfo):
331
start_rev_id = start_revision.rev_id
332
start_revno = start_revision.revno or 1
334
branch.check_real_revno(start_revision)
335
start_revno = start_revision
338
if end_revision is None:
339
end_revno = len(which_revs)
341
if isinstance(end_revision,RevisionInfo):
342
end_rev_id = end_revision.rev_id
343
end_revno = end_revision.revno or len(which_revs)
345
branch.check_real_revno(end_revision)
346
end_revno = end_revision
348
if start_revno > end_revno:
349
from bzrlib.errors import BzrCommandError
350
raise BzrCommandError("Start revision must be older than "
353
# list indexes are 0-based; revisions are 1-based
354
cut_revs = which_revs[(start_revno-1):(end_revno)]
356
return None, None, None, None
358
# convert the revision history to a dictionary:
359
rev_nos = dict((k, v) for v, k in cut_revs)
361
# override the mainline to look like the revision history.
362
mainline_revs = [revision_id for index, revision_id in cut_revs]
363
if cut_revs[0][0] == 1:
364
mainline_revs.insert(0, None)
366
mainline_revs.insert(0, which_revs[start_revno-2][1])
367
return mainline_revs, rev_nos, start_rev_id, end_rev_id
370
def _filter_revision_range(view_revisions, start_rev_id, end_rev_id):
371
"""Filter view_revisions based on revision ranges.
373
:param view_revisions: A list of (revision_id, dotted_revno, merge_depth)
374
tuples to be filtered.
376
:param start_rev_id: If not NONE specifies the first revision to be logged.
377
If NONE then all revisions up to the end_rev_id are logged.
379
:param end_rev_id: If not NONE specifies the last revision to be logged.
380
If NONE then all revisions up to the end of the log are logged.
382
:return: The filtered view_revisions.
384
if start_rev_id or end_rev_id:
385
revision_ids = [r for r, n, d in view_revisions]
387
start_index = revision_ids.index(start_rev_id)
390
if start_rev_id == end_rev_id:
391
end_index = start_index
394
end_index = revision_ids.index(end_rev_id)
396
end_index = len(view_revisions) - 1
397
# To include the revisions merged into the last revision,
398
# extend end_rev_id down to, but not including, the next rev
399
# with the same or lesser merge_depth
400
end_merge_depth = view_revisions[end_index][2]
402
for index in xrange(end_index+1, len(view_revisions)+1):
403
if view_revisions[index][2] <= end_merge_depth:
404
end_index = index - 1
407
# if the search falls off the end then log to the end as well
408
end_index = len(view_revisions) - 1
409
view_revisions = view_revisions[start_index:end_index+1]
410
return view_revisions
413
def _filter_revisions_touching_file_id(branch, file_id, mainline_revisions,
315
415
"""Return the list of revision ids which touch a given file id.
417
The function filters view_revisions and returns a subset.
317
418
This includes the revisions which directly change the file id,
318
419
and the revisions which merge these changes. So if the
319
420
revision graph is::