~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/branch.py

  • Committer: Jelmer Vernooij
  • Date: 2009-02-11 03:02:03 UTC
  • mto: This revision was merged to the branch mainline in revision 4053.
  • Revision ID: jelmer@samba.org-20090211030203-znq9j2cd2wff1e0x
Add InterBranch.

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.symbol_versioning import (
49
50
    deprecated_in,
50
51
    deprecated_method,
668
669
            information. This can be None.
669
670
        :return: None
670
671
        """
671
 
        other.lock_read()
672
 
        try:
673
 
            other_revno, other_last_revision = other.last_revision_info()
674
 
            stop_revno = None # unknown
675
 
            if stop_revision is None:
676
 
                stop_revision = other_last_revision
677
 
                if _mod_revision.is_null(stop_revision):
678
 
                    # if there are no commits, we're done.
679
 
                    return
680
 
                stop_revno = other_revno
681
 
 
682
 
            # what's the current last revision, before we fetch [and change it
683
 
            # possibly]
684
 
            last_rev = _mod_revision.ensure_null(self.last_revision())
685
 
            # we fetch here so that we don't process data twice in the common
686
 
            # case of having something to pull, and so that the check for 
687
 
            # already merged can operate on the just fetched graph, which will
688
 
            # be cached in memory.
689
 
            self.fetch(other, stop_revision)
690
 
            # Check to see if one is an ancestor of the other
691
 
            if not overwrite:
692
 
                if graph is None:
693
 
                    graph = self.repository.get_graph()
694
 
                if self._check_if_descendant_or_diverged(
695
 
                        stop_revision, last_rev, graph, other):
696
 
                    # stop_revision is a descendant of last_rev, but we aren't
697
 
                    # overwriting, so we're done.
698
 
                    return
699
 
            if stop_revno is None:
700
 
                if graph is None:
701
 
                    graph = self.repository.get_graph()
702
 
                this_revno, this_last_revision = self.last_revision_info()
703
 
                stop_revno = graph.find_distance_to_null(stop_revision,
704
 
                                [(other_last_revision, other_revno),
705
 
                                 (this_last_revision, this_revno)])
706
 
            self.set_last_revision_info(stop_revno, stop_revision)
707
 
        finally:
708
 
            other.unlock()
 
672
        return InterBranch.get(other, self).update_revisions(stop_revision,
 
673
            overwrite, graph)
709
674
 
710
675
    def revision_id_to_revno(self, revision_id):
711
676
        """Given a revision id, return its revno"""
2688
2653
    else:
2689
2654
        target.unlock()
2690
2655
        return result
 
2656
 
 
2657
 
 
2658
class InterBranch(InterObject):
 
2659
    """This class represents operations taking place between two branches.
 
2660
 
 
2661
    Its instances have methods like pull() and push() and contain
 
2662
    references to the source and target repositories these operations
 
2663
    can be carried out on.
 
2664
    """
 
2665
 
 
2666
    _optimisers = []
 
2667
    """The available optimised InterBranch types."""
 
2668
 
 
2669
    def update_revisions(self, stop_revision=None, overwrite=False,
 
2670
                         graph=None):
 
2671
        """Pull in new perfect-fit revisions.
 
2672
 
 
2673
        :param stop_revision: Updated until the given revision
 
2674
        :param overwrite: Always set the branch pointer, rather than checking
 
2675
            to see if it is a proper descendant.
 
2676
        :param graph: A Graph object that can be used to query history
 
2677
            information. This can be None.
 
2678
        :return: None
 
2679
        """
 
2680
        raise NotImplementedError(self.update_revisions)
 
2681
 
 
2682
 
 
2683
class GenericInterBranch(InterBranch):
 
2684
    """InterBranch implementation that uses public Branch functions.
 
2685
    """
 
2686
 
 
2687
    def update_revisions(self, stop_revision=None, overwrite=False,
 
2688
        graph=None):
 
2689
        """See InterBranch.update_revisions()."""
 
2690
        self.source.lock_read()
 
2691
        try:
 
2692
            other_revno, other_last_revision = self.source.last_revision_info()
 
2693
            stop_revno = None # unknown
 
2694
            if stop_revision is None:
 
2695
                stop_revision = other_last_revision
 
2696
                if _mod_revision.is_null(stop_revision):
 
2697
                    # if there are no commits, we're done.
 
2698
                    return
 
2699
                stop_revno = other_revno
 
2700
 
 
2701
            # what's the current last revision, before we fetch [and change it
 
2702
            # possibly]
 
2703
            last_rev = _mod_revision.ensure_null(self.target.last_revision())
 
2704
            # we fetch here so that we don't process data twice in the common
 
2705
            # case of having something to pull, and so that the check for
 
2706
            # already merged can operate on the just fetched graph, which will
 
2707
            # be cached in memory.
 
2708
            self.target.fetch(self.source, stop_revision)
 
2709
            # Check to see if one is an ancestor of the other
 
2710
            if not overwrite:
 
2711
                if graph is None:
 
2712
                    graph = self.target.repository.get_graph()
 
2713
                if self.target._check_if_descendant_or_diverged(
 
2714
                        stop_revision, last_rev, graph, self.source):
 
2715
                    # stop_revision is a descendant of last_rev, but we aren't
 
2716
                    # overwriting, so we're done.
 
2717
                    return
 
2718
            if stop_revno is None:
 
2719
                if graph is None:
 
2720
                    graph = self.target.repository.get_graph()
 
2721
                this_revno, this_last_revision = \
 
2722
                        self.target.last_revision_info()
 
2723
                stop_revno = graph.find_distance_to_null(stop_revision,
 
2724
                                [(other_last_revision, other_revno),
 
2725
                                 (this_last_revision, this_revno)])
 
2726
            self.target.set_last_revision_info(stop_revno, stop_revision)
 
2727
        finally:
 
2728
            self.source.unlock()
 
2729
 
 
2730
    @classmethod
 
2731
    def is_compatible(self, source, target):
 
2732
        # GenericBranch uses the public API, so always compatible
 
2733
        return True
 
2734
 
 
2735
 
 
2736
InterBranch.register_optimiser(GenericInterBranch)