60
61
from bzrlib.store.text import TextStore
61
62
from bzrlib.store.versioned import WeaveStore
62
63
from bzrlib.transactions import WriteTransaction
63
from bzrlib.transport import get_transport
64
from bzrlib.transport import (
65
do_catching_redirections,
64
68
from bzrlib.weave import Weave
67
from bzrlib.trace import mutter, note
71
from bzrlib.trace import (
68
75
from bzrlib.transport.local import LocalTransport
110
117
source_repo_format.check_conversion_target(target_repo_format)
113
def _check_supported(format, allow_unsupported):
114
"""Check whether format is a supported format.
116
If allow_unsupported is True, this is a no-op.
120
def _check_supported(format, allow_unsupported,
121
recommend_upgrade=True,
123
"""Give an error or warning on old formats.
125
:param format: may be any kind of format - workingtree, branch,
128
:param allow_unsupported: If true, allow opening
129
formats that are strongly deprecated, and which may
130
have limited functionality.
132
:param recommend_upgrade: If true (default), warn
133
the user through the ui object that they may wish
134
to upgrade the object.
136
# TODO: perhaps move this into a base Format class; it's not BzrDir
137
# specific. mbp 20070323
118
138
if not allow_unsupported and not format.is_supported():
119
139
# see open_downlevel to open legacy branches.
120
140
raise errors.UnsupportedFormatError(format=format)
141
if recommend_upgrade \
142
and getattr(format, 'upgrade_recommended', False):
143
ui.ui_factory.recommend_upgrade(
144
format.get_format_description(),
122
def clone(self, url, revision_id=None, basis=None, force_new_repo=False):
147
def clone(self, url, revision_id=None, force_new_repo=False):
123
148
"""Clone this bzrdir and its contents to url verbatim.
125
150
If urls last component does not exist, it will be created.
130
155
even if one is available.
132
157
self._make_tail(url)
133
basis_repo, basis_branch, basis_tree = self._get_basis_components(basis)
134
158
result = self._format.initialize(url)
136
160
local_repo = self.find_repository()
141
165
if force_new_repo:
142
166
result_repo = local_repo.clone(
144
revision_id=revision_id,
168
revision_id=revision_id)
146
169
result_repo.set_make_working_trees(local_repo.make_working_trees())
149
172
result_repo = result.find_repository()
150
173
# fetch content this dir needs.
152
# XXX FIXME RBC 20060214 need tests for this when the basis
154
result_repo.fetch(basis_repo, revision_id=revision_id)
155
174
result_repo.fetch(local_repo, revision_id=revision_id)
156
175
except errors.NoRepositoryPresent:
157
176
# needed to make one anyway.
158
177
result_repo = local_repo.clone(
160
revision_id=revision_id,
179
revision_id=revision_id)
162
180
result_repo.set_make_working_trees(local_repo.make_working_trees())
163
181
# 1 if there is a branch present
164
182
# make sure its content is available in the target repository
168
186
except errors.NotBranchError:
171
self.open_workingtree().clone(result, basis=basis_tree)
189
self.open_workingtree().clone(result)
172
190
except (errors.NoWorkingTree, errors.NotLocalUrl):
176
def _get_basis_components(self, basis):
177
"""Retrieve the basis components that are available at basis."""
179
return None, None, None
181
basis_tree = basis.open_workingtree()
182
basis_branch = basis_tree.branch
183
basis_repo = basis_branch.repository
184
except (errors.NoWorkingTree, errors.NotLocalUrl):
187
basis_branch = basis.open_branch()
188
basis_repo = basis_branch.repository
189
except errors.NotBranchError:
192
basis_repo = basis.open_repository()
193
except errors.NoRepositoryPresent:
195
return basis_repo, basis_branch, basis_tree
197
194
# TODO: This should be given a Transport, and should chdir up; otherwise
198
195
# this will open a new connection.
199
196
def _make_tail(self, url):
536
533
:param transport: Transport containing the bzrdir.
537
534
:param _unsupported: private.
539
format = BzrDirFormat.find_format(transport)
536
base = transport.base
538
def find_format(transport):
539
return transport, BzrDirFormat.find_format(transport)
541
def redirected(transport, e, redirection_notice):
542
qualified_source = e.get_source_url()
543
relpath = transport.relpath(qualified_source)
544
if not e.target.endswith(relpath):
545
# Not redirected to a branch-format, not a branch
546
raise errors.NotBranchError(path=e.target)
547
target = e.target[:-len(relpath)]
548
note('%s is%s redirected to %s',
549
transport.base, e.permanently, target)
550
# Let's try with a new transport
551
qualified_target = e.get_target_url()[:-len(relpath)]
552
# FIXME: If 'transport' has a qualifier, this should
553
# be applied again to the new transport *iff* the
554
# schemes used are the same. It's a bit tricky to
555
# verify, so I'll punt for now
557
return get_transport(target)
560
transport, format = do_catching_redirections(find_format,
563
except errors.TooManyRedirections:
564
raise errors.NotBranchError(base)
540
566
BzrDir._check_supported(format, _unsupported)
541
567
return format.open(transport, _found=True)
625
651
raise NotImplementedError(self.open_repository)
627
def open_workingtree(self, _unsupported=False):
653
def open_workingtree(self, _unsupported=False,
654
recommend_upgrade=True):
628
655
"""Open the workingtree object at this BzrDir if one is present.
630
657
TODO: static convenience version of this?
655
682
workingtree and discards it, and that's somewhat expensive.)
658
self.open_workingtree()
685
self.open_workingtree(recommend_upgrade=False)
660
687
except errors.NoWorkingTree:
663
690
def _cloning_metadir(self):
664
691
"""Produce a metadir suitable for cloning with"""
665
def related_repository(bzrdir):
692
result_format = self._format.__class__()
667
branch = bzrdir.open_branch()
668
return branch.repository
695
branch = self.open_branch()
696
source_repository = branch.repository
669
697
except errors.NotBranchError:
670
698
source_branch = None
671
return bzrdir.open_repository()
672
result_format = self._format.__class__()
674
source_repository = related_repository(self)
699
source_repository = self.open_repository()
675
700
except errors.NoRepositoryPresent:
676
701
source_repository = None
703
# XXX TODO: This isinstance is here because we have not implemented
704
# the fix recommended in bug # 103195 - to delegate this choice the
678
706
repo_format = source_repository._format
679
707
if not isinstance(repo_format, remote.RemoteRepositoryFormat):
680
708
result_format.repository_format = repo_format
682
tree = self.open_workingtree()
710
# TODO: Couldn't we just probe for the format in these cases,
711
# rather than opening the whole tree? It would be a little
712
# faster. mbp 20070401
713
tree = self.open_workingtree(recommend_upgrade=False)
683
714
except (errors.NoWorkingTree, errors.NotLocalUrl):
684
715
result_format.workingtree_format = None
704
735
def checkout_metadir(self):
705
736
return self.cloning_metadir()
707
def sprout(self, url, revision_id=None, basis=None, force_new_repo=False,
738
def sprout(self, url, revision_id=None, force_new_repo=False,
709
740
"""Create a copy of this bzrdir prepared for use as a new line of
722
753
self._make_tail(url)
723
754
cloning_format = self.cloning_metadir()
724
755
result = cloning_format.initialize(url)
725
basis_repo, basis_branch, basis_tree = self._get_basis_components(basis)
727
757
source_branch = self.open_branch()
728
758
source_repository = source_branch.repository
732
762
source_repository = self.open_repository()
733
763
except errors.NoRepositoryPresent:
734
# copy the entire basis one if there is one
735
# but there is no repository.
736
source_repository = basis_repo
764
source_repository = None
737
765
if force_new_repo:
738
766
result_repo = None
754
782
result_repo = result.create_repository()
755
783
if result_repo is not None:
756
784
# fetch needed content into target.
758
# XXX FIXME RBC 20060214 need tests for this when the basis
760
result_repo.fetch(basis_repo, revision_id=revision_id)
761
785
if source_repository is not None:
762
786
result_repo.fetch(source_repository, revision_id=revision_id)
763
787
if source_branch is not None:
823
847
"""Pre-splitout bzrdirs do not suffer from stale locks."""
824
848
raise NotImplementedError(self.break_lock)
826
def clone(self, url, revision_id=None, basis=None, force_new_repo=False):
850
def clone(self, url, revision_id=None, force_new_repo=False):
827
851
"""See BzrDir.clone()."""
828
852
from bzrlib.workingtree import WorkingTreeFormat2
829
853
self._make_tail(url)
830
854
result = self._format._initialize_for_clone(url)
831
basis_repo, basis_branch, basis_tree = self._get_basis_components(basis)
832
self.open_repository().clone(result, revision_id=revision_id, basis=basis_repo)
855
self.open_repository().clone(result, revision_id=revision_id)
833
856
from_branch = self.open_branch()
834
857
from_branch.clone(result, revision_id=revision_id)
836
self.open_workingtree().clone(result, basis=basis_tree)
859
self.open_workingtree().clone(result)
837
860
except errors.NotLocalUrl:
838
861
# make a new one, this format always has to have one.
857
880
def create_workingtree(self, revision_id=None):
858
881
"""See BzrDir.create_workingtree."""
859
882
# this looks buggy but is not -really-
883
# because this format creates the workingtree when the bzrdir is
860
885
# clone and sprout will have set the revision_id
861
886
# and that will have set it for us, its only
862
887
# specific uses of create_workingtree in isolation
863
888
# that can do wonky stuff here, and that only
864
889
# happens for creating checkouts, which cannot be
865
890
# done on this format anyway. So - acceptable wart.
866
result = self.open_workingtree()
891
result = self.open_workingtree(recommend_upgrade=False)
867
892
if revision_id is not None:
868
893
if revision_id == _mod_revision.NULL_REVISION:
869
894
result.set_parent_ids([])
925
950
self._check_supported(format, unsupported)
926
951
return format.open(self, _found=True)
928
def sprout(self, url, revision_id=None, basis=None, force_new_repo=False):
953
def sprout(self, url, revision_id=None, force_new_repo=False):
929
954
"""See BzrDir.sprout()."""
930
955
from bzrlib.workingtree import WorkingTreeFormat2
931
956
self._make_tail(url)
932
957
result = self._format._initialize_for_clone(url)
933
basis_repo, basis_branch, basis_tree = self._get_basis_components(basis)
935
self.open_repository().clone(result, revision_id=revision_id, basis=basis_repo)
959
self.open_repository().clone(result, revision_id=revision_id)
936
960
except errors.NoRepositoryPresent:
975
999
from bzrlib.repofmt.weaverepo import RepositoryFormat5
976
1000
return RepositoryFormat5().open(self, _found=True)
978
def open_workingtree(self, _unsupported=False):
1002
def open_workingtree(self, _unsupported=False,
1003
recommend_upgrade=True):
979
1004
"""See BzrDir.create_workingtree."""
980
1005
from bzrlib.workingtree import WorkingTreeFormat2
981
return WorkingTreeFormat2().open(self, _found=True)
1006
wt_format = WorkingTreeFormat2()
1007
# we don't warn here about upgrades; that ought to be handled for the
1009
return wt_format.open(self, _found=True)
984
1012
class BzrDir6(BzrDirPreSplitOut):
992
1020
from bzrlib.repofmt.weaverepo import RepositoryFormat6
993
1021
return RepositoryFormat6().open(self, _found=True)
995
def open_workingtree(self, _unsupported=False):
1023
def open_workingtree(self, _unsupported=False,
1024
recommend_upgrade=True):
996
1025
"""See BzrDir.create_workingtree."""
1026
# we don't warn here about upgrades; that ought to be handled for the
997
1028
from bzrlib.workingtree import WorkingTreeFormat2
998
1029
return WorkingTreeFormat2().open(self, _found=True)
1027
1058
def destroy_workingtree(self):
1028
1059
"""See BzrDir.destroy_workingtree."""
1029
wt = self.open_workingtree()
1060
wt = self.open_workingtree(recommend_upgrade=False)
1030
1061
repository = wt.branch.repository
1031
1062
empty = repository.revision_tree(_mod_revision.NULL_REVISION)
1032
1063
wt.revert([], old_tree=empty)
1120
1151
except errors.NotBranchError:
1123
if not isinstance(self.open_workingtree()._format,
1154
my_wt = self.open_workingtree(recommend_upgrade=False)
1155
if not isinstance(my_wt._format,
1124
1156
format.workingtree_format.__class__):
1125
1157
# the workingtree needs an upgrade.
1141
1173
self._check_supported(format, unsupported)
1142
1174
return format.open(self, _found=True)
1144
def open_workingtree(self, unsupported=False):
1176
def open_workingtree(self, unsupported=False,
1177
recommend_upgrade=True):
1145
1178
"""See BzrDir.open_workingtree."""
1146
1179
from bzrlib.workingtree import WorkingTreeFormat
1147
1180
format = WorkingTreeFormat.find_format(self)
1148
self._check_supported(format, unsupported)
1181
self._check_supported(format, unsupported,
1183
basedir=self.root_transport.base)
1149
1184
return format.open(self, _found=True)
1334
1369
def register_control_format(klass, format):
1335
"""Register a format that does not use '.bzrdir' for its control dir.
1370
"""Register a format that does not use '.bzr' for its control dir.
1337
1372
TODO: This should be pulled up into a 'ControlDirFormat' base class
1338
1373
which BzrDirFormat can inherit from, and renamed to register_format
1624
1655
__set_workingtree_format)
1658
# Register bzr control format
1659
BzrDirFormat.register_control_format(BzrDirFormat)
1661
# Register bzr formats
1627
1662
BzrDirFormat.register_format(BzrDirFormat4())
1628
1663
BzrDirFormat.register_format(BzrDirFormat5())
1629
1664
BzrDirFormat.register_format(BzrDirFormat6())
2143
2178
branch_converter = _mod_branch.Converter5to6()
2144
2179
branch_converter.convert(branch)
2146
tree = self.bzrdir.open_workingtree()
2181
tree = self.bzrdir.open_workingtree(recommend_upgrade=False)
2147
2182
except (errors.NoWorkingTree, errors.NotLocalUrl):