2353
2353
InterRepository.get(other).method_name(parameters).
2356
_walk_to_common_revisions_batch_size = 1
2356
2357
_optimisers = []
2357
2358
"""The available optimised InterRepository types."""
2360
def __init__(self, source, target):
2361
InterObject.__init__(self, source, target)
2362
# These two attributes may be overridden by e.g. InterOtherToRemote to
2363
# provide a faster implementation.
2364
self.target_get_graph = self.target.get_graph
2365
self.target_get_parent_map = self.target.get_parent_map
2359
2367
def copy_content(self, revision_id=None):
2360
2368
raise NotImplementedError(self.copy_content)
2386
2394
:param revision_ids: The start point for the search.
2387
2395
:return: A set of revision ids.
2389
target_graph = self.target.get_graph()
2397
target_graph = self.target_get_graph()
2390
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
2391
2404
if set(target_graph.get_parent_map(revision_ids)) == revision_ids:
2392
2405
return graph.SearchResult(revision_ids, set(), 0, set())
2393
2406
missing_revs = set()
2395
2408
# ensure we don't pay silly lookup costs.
2396
2409
searcher = source_graph._make_breadth_first_searcher(revision_ids)
2397
2410
null_set = frozenset([_mod_revision.NULL_REVISION])
2411
searcher_exhausted = False
2400
next_revs, ghosts = searcher.next_with_ghosts()
2401
except StopIteration:
2403
if revision_ids.intersection(ghosts):
2404
absent_ids = set(revision_ids.intersection(ghosts))
2405
# If all absent_ids are present in target, no error is needed.
2406
absent_ids.difference_update(
2407
set(target_graph.get_parent_map(absent_ids)))
2409
raise errors.NoSuchRevision(self.source, absent_ids.pop())
2410
# 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
2411
2427
# haven't been asked to.
2412
next_revs = set(next_revs)
2413
# we always have NULL_REVISION present.
2414
have_revs = set(target_graph.get_parent_map(next_revs)).union(null_set)
2415
missing_revs.update(next_revs - have_revs)
2416
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:
2417
2445
return searcher.get_result()
2419
2447
@deprecated_method(one_two)
2782
2810
source_revision_ids = frozenset(self.source.all_revision_ids())
2783
2811
revision_ids = source_revision_ids - \
2784
frozenset(self.target.get_parent_map(source_revision_ids))
2812
frozenset(self.target_get_parent_map(source_revision_ids))
2785
2813
revision_keys = [(revid,) for revid in revision_ids]
2786
2814
index = self.target._pack_collection.revision_index.combined_index
2787
2815
present_revision_ids = set(item[1][0] for item in
2830
2858
elif revision_id is not None:
2831
2859
# Find ghosts: search for revisions pointing from one repository to
2832
2860
# the other, and vice versa, anywhere in the history of revision_id.
2833
graph = self.target.get_graph(other_repository=self.source)
2861
graph = self.target_get_graph(other_repository=self.source)
2834
2862
searcher = graph._make_breadth_first_searcher([revision_id])
2835
2863
found_ids = set()
2846
2874
# Double query here: should be able to avoid this by changing the
2847
2875
# graph api further.
2848
2876
result_set = found_ids - frozenset(
2849
self.target.get_parent_map(found_ids))
2877
self.target_get_parent_map(found_ids))
2851
2879
source_ids = self.source.all_revision_ids()
2852
2880
# source_ids is the worst possible case we may need to pull.
3023
3051
class InterOtherToRemote(InterRepository):
3053
_walk_to_common_revisions_batch_size = 50
3025
3055
def __init__(self, source, target):
3026
3056
InterRepository.__init__(self, source, target)
3027
3057
self._real_inter = None
3037
3067
self.target._ensure_real()
3038
3068
real_target = self.target._real_repository
3039
3069
self._real_inter = InterRepository.get(self.source, real_target)
3070
# Make _real_inter use the RemoteRepository for get_parent_map
3071
self._real_inter.target_get_graph = self.target.get_graph
3072
self._real_inter.target_get_parent_map = self.target.get_parent_map
3041
3074
def copy_content(self, revision_id=None):
3042
3075
self._ensure_real_inter()