~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/branch.py

  • Committer: Martin Pool
  • Date: 2009-08-04 11:40:59 UTC
  • mfrom: (4584 +trunk)
  • mto: This revision was merged to the branch mainline in revision 4586.
  • Revision ID: mbp@sourcefrog.net-20090804114059-xptutagbs5jev3ry
merge trunk

Show diffs side-by-side

added added

removed removed

Lines of Context:
105
105
    def _activate_fallback_location(self, url):
106
106
        """Activate the branch/repository from url as a fallback repository."""
107
107
        repo = self._get_fallback_repository(url)
 
108
        if repo.has_same_location(self.repository):
 
109
            raise errors.UnstackableLocationError(self.base, url)
108
110
        self.repository.add_fallback_repository(repo)
109
111
 
110
112
    def break_lock(self):
661
663
        """
662
664
        if not self._format.supports_stacking():
663
665
            raise errors.UnstackableBranchFormat(self._format, self.base)
 
666
        # XXX: Changing from one fallback repository to another does not check
 
667
        # that all the data you need is present in the new fallback.
 
668
        # Possibly it should.
664
669
        self._check_stackable_repo()
665
670
        if not url:
666
671
            try:
668
673
            except (errors.NotStacked, errors.UnstackableBranchFormat,
669
674
                errors.UnstackableRepositoryFormat):
670
675
                return
671
 
            url = ''
672
 
            # XXX: Lock correctness - should unlock our old repo if we were
673
 
            # locked.
674
 
            # repositories don't offer an interface to remove fallback
675
 
            # repositories today; take the conceptually simpler option and just
676
 
            # reopen it.
677
 
            self.repository = self.bzrdir.find_repository()
678
 
            self.repository.lock_write()
679
 
            # for every revision reference the branch has, ensure it is pulled
680
 
            # in.
681
 
            source_repository = self._get_fallback_repository(old_url)
682
 
            for revision_id in chain([self.last_revision()],
683
 
                self.tags.get_reverse_tag_dict()):
684
 
                self.repository.fetch(source_repository, revision_id,
685
 
                    find_ghosts=True)
 
676
            self._unstack()
686
677
        else:
687
678
            self._activate_fallback_location(url)
688
679
        # write this out after the repository is stacked to avoid setting a
689
680
        # stacked config that doesn't work.
690
681
        self._set_config_location('stacked_on_location', url)
691
682
 
 
683
    def _unstack(self):
 
684
        """Change a branch to be unstacked, copying data as needed.
 
685
        
 
686
        Don't call this directly, use set_stacked_on_url(None).
 
687
        """
 
688
        pb = ui.ui_factory.nested_progress_bar()
 
689
        try:
 
690
            pb.update("Unstacking")
 
691
            # The basic approach here is to fetch the tip of the branch,
 
692
            # including all available ghosts, from the existing stacked
 
693
            # repository into a new repository object without the fallbacks. 
 
694
            #
 
695
            # XXX: See <https://launchpad.net/bugs/397286> - this may not be
 
696
            # correct for CHKMap repostiories
 
697
            old_repository = self.repository
 
698
            if len(old_repository._fallback_repositories) != 1:
 
699
                raise AssertionError("can't cope with fallback repositories "
 
700
                    "of %r" % (self.repository,))
 
701
            # unlock it, including unlocking the fallback
 
702
            old_repository.unlock()
 
703
            old_repository.lock_read()
 
704
            try:
 
705
                # Repositories don't offer an interface to remove fallback
 
706
                # repositories today; take the conceptually simpler option and just
 
707
                # reopen it.  We reopen it starting from the URL so that we
 
708
                # get a separate connection for RemoteRepositories and can
 
709
                # stream from one of them to the other.  This does mean doing
 
710
                # separate SSH connection setup, but unstacking is not a
 
711
                # common operation so it's tolerable.
 
712
                new_bzrdir = bzrdir.BzrDir.open(self.bzrdir.root_transport.base)
 
713
                new_repository = new_bzrdir.find_repository()
 
714
                self.repository = new_repository
 
715
                if self.repository._fallback_repositories:
 
716
                    raise AssertionError("didn't expect %r to have "
 
717
                        "fallback_repositories"
 
718
                        % (self.repository,))
 
719
                # this is not paired with an unlock because it's just restoring
 
720
                # the previous state; the lock's released when set_stacked_on_url
 
721
                # returns
 
722
                self.repository.lock_write()
 
723
                # XXX: If you unstack a branch while it has a working tree
 
724
                # with a pending merge, the pending-merged revisions will no
 
725
                # longer be present.  You can (probably) revert and remerge.
 
726
                #
 
727
                # XXX: This only fetches up to the tip of the repository; it
 
728
                # doesn't bring across any tags.  That's fairly consistent
 
729
                # with how branch works, but perhaps not ideal.
 
730
                self.repository.fetch(old_repository,
 
731
                    revision_id=self.last_revision(),
 
732
                    find_ghosts=True)
 
733
            finally:
 
734
                old_repository.unlock()
 
735
        finally:
 
736
            pb.finished()
692
737
 
693
738
    def _set_tags_bytes(self, bytes):
694
739
        """Mirror method for _get_tags_bytes.
2907
2952
    @staticmethod
2908
2953
    def _get_branch_formats_to_test():
2909
2954
        """Return a tuple with the Branch formats to use when testing."""
2910
 
        raise NotImplementedError(self._get_branch_formats_to_test)
 
2955
        raise NotImplementedError(InterBranch._get_branch_formats_to_test)
2911
2956
 
2912
2957
    def pull(self, overwrite=False, stop_revision=None,
2913
2958
             possible_transports=None, local=False):
3068
3113
                _override_hook_source_branch=_override_hook_source_branch)
3069
3114
        finally:
3070
3115
            self.source.unlock()
3071
 
        return result
3072
3116
 
3073
3117
    def _push_with_bound_branches(self, overwrite, stop_revision,
3074
3118
            _override_hook_source_branch=None):