2396
2397
target_graph = self.target_get_graph()
2397
2398
revision_ids = frozenset(revision_ids)
2399
# Fast path for the case where all the revisions are already in the
2401
# (Although this does incur an extra round trip for the
2402
# fairly common case where the target doesn't already have the revision
2398
2404
if set(target_graph.get_parent_map(revision_ids)) == revision_ids:
2399
2405
return graph.SearchResult(revision_ids, set(), 0, set())
2400
2406
missing_revs = set()
2402
2408
# ensure we don't pay silly lookup costs.
2403
2409
searcher = source_graph._make_breadth_first_searcher(revision_ids)
2404
2410
null_set = frozenset([_mod_revision.NULL_REVISION])
2411
searcher_exhausted = False
2407
next_revs, ghosts = searcher.next_with_ghosts()
2408
except StopIteration:
2410
if revision_ids.intersection(ghosts):
2411
absent_ids = set(revision_ids.intersection(ghosts))
2412
# If all absent_ids are present in target, no error is needed.
2413
absent_ids.difference_update(
2414
set(target_graph.get_parent_map(absent_ids)))
2416
raise errors.NoSuchRevision(self.source, absent_ids.pop())
2417
# we don't care about other ghosts as we can't fetch them and
2415
# Iterate the searcher until we have enough next_revs
2416
while len(next_revs) < self._walk_to_common_revisions_batch_size:
2418
next_revs_part, ghosts_part = searcher.next_with_ghosts()
2419
next_revs.update(next_revs_part)
2420
ghosts.update(ghosts_part)
2421
except StopIteration:
2422
searcher_exhausted = True
2424
# If there are ghosts in the source graph, and the caller asked for
2425
# them, make sure that they are present in the target.
2426
# We don't care about other ghosts as we can't fetch them and
2418
2427
# haven't been asked to.
2419
next_revs = set(next_revs)
2420
# we always have NULL_REVISION present.
2421
have_revs = set(target_graph.get_parent_map(next_revs)).union(null_set)
2422
missing_revs.update(next_revs - have_revs)
2423
searcher.stop_searching_any(have_revs)
2428
ghosts_to_check = set(revision_ids.intersection(ghosts))
2429
revs_to_get = set(next_revs).union(ghosts_to_check)
2431
have_revs = set(target_graph.get_parent_map(revs_to_get))
2432
# we always have NULL_REVISION present.
2433
have_revs = have_revs.union(null_set)
2434
# Check if the target is missing any ghosts we need.
2435
ghosts_to_check.difference_update(have_revs)
2437
# One of the caller's revision_ids is a ghost in both the
2438
# source and the target.
2439
raise errors.NoSuchRevision(
2440
self.source, ghosts_to_check.pop())
2441
missing_revs.update(next_revs - have_revs)
2442
searcher.stop_searching_any(have_revs)
2443
if searcher_exhausted:
2424
2445
return searcher.get_result()
2426
2447
@deprecated_method(one_two)
3030
3051
class InterOtherToRemote(InterRepository):
3053
_walk_to_common_revisions_batch_size = 50
3032
3055
def __init__(self, source, target):
3033
3056
InterRepository.__init__(self, source, target)
3034
3057
self._real_inter = None