~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/repository.py

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2008-07-14 08:21:19 UTC
  • mfrom: (3517.4.20 stacking)
  • Revision ID: pqm@pqm.ubuntu.com-20080714082119-ju6qe5weo8pp7f1c
merge integrated branch stacking

Show diffs side-by-side

added added

removed removed

Lines of Context:
524
524
        attempted.
525
525
        """
526
526
 
 
527
    def add_fallback_repository(self, repository):
 
528
        """Add a repository to use for looking up data not held locally.
 
529
        
 
530
        :param repository: A repository.
 
531
        """
 
532
        if not self._format.supports_external_lookups:
 
533
            raise errors.UnstackableRepositoryFormat(self._format, self.base)
 
534
        if not self._add_fallback_repository_check(repository):
 
535
            raise errors.IncompatibleRepositories(self, repository)
 
536
        self._fallback_repositories.append(repository)
 
537
        self.texts.add_fallback_versioned_files(repository.texts)
 
538
        self.inventories.add_fallback_versioned_files(repository.inventories)
 
539
        self.revisions.add_fallback_versioned_files(repository.revisions)
 
540
        self.signatures.add_fallback_versioned_files(repository.signatures)
 
541
 
 
542
    def _add_fallback_repository_check(self, repository):
 
543
        """Check that this repository can fallback to repository safely.
 
544
        
 
545
        :param repository: A repository to fallback to.
 
546
        :return: True if the repositories can stack ok.
 
547
        """
 
548
        return InterRepository._same_model(self, repository)
 
549
 
527
550
    def add_inventory(self, revision_id, inv, parents):
528
551
        """Add the inventory inv to the repository as revision_id.
529
552
        
597
620
    def all_revision_ids(self):
598
621
        """Returns a list of all the revision ids in the repository. 
599
622
 
600
 
        This is deprecated because code should generally work on the graph
601
 
        reachable from a particular revision, and ignore any other revisions
602
 
        that might be present.  There is no direct replacement method.
 
623
        This is conceptually deprecated because code should generally work on
 
624
        the graph reachable from a particular revision, and ignore any other
 
625
        revisions that might be present.  There is no direct replacement
 
626
        method.
603
627
        """
604
628
        if 'evil' in debug.debug_flags:
605
629
            mutter_callsite(2, "all_revision_ids is linear with history.")
665
689
        # on whether escaping is required.
666
690
        self._warn_if_deprecated()
667
691
        self._write_group = None
 
692
        # Additional places to query for data.
 
693
        self._fallback_repositories = []
668
694
 
669
695
    def __repr__(self):
670
696
        return '%s(%r)' % (self.__class__.__name__,
718
744
        XXX: this docstring is duplicated in many places, e.g. lockable_files.py
719
745
        """
720
746
        result = self.control_files.lock_write(token=token)
 
747
        for repo in self._fallback_repositories:
 
748
            # Writes don't affect fallback repos
 
749
            repo.lock_read()
721
750
        self._refresh_data()
722
751
        return result
723
752
 
724
753
    def lock_read(self):
725
754
        self.control_files.lock_read()
 
755
        for repo in self._fallback_repositories:
 
756
            repo.lock_read()
726
757
        self._refresh_data()
727
758
 
728
759
    def get_physical_lock_status(self):
962
993
                raise errors.BzrError(
963
994
                    'Must end write groups before releasing write locks.')
964
995
        self.control_files.unlock()
 
996
        for repo in self._fallback_repositories:
 
997
            repo.unlock()
965
998
 
966
999
    @needs_read_lock
967
1000
    def clone(self, a_bzrdir, revision_id=None):
1696
1729
        parent_map = self.get_parent_map(revision_ids)
1697
1730
        return [parent_map.get(r, None) for r in revision_ids]
1698
1731
 
1699
 
    def get_parent_map(self, keys):
 
1732
    def get_parent_map(self, revision_ids):
1700
1733
        """See graph._StackedParentsProvider.get_parent_map"""
1701
 
        parent_map = {}
1702
 
        for revision_id in keys:
1703
 
            if revision_id is None:
 
1734
        # revisions index works in keys; this just works in revisions
 
1735
        # therefore wrap and unwrap
 
1736
        query_keys = []
 
1737
        result = {}
 
1738
        for revision_id in revision_ids:
 
1739
            if revision_id == _mod_revision.NULL_REVISION:
 
1740
                result[revision_id] = ()
 
1741
            elif revision_id is None:
1704
1742
                raise ValueError('get_parent_map(None) is not valid')
1705
 
            if revision_id == _mod_revision.NULL_REVISION:
1706
 
                parent_map[revision_id] = ()
1707
 
            else:
1708
 
                try:
1709
 
                    parent_id_list = self.get_revision(revision_id).parent_ids
1710
 
                except errors.NoSuchRevision:
1711
 
                    pass
1712
 
                else:
1713
 
                    if len(parent_id_list) == 0:
1714
 
                        parent_ids = (_mod_revision.NULL_REVISION,)
1715
 
                    else:
1716
 
                        parent_ids = tuple(parent_id_list)
1717
 
                    parent_map[revision_id] = parent_ids
1718
 
        return parent_map
 
1743
            else:
 
1744
                query_keys.append((revision_id ,))
 
1745
        for ((revision_id,), parent_keys) in \
 
1746
                self.revisions.get_parent_map(query_keys).iteritems():
 
1747
            if parent_keys:
 
1748
                result[revision_id] = tuple(parent_revid
 
1749
                    for (parent_revid,) in parent_keys)
 
1750
            else:
 
1751
                result[revision_id] = (_mod_revision.NULL_REVISION,)
 
1752
        return result
1719
1753
 
1720
1754
    def _make_parents_provider(self):
1721
1755
        return self
2264
2298
    'bzrlib.repofmt.pack_repo',
2265
2299
    'RepositoryFormatPackDevelopment0Subtree',
2266
2300
    )
 
2301
format_registry.register_lazy(
 
2302
    "Bazaar development format 1 (needs bzr.dev from before 1.6)\n",
 
2303
    'bzrlib.repofmt.pack_repo',
 
2304
    'RepositoryFormatPackDevelopment1',
 
2305
    )
 
2306
format_registry.register_lazy(
 
2307
    ("Bazaar development format 1 with subtree support "
 
2308
        "(needs bzr.dev from before 1.6)\n"),
 
2309
    'bzrlib.repofmt.pack_repo',
 
2310
    'RepositoryFormatPackDevelopment1Subtree',
 
2311
    )
2267
2312
# 1.3->1.4 go below here
2268
2313
 
2269
2314
 
2674
2719
            # to fetch from all packs to one without
2675
2720
            # inventory parsing etc, IFF nothing to be copied is in the target.
2676
2721
            # till then:
2677
 
            revision_ids = self.source.all_revision_ids()
 
2722
            source_revision_ids = frozenset(self.source.all_revision_ids())
 
2723
            revision_ids = source_revision_ids - \
 
2724
                frozenset(self.target.get_parent_map(source_revision_ids))
2678
2725
            revision_keys = [(revid,) for revid in revision_ids]
2679
2726
            index = self.target._pack_collection.revision_index.combined_index
2680
2727
            present_revision_ids = set(item[1][0] for item in
2721
2768
        if not find_ghosts and revision_id is not None:
2722
2769
            return self._walk_to_common_revisions([revision_id])
2723
2770
        elif revision_id is not None:
2724
 
            source_ids = self.source.get_ancestry(revision_id)
2725
 
            if source_ids[0] is not None:
2726
 
                raise AssertionError()
2727
 
            source_ids.pop(0)
 
2771
            # Find ghosts: search for revisions pointing from one repository to
 
2772
            # the other, and vice versa, anywhere in the history of revision_id.
 
2773
            graph = self.target.get_graph(other_repository=self.source)
 
2774
            searcher = graph._make_breadth_first_searcher([revision_id])
 
2775
            found_ids = set()
 
2776
            while True:
 
2777
                try:
 
2778
                    next_revs, ghosts = searcher.next_with_ghosts()
 
2779
                except StopIteration:
 
2780
                    break
 
2781
                if revision_id in ghosts:
 
2782
                    raise errors.NoSuchRevision(self.source, revision_id)
 
2783
                found_ids.update(next_revs)
 
2784
                found_ids.update(ghosts)
 
2785
            found_ids = frozenset(found_ids)
 
2786
            # Double query here: should be able to avoid this by changing the
 
2787
            # graph api further.
 
2788
            result_set = found_ids - frozenset(
 
2789
                self.target.get_graph().get_parent_map(found_ids))
2728
2790
        else:
2729
2791
            source_ids = self.source.all_revision_ids()
2730
 
        # source_ids is the worst possible case we may need to pull.
2731
 
        # now we want to filter source_ids against what we actually
2732
 
        # have in target, but don't try to check for existence where we know
2733
 
        # we do not have a revision as that would be pointless.
2734
 
        target_ids = set(self.target.all_revision_ids())
2735
 
        result_set = set(source_ids).difference(target_ids)
 
2792
            # source_ids is the worst possible case we may need to pull.
 
2793
            # now we want to filter source_ids against what we actually
 
2794
            # have in target, but don't try to check for existence where we know
 
2795
            # we do not have a revision as that would be pointless.
 
2796
            target_ids = set(self.target.all_revision_ids())
 
2797
            result_set = set(source_ids).difference(target_ids)
2736
2798
        return self.source.revision_ids_to_search_result(result_set)
2737
2799
 
2738
2800