~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/branch.py

(spiv) Fix Branch._unstack to work with repeatedly locked RemoteBranch
 objects. (#551525) (Andrew Bennetts)

Show diffs side-by-side

added added

removed removed

Lines of Context:
801
801
            if len(old_repository._fallback_repositories) != 1:
802
802
                raise AssertionError("can't cope with fallback repositories "
803
803
                    "of %r" % (self.repository,))
804
 
            # unlock it, including unlocking the fallback
 
804
            # Open the new repository object.
 
805
            # Repositories don't offer an interface to remove fallback
 
806
            # repositories today; take the conceptually simpler option and just
 
807
            # reopen it.  We reopen it starting from the URL so that we
 
808
            # get a separate connection for RemoteRepositories and can
 
809
            # stream from one of them to the other.  This does mean doing
 
810
            # separate SSH connection setup, but unstacking is not a
 
811
            # common operation so it's tolerable.
 
812
            new_bzrdir = bzrdir.BzrDir.open(self.bzrdir.root_transport.base)
 
813
            new_repository = new_bzrdir.find_repository()
 
814
            if new_repository._fallback_repositories:
 
815
                raise AssertionError("didn't expect %r to have "
 
816
                    "fallback_repositories"
 
817
                    % (self.repository,))
 
818
            # Replace self.repository with the new repository.
 
819
            # Do our best to transfer the lock state (i.e. lock-tokens and
 
820
            # lock count) of self.repository to the new repository.
 
821
            lock_token = old_repository.lock_write().repository_token
 
822
            self.repository = new_repository
 
823
            if isinstance(self, remote.RemoteBranch):
 
824
                # Remote branches can have a second reference to the old
 
825
                # repository that need to be replaced.
 
826
                if self._real_branch is not None:
 
827
                    self._real_branch.repository = new_repository
 
828
            self.repository.lock_write(token=lock_token)
 
829
            if lock_token is not None:
 
830
                old_repository.leave_lock_in_place()
805
831
            old_repository.unlock()
 
832
            if lock_token is not None:
 
833
                # XXX: self.repository.leave_lock_in_place() before this
 
834
                # function will not be preserved.  Fortunately that doesn't
 
835
                # affect the current default format (2a), and would be a
 
836
                # corner-case anyway.
 
837
                #  - Andrew Bennetts, 2010/06/30
 
838
                self.repository.dont_leave_lock_in_place()
 
839
            old_lock_count = 0
 
840
            while True:
 
841
                try:
 
842
                    old_repository.unlock()
 
843
                except errors.LockNotHeld:
 
844
                    break
 
845
                old_lock_count += 1
 
846
            if old_lock_count == 0:
 
847
                raise AssertionError(
 
848
                    'old_repository should have been locked at least once.')
 
849
            for i in range(old_lock_count-1):
 
850
                self.repository.lock_write()
 
851
            # Fetch from the old repository into the new.
806
852
            old_repository.lock_read()
807
853
            try:
808
 
                # Repositories don't offer an interface to remove fallback
809
 
                # repositories today; take the conceptually simpler option and just
810
 
                # reopen it.  We reopen it starting from the URL so that we
811
 
                # get a separate connection for RemoteRepositories and can
812
 
                # stream from one of them to the other.  This does mean doing
813
 
                # separate SSH connection setup, but unstacking is not a
814
 
                # common operation so it's tolerable.
815
 
                new_bzrdir = bzrdir.BzrDir.open(self.bzrdir.root_transport.base)
816
 
                new_repository = new_bzrdir.find_repository()
817
 
                self.repository = new_repository
818
 
                if self.repository._fallback_repositories:
819
 
                    raise AssertionError("didn't expect %r to have "
820
 
                        "fallback_repositories"
821
 
                        % (self.repository,))
822
 
                # this is not paired with an unlock because it's just restoring
823
 
                # the previous state; the lock's released when set_stacked_on_url
824
 
                # returns
825
 
                self.repository.lock_write()
826
854
                # XXX: If you unstack a branch while it has a working tree
827
855
                # with a pending merge, the pending-merged revisions will no
828
856
                # longer be present.  You can (probably) revert and remerge.