275
275
def get_intervening_revisions(ancestor_id, rev_id, rev_source,
276
276
revision_history=None):
277
277
"""Find the longest line of descent from maybe_ancestor to revision.
278
Revision history is followed where possible
278
Revision history is followed where possible.
280
280
If ancestor_id == rev_id, list will be empty.
281
281
Otherwise, rev_id will be the last entry. ancestor_id will never appear.
282
282
If ancestor_id is not an ancestor, NotAncestor will be thrown
284
# This lists only the first descendant we encounter
284
[rev_source.get_revision(r) for r in (ancestor_id, rev_id)]
285
285
if ancestor_id == rev_id:
288
def in_history(myrev):
289
return revision_history is not None and myrev in revision_history
291
def remove_broken_lines(revisions, rev_id, descendant_map):
293
for revision in revisions:
294
cur_revision = revision
295
while cur_revision != rev_id:
296
cur_revision = descendant_map.get(cur_revision)
297
if cur_revision is None:
300
return [r for r in revisions if r not in broken]
302
def trace_ancestry():
305
while len(revisions) > 0:
306
remove_broken = False
308
for revision in revisions:
309
parent_ids = [p.revision_id for p in
310
rev_source.get_revision(revision).parents]
311
for parent_id in parent_ids:
312
if parent_id == ancestor_id:
313
return revision, descendant_map
314
if descendant_map.has_key(parent_id):
315
if in_history(descendant_map[parent_id]):
319
descendant_map[parent_id] = revision
320
new_revisions.append(parent_id)
322
new_revisions = remove_broken_lines(new_revisions, rev_id,
324
revisions = new_revisions
325
raise Exception(revision, parent_ids)
326
return None, descendant_map
328
list_start, descendant_map = trace_ancestry()
329
if list_start is None:
330
raise Exception(descendant_map)
287
def historical_lines(line):
288
"""Return a tuple of historical/non_historical lines, for sorting.
289
The non_historical count is negative, since non_historical lines are
294
for revision in line:
295
if revision in revision_history:
299
return good_count, bad_count
301
successful_lines = []
302
while len(active) > 0:
305
parent_ids = [p.revision_id for p in
306
rev_source.get_revision(line[-1]).parents]
307
for parent in parent_ids:
309
if parent == ancestor_id:
310
successful_lines.append(line_copy)
312
line_copy.append(parent)
313
new_active.append(line_copy)
315
if len(successful_lines) == 0:
331
316
raise bzrlib.errors.NotAncestor(rev_id, ancestor_id)
332
intermediate_revisions = [list_start]
333
next_revision = list_start
334
while next_revision != rev_id:
335
next_revision = descendant_map[next_revision]
336
intermediate_revisions.append(next_revision)
337
return intermediate_revisions
317
for line in successful_lines:
319
if revision_history is not None:
320
by_historical_lines = []
321
for line in successful_lines:
322
count = historical_lines(line)
323
by_historical_lines.append((count, line))
324
by_historical_lines.sort()
325
if by_historical_lines[-1][0][0] > 0:
326
return by_historical_lines[-1][1]
327
assert len(successful_lines)
328
successful_lines.sort(cmp, len)
329
return successful_lines[-1]