61
62
from bzrlib.store.text import TextStore
62
63
from bzrlib.store.versioned import WeaveStore
63
64
from bzrlib.transactions import WriteTransaction
64
from bzrlib.transport import get_transport
65
from bzrlib.transport import (
66
do_catching_redirections,
65
69
from bzrlib.weave import Weave
68
from bzrlib.trace import mutter, note
72
from bzrlib.trace import (
69
76
from bzrlib.transport.local import LocalTransport
109
116
source_repo_format.check_conversion_target(target_repo_format)
112
def _check_supported(format, allow_unsupported):
113
"""Check whether format is a supported format.
115
If allow_unsupported is True, this is a no-op.
119
def _check_supported(format, allow_unsupported,
120
recommend_upgrade=True,
122
"""Give an error or warning on old formats.
124
:param format: may be any kind of format - workingtree, branch,
127
:param allow_unsupported: If true, allow opening
128
formats that are strongly deprecated, and which may
129
have limited functionality.
131
:param recommend_upgrade: If true (default), warn
132
the user through the ui object that they may wish
133
to upgrade the object.
135
# TODO: perhaps move this into a base Format class; it's not BzrDir
136
# specific. mbp 20070323
117
137
if not allow_unsupported and not format.is_supported():
118
138
# see open_downlevel to open legacy branches.
119
139
raise errors.UnsupportedFormatError(format=format)
140
if recommend_upgrade \
141
and getattr(format, 'upgrade_recommended', False):
142
ui.ui_factory.recommend_upgrade(
143
format.get_format_description(),
121
def clone(self, url, revision_id=None, basis=None, force_new_repo=False):
146
def clone(self, url, revision_id=None, force_new_repo=False):
122
147
"""Clone this bzrdir and its contents to url verbatim.
124
149
If urls last component does not exist, it will be created.
129
154
even if one is available.
131
156
self._make_tail(url)
132
basis_repo, basis_branch, basis_tree = self._get_basis_components(basis)
133
157
result = self._format.initialize(url)
135
159
local_repo = self.find_repository()
140
164
if force_new_repo:
141
165
result_repo = local_repo.clone(
143
revision_id=revision_id,
167
revision_id=revision_id)
145
168
result_repo.set_make_working_trees(local_repo.make_working_trees())
148
171
result_repo = result.find_repository()
149
172
# fetch content this dir needs.
151
# XXX FIXME RBC 20060214 need tests for this when the basis
153
result_repo.fetch(basis_repo, revision_id=revision_id)
154
173
result_repo.fetch(local_repo, revision_id=revision_id)
155
174
except errors.NoRepositoryPresent:
156
175
# needed to make one anyway.
157
176
result_repo = local_repo.clone(
159
revision_id=revision_id,
178
revision_id=revision_id)
161
179
result_repo.set_make_working_trees(local_repo.make_working_trees())
162
180
# 1 if there is a branch present
163
181
# make sure its content is available in the target repository
167
185
except errors.NotBranchError:
170
self.open_workingtree().clone(result, basis=basis_tree)
188
self.open_workingtree().clone(result)
171
189
except (errors.NoWorkingTree, errors.NotLocalUrl):
175
def _get_basis_components(self, basis):
176
"""Retrieve the basis components that are available at basis."""
178
return None, None, None
180
basis_tree = basis.open_workingtree()
181
basis_branch = basis_tree.branch
182
basis_repo = basis_branch.repository
183
except (errors.NoWorkingTree, errors.NotLocalUrl):
186
basis_branch = basis.open_branch()
187
basis_repo = basis_branch.repository
188
except errors.NotBranchError:
191
basis_repo = basis.open_repository()
192
except errors.NoRepositoryPresent:
194
return basis_repo, basis_branch, basis_tree
196
193
# TODO: This should be given a Transport, and should chdir up; otherwise
197
194
# this will open a new connection.
198
195
def _make_tail(self, url):
526
523
:param transport: Transport containing the bzrdir.
527
524
:param _unsupported: private.
529
format = BzrDirFormat.find_format(transport)
526
base = transport.base
528
def find_format(transport):
529
return transport, BzrDirFormat.find_format(transport)
531
def redirected(transport, e, redirection_notice):
532
qualified_source = e.get_source_url()
533
relpath = transport.relpath(qualified_source)
534
if not e.target.endswith(relpath):
535
# Not redirected to a branch-format, not a branch
536
raise errors.NotBranchError(path=e.target)
537
target = e.target[:-len(relpath)]
538
note('%s is%s redirected to %s',
539
transport.base, e.permanently, target)
540
# Let's try with a new transport
541
qualified_target = e.get_target_url()[:-len(relpath)]
542
# FIXME: If 'transport' has a qualifier, this should
543
# be applied again to the new transport *iff* the
544
# schemes used are the same. It's a bit tricky to
545
# verify, so I'll punt for now
547
return get_transport(target)
550
transport, format = do_catching_redirections(find_format,
553
except errors.TooManyRedirections:
554
raise errors.NotBranchError(base)
530
556
BzrDir._check_supported(format, _unsupported)
531
557
return format.open(transport, _found=True)
641
667
workingtree and discards it, and that's somewhat expensive.)
644
self.open_workingtree()
670
self.open_workingtree(recommend_upgrade=False)
646
672
except errors.NoWorkingTree:
649
def _cloning_metadir(self, basis=None):
650
def related_repository(bzrdir):
675
def _cloning_metadir(self):
676
result_format = self._format.__class__()
652
branch = bzrdir.open_branch()
653
return branch.repository
679
branch = self.open_branch()
680
source_repository = branch.repository
654
681
except errors.NotBranchError:
655
682
source_branch = None
656
return bzrdir.open_repository()
657
result_format = self._format.__class__()
660
source_repository = related_repository(self)
661
except errors.NoRepositoryPresent:
664
source_repository = related_repository(self)
683
source_repository = self.open_repository()
665
684
result_format.repository_format = source_repository._format
666
685
except errors.NoRepositoryPresent:
667
686
source_repository = None
669
tree = self.open_workingtree()
688
# TODO: Couldn't we just probe for the format in these cases,
689
# rather than opening the whole tree? It would be a little
690
# faster. mbp 20070401
691
tree = self.open_workingtree(recommend_upgrade=False)
670
692
except (errors.NoWorkingTree, errors.NotLocalUrl):
671
693
result_format.workingtree_format = None
673
695
result_format.workingtree_format = tree._format.__class__()
674
696
return result_format, source_repository
676
def cloning_metadir(self, basis=None):
698
def cloning_metadir(self):
677
699
"""Produce a metadir suitable for cloning or sprouting with.
679
701
These operations may produce workingtrees (yes, even though they're
691
713
def checkout_metadir(self):
692
714
return self.cloning_metadir()
694
def sprout(self, url, revision_id=None, basis=None, force_new_repo=False,
716
def sprout(self, url, revision_id=None, force_new_repo=False,
696
718
"""Create a copy of this bzrdir prepared for use as a new line of
707
729
itself to download less data.
709
731
self._make_tail(url)
710
cloning_format = self.cloning_metadir(basis)
732
cloning_format = self.cloning_metadir()
711
733
result = cloning_format.initialize(url)
712
basis_repo, basis_branch, basis_tree = self._get_basis_components(basis)
714
735
source_branch = self.open_branch()
715
736
source_repository = source_branch.repository
719
740
source_repository = self.open_repository()
720
741
except errors.NoRepositoryPresent:
721
# copy the entire basis one if there is one
722
# but there is no repository.
723
source_repository = basis_repo
742
source_repository = None
724
743
if force_new_repo:
725
744
result_repo = None
741
760
result_repo = result.create_repository()
742
761
if result_repo is not None:
743
762
# fetch needed content into target.
745
# XXX FIXME RBC 20060214 need tests for this when the basis
747
result_repo.fetch(basis_repo, revision_id=revision_id)
748
763
if source_repository is not None:
749
764
result_repo.fetch(source_repository, revision_id=revision_id)
750
765
if source_branch is not None:
810
825
"""Pre-splitout bzrdirs do not suffer from stale locks."""
811
826
raise NotImplementedError(self.break_lock)
813
def clone(self, url, revision_id=None, basis=None, force_new_repo=False):
828
def clone(self, url, revision_id=None, force_new_repo=False):
814
829
"""See BzrDir.clone()."""
815
830
from bzrlib.workingtree import WorkingTreeFormat2
816
831
self._make_tail(url)
817
832
result = self._format._initialize_for_clone(url)
818
basis_repo, basis_branch, basis_tree = self._get_basis_components(basis)
819
self.open_repository().clone(result, revision_id=revision_id, basis=basis_repo)
833
self.open_repository().clone(result, revision_id=revision_id)
820
834
from_branch = self.open_branch()
821
835
from_branch.clone(result, revision_id=revision_id)
823
self.open_workingtree().clone(result, basis=basis_tree)
837
self.open_workingtree().clone(result)
824
838
except errors.NotLocalUrl:
825
839
# make a new one, this format always has to have one.
844
858
def create_workingtree(self, revision_id=None):
845
859
"""See BzrDir.create_workingtree."""
846
860
# this looks buggy but is not -really-
861
# because this format creates the workingtree when the bzrdir is
847
863
# clone and sprout will have set the revision_id
848
864
# and that will have set it for us, its only
849
865
# specific uses of create_workingtree in isolation
850
866
# that can do wonky stuff here, and that only
851
867
# happens for creating checkouts, which cannot be
852
868
# done on this format anyway. So - acceptable wart.
853
result = self.open_workingtree()
869
result = self.open_workingtree(recommend_upgrade=False)
854
870
if revision_id is not None:
855
871
if revision_id == _mod_revision.NULL_REVISION:
856
872
result.set_parent_ids([])
912
928
self._check_supported(format, unsupported)
913
929
return format.open(self, _found=True)
915
def sprout(self, url, revision_id=None, basis=None, force_new_repo=False):
931
def sprout(self, url, revision_id=None, force_new_repo=False):
916
932
"""See BzrDir.sprout()."""
917
933
from bzrlib.workingtree import WorkingTreeFormat2
918
934
self._make_tail(url)
919
935
result = self._format._initialize_for_clone(url)
920
basis_repo, basis_branch, basis_tree = self._get_basis_components(basis)
922
self.open_repository().clone(result, revision_id=revision_id, basis=basis_repo)
937
self.open_repository().clone(result, revision_id=revision_id)
923
938
except errors.NoRepositoryPresent:
962
977
from bzrlib.repofmt.weaverepo import RepositoryFormat5
963
978
return RepositoryFormat5().open(self, _found=True)
965
def open_workingtree(self, _unsupported=False):
980
def open_workingtree(self, _unsupported=False,
981
recommend_upgrade=True):
966
982
"""See BzrDir.create_workingtree."""
967
983
from bzrlib.workingtree import WorkingTreeFormat2
968
return WorkingTreeFormat2().open(self, _found=True)
984
wt_format = WorkingTreeFormat2()
985
# we don't warn here about upgrades; that ought to be handled for the
987
return wt_format.open(self, _found=True)
971
990
class BzrDir6(BzrDirPreSplitOut):
979
998
from bzrlib.repofmt.weaverepo import RepositoryFormat6
980
999
return RepositoryFormat6().open(self, _found=True)
982
def open_workingtree(self, _unsupported=False):
1001
def open_workingtree(self, _unsupported=False,
1002
recommend_upgrade=True):
983
1003
"""See BzrDir.create_workingtree."""
1004
# we don't warn here about upgrades; that ought to be handled for the
984
1006
from bzrlib.workingtree import WorkingTreeFormat2
985
1007
return WorkingTreeFormat2().open(self, _found=True)
1014
1036
def destroy_workingtree(self):
1015
1037
"""See BzrDir.destroy_workingtree."""
1016
wt = self.open_workingtree()
1038
wt = self.open_workingtree(recommend_upgrade=False)
1017
1039
repository = wt.branch.repository
1018
1040
empty = repository.revision_tree(_mod_revision.NULL_REVISION)
1019
1041
wt.revert([], old_tree=empty)
1093
1115
except errors.NotBranchError:
1096
if not isinstance(self.open_workingtree()._format,
1118
my_wt = self.open_workingtree(recommend_upgrade=False)
1119
if not isinstance(my_wt._format,
1097
1120
format.workingtree_format.__class__):
1098
1121
# the workingtree needs an upgrade.
1115
1138
self._check_supported(format, unsupported)
1116
1139
return format.open(self, _found=True)
1118
def open_workingtree(self, unsupported=False):
1141
def open_workingtree(self, unsupported=False,
1142
recommend_upgrade=True):
1119
1143
"""See BzrDir.open_workingtree."""
1120
1144
from bzrlib.workingtree import WorkingTreeFormat
1121
1145
format = WorkingTreeFormat.find_format(self)
1122
self._check_supported(format, unsupported)
1146
self._check_supported(format, unsupported,
1148
basedir=self.root_transport.base)
1123
1149
return format.open(self, _found=True)
1308
1334
def register_control_format(klass, format):
1309
"""Register a format that does not use '.bzrdir' for its control dir.
1335
"""Register a format that does not use '.bzr' for its control dir.
1311
1337
TODO: This should be pulled up into a 'ControlDirFormat' base class
1312
1338
which BzrDirFormat can inherit from, and renamed to register_format
1598
1620
__set_workingtree_format)
1623
# Register bzr control format
1624
BzrDirFormat.register_control_format(BzrDirFormat)
1626
# Register bzr formats
1601
1627
BzrDirFormat.register_format(BzrDirFormat4())
1602
1628
BzrDirFormat.register_format(BzrDirFormat5())
1603
1629
BzrDirFormat.register_format(BzrDirFormat6())
2109
2135
branch_converter = _mod_branch.Converter5to6()
2110
2136
branch_converter.convert(branch)
2112
tree = self.bzrdir.open_workingtree()
2138
tree = self.bzrdir.open_workingtree(recommend_upgrade=False)
2113
2139
except (errors.NoWorkingTree, errors.NotLocalUrl):