~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/branch.py

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2009-02-25 23:52:42 UTC
  • mfrom: (4000.5.8 interbranch)
  • Revision ID: pqm@pqm.ubuntu.com-20090225235242-3h3yxyd8smf6b0g2
(Jelmer) Add InterBranch class.

Show diffs side-by-side

added added

removed removed

Lines of Context:
45
45
 
46
46
from bzrlib.decorators import needs_read_lock, needs_write_lock
47
47
from bzrlib.hooks import Hooks
 
48
from bzrlib.inter import InterObject
48
49
from bzrlib import registry
49
50
from bzrlib.symbol_versioning import (
50
51
    deprecated_in,
704
705
            information. This can be None.
705
706
        :return: None
706
707
        """
707
 
        other.lock_read()
708
 
        try:
709
 
            other_revno, other_last_revision = other.last_revision_info()
710
 
            stop_revno = None # unknown
711
 
            if stop_revision is None:
712
 
                stop_revision = other_last_revision
713
 
                if _mod_revision.is_null(stop_revision):
714
 
                    # if there are no commits, we're done.
715
 
                    return
716
 
                stop_revno = other_revno
717
 
 
718
 
            # what's the current last revision, before we fetch [and change it
719
 
            # possibly]
720
 
            last_rev = _mod_revision.ensure_null(self.last_revision())
721
 
            # we fetch here so that we don't process data twice in the common
722
 
            # case of having something to pull, and so that the check for
723
 
            # already merged can operate on the just fetched graph, which will
724
 
            # be cached in memory.
725
 
            self.fetch(other, stop_revision)
726
 
            # Check to see if one is an ancestor of the other
727
 
            if not overwrite:
728
 
                if graph is None:
729
 
                    graph = self.repository.get_graph()
730
 
                if self._check_if_descendant_or_diverged(
731
 
                        stop_revision, last_rev, graph, other):
732
 
                    # stop_revision is a descendant of last_rev, but we aren't
733
 
                    # overwriting, so we're done.
734
 
                    return
735
 
            if stop_revno is None:
736
 
                if graph is None:
737
 
                    graph = self.repository.get_graph()
738
 
                this_revno, this_last_revision = self.last_revision_info()
739
 
                stop_revno = graph.find_distance_to_null(stop_revision,
740
 
                                [(other_last_revision, other_revno),
741
 
                                 (this_last_revision, this_revno)])
742
 
            self.set_last_revision_info(stop_revno, stop_revision)
743
 
        finally:
744
 
            other.unlock()
 
708
        return InterBranch.get(other, self).update_revisions(stop_revision,
 
709
            overwrite, graph)
745
710
 
746
711
    def revision_id_to_revno(self, revision_id):
747
712
        """Given a revision id, return its revno"""
2744
2709
    else:
2745
2710
        target.unlock()
2746
2711
        return result
 
2712
 
 
2713
 
 
2714
class InterBranch(InterObject):
 
2715
    """This class represents operations taking place between two branches.
 
2716
 
 
2717
    Its instances have methods like pull() and push() and contain
 
2718
    references to the source and target repositories these operations
 
2719
    can be carried out on.
 
2720
    """
 
2721
 
 
2722
    _optimisers = []
 
2723
    """The available optimised InterBranch types."""
 
2724
 
 
2725
    @staticmethod
 
2726
    def _get_branch_formats_to_test():
 
2727
        """Return a tuple with the Branch formats to use when testing."""
 
2728
        raise NotImplementedError(self._get_branch_formats_to_test)
 
2729
 
 
2730
    def update_revisions(self, stop_revision=None, overwrite=False,
 
2731
                         graph=None):
 
2732
        """Pull in new perfect-fit revisions.
 
2733
 
 
2734
        :param stop_revision: Updated until the given revision
 
2735
        :param overwrite: Always set the branch pointer, rather than checking
 
2736
            to see if it is a proper descendant.
 
2737
        :param graph: A Graph object that can be used to query history
 
2738
            information. This can be None.
 
2739
        :return: None
 
2740
        """
 
2741
        raise NotImplementedError(self.update_revisions)
 
2742
 
 
2743
 
 
2744
class GenericInterBranch(InterBranch):
 
2745
    """InterBranch implementation that uses public Branch functions.
 
2746
    """
 
2747
 
 
2748
    @staticmethod
 
2749
    def _get_branch_formats_to_test():
 
2750
        return BranchFormat._default_format, BranchFormat._default_format
 
2751
 
 
2752
    def update_revisions(self, stop_revision=None, overwrite=False,
 
2753
        graph=None):
 
2754
        """See InterBranch.update_revisions()."""
 
2755
        self.source.lock_read()
 
2756
        try:
 
2757
            other_revno, other_last_revision = self.source.last_revision_info()
 
2758
            stop_revno = None # unknown
 
2759
            if stop_revision is None:
 
2760
                stop_revision = other_last_revision
 
2761
                if _mod_revision.is_null(stop_revision):
 
2762
                    # if there are no commits, we're done.
 
2763
                    return
 
2764
                stop_revno = other_revno
 
2765
 
 
2766
            # what's the current last revision, before we fetch [and change it
 
2767
            # possibly]
 
2768
            last_rev = _mod_revision.ensure_null(self.target.last_revision())
 
2769
            # we fetch here so that we don't process data twice in the common
 
2770
            # case of having something to pull, and so that the check for
 
2771
            # already merged can operate on the just fetched graph, which will
 
2772
            # be cached in memory.
 
2773
            self.target.fetch(self.source, stop_revision)
 
2774
            # Check to see if one is an ancestor of the other
 
2775
            if not overwrite:
 
2776
                if graph is None:
 
2777
                    graph = self.target.repository.get_graph()
 
2778
                if self.target._check_if_descendant_or_diverged(
 
2779
                        stop_revision, last_rev, graph, self.source):
 
2780
                    # stop_revision is a descendant of last_rev, but we aren't
 
2781
                    # overwriting, so we're done.
 
2782
                    return
 
2783
            if stop_revno is None:
 
2784
                if graph is None:
 
2785
                    graph = self.target.repository.get_graph()
 
2786
                this_revno, this_last_revision = \
 
2787
                        self.target.last_revision_info()
 
2788
                stop_revno = graph.find_distance_to_null(stop_revision,
 
2789
                                [(other_last_revision, other_revno),
 
2790
                                 (this_last_revision, this_revno)])
 
2791
            self.target.set_last_revision_info(stop_revno, stop_revision)
 
2792
        finally:
 
2793
            self.source.unlock()
 
2794
 
 
2795
    @classmethod
 
2796
    def is_compatible(self, source, target):
 
2797
        # GenericBranch uses the public API, so always compatible
 
2798
        return True
 
2799
 
 
2800
 
 
2801
InterBranch.register_optimiser(GenericInterBranch)