537
536
return view_revisions
540
def _filter_revisions_touching_file_id(branch, file_id, mainline_revisions,
541
view_revs_iter, direction):
542
"""Return the list of revision ids which touch a given file id.
539
def _filter_revisions_touching_file_id(branch, file_id, view_revisions,
541
r"""Return the list of revision ids which touch a given file id.
544
543
The function filters view_revisions and returns a subset.
545
544
This includes the revisions which directly change the file id,
546
545
and the revisions which merge these changes. So if the
547
546
revision graph is::
554
And 'C' changes a file, then both C and D will be returned.
556
This will also can be restricted based on a subset of the mainline.
557
And 'C' changes a file, then both C and D will be returned. F will not be
558
returned even though it brings the changes to C into the branch starting
559
with E. (Note that if we were using F as the tip instead of G, then we
562
This will also be restricted based on a subset of the mainline.
564
:param branch: The branch where we can get text revision information.
565
:param file_id: Filter out revisions that do not touch file_id.
566
:param view_revisions: A list of (revision_id, dotted_revno, merge_depth)
567
tuples. This is the list of revisions which will be filtered. It is
568
assumed that view_revisions is in merge_sort order (either forward or
570
:param direction: The direction of view_revisions. See also
571
reverse_by_depth, and get_view_revisions
558
572
:return: A list of (revision_id, dotted_revno, merge_depth) tuples.
560
# find all the revisions that change the specific file
561
text_keys = [(file_id, rev_id) for rev_id, revno, depth in view_revs_iter]
562
# Do a direct lookup of all possible text keys, and figure out which ones
563
# are actually present, and then convert it back to revision_ids, since the
564
# file_id prefix is shared by everything.
574
# Lookup all possible text keys to determine which ones actually modified
576
text_keys = [(file_id, rev_id) for rev_id, revno, depth in view_revisions]
565
577
# Looking up keys in batches of 1000 can cut the time in half, as well as
566
578
# memory consumption. GraphIndex *does* like to look for a few keys in
567
579
# parallel, it just doesn't like looking for *lots* of keys in parallel.
574
586
chunk_size = 1000
575
587
for start in xrange(0, len(text_keys), chunk_size):
576
588
next_keys = text_keys[start:start + chunk_size]
589
# Only keep the revision_id portion of the key
577
590
modified_text_revisions.update(
578
591
[k[1] for k in get_parent_map(next_keys)])
579
592
del text_keys, next_keys
582
595
if direction == 'forward':
583
view_revs_iter = reverse_by_depth(view_revs_iter)
596
# TODO: The algorithm for finding 'merges' of file changes expects
597
# 'reverse' order (the default from 'merge_sort()'). Instead of
598
# forcing this, we could just use the reverse_by_depth order.
599
view_revisions = reverse_by_depth(view_revisions)
584
600
# Track what revisions will merge the current revision, replace entries
585
601
# with 'None' when they have been added to result
586
602
current_merge_stack = [None]
587
for info in view_revs_iter:
603
for info in view_revisions:
588
604
rev_id, revno, depth = info
589
605
if depth == len(current_merge_stack):
590
606
current_merge_stack.append(info)