~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/repository.py

Merge in bzr.dev 3801, resolve NEWS

Show diffs side-by-side

added added

removed removed

Lines of Context:
2353
2353
    InterRepository.get(other).method_name(parameters).
2354
2354
    """
2355
2355
 
 
2356
    _walk_to_common_revisions_batch_size = 1
2356
2357
    _optimisers = []
2357
2358
    """The available optimised InterRepository types."""
2358
2359
 
 
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
 
2366
 
2359
2367
    def copy_content(self, revision_id=None):
2360
2368
        raise NotImplementedError(self.copy_content)
2361
2369
 
2386
2394
        :param revision_ids: The start point for the search.
2387
2395
        :return: A set of revision ids.
2388
2396
        """
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
 
2400
        # target repo.
 
2401
        # (Although this does incur an extra round trip for the
 
2402
        # fairly common case where the target doesn't already have the revision
 
2403
        # we're pushing.)
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
2398
2412
        while True:
2399
 
            try:
2400
 
                next_revs, ghosts = searcher.next_with_ghosts()
2401
 
            except StopIteration:
2402
 
                break
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)))
2408
 
                if 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
 
2413
            next_revs = set()
 
2414
            ghosts = set()
 
2415
            # Iterate the searcher until we have enough next_revs
 
2416
            while len(next_revs) < self._walk_to_common_revisions_batch_size:
 
2417
                try:
 
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
 
2423
                    break
 
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)
 
2430
            if revs_to_get:
 
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)
 
2436
                if ghosts_to_check:
 
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:
 
2444
                break
2417
2445
        return searcher.get_result()
2418
2446
   
2419
2447
    @deprecated_method(one_two)
2781
2809
            # till then:
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()
2836
2864
            while True:
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))
2850
2878
        else:
2851
2879
            source_ids = self.source.all_revision_ids()
2852
2880
            # source_ids is the worst possible case we may need to pull.
3022
3050
 
3023
3051
class InterOtherToRemote(InterRepository):
3024
3052
 
 
3053
    _walk_to_common_revisions_batch_size = 50
 
3054
 
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
3040
3073
    
3041
3074
    def copy_content(self, revision_id=None):
3042
3075
        self._ensure_real_inter()