47
45
revision as _mod_revision,
53
54
from bzrlib.osutils import (
59
from bzrlib.smart.client import _SmartClient
60
from bzrlib.smart import protocol
58
61
from bzrlib.store.revision.text import TextRevisionStore
59
62
from bzrlib.store.text import TextStore
60
63
from bzrlib.store.versioned import WeaveStore
61
64
from bzrlib.transactions import WriteTransaction
62
from bzrlib.transport import get_transport
65
from bzrlib.transport import (
66
do_catching_redirections,
63
69
from bzrlib.weave import Weave
66
from bzrlib.trace import mutter
72
from bzrlib.trace import (
67
76
from bzrlib.transport.local import LocalTransport
107
118
source_repo_format.check_conversion_target(target_repo_format)
110
def _check_supported(format, allow_unsupported):
111
"""Check whether format is a supported format.
113
If allow_unsupported is True, this is a no-op.
121
def _check_supported(format, allow_unsupported,
122
recommend_upgrade=True,
124
"""Give an error or warning on old formats.
126
:param format: may be any kind of format - workingtree, branch,
129
:param allow_unsupported: If true, allow opening
130
formats that are strongly deprecated, and which may
131
have limited functionality.
133
:param recommend_upgrade: If true (default), warn
134
the user through the ui object that they may wish
135
to upgrade the object.
137
# TODO: perhaps move this into a base Format class; it's not BzrDir
138
# specific. mbp 20070323
115
139
if not allow_unsupported and not format.is_supported():
116
140
# see open_downlevel to open legacy branches.
117
141
raise errors.UnsupportedFormatError(format=format)
142
if recommend_upgrade \
143
and getattr(format, 'upgrade_recommended', False):
144
ui.ui_factory.recommend_upgrade(
145
format.get_format_description(),
119
def clone(self, url, revision_id=None, basis=None, force_new_repo=False):
148
def clone(self, url, revision_id=None, force_new_repo=False):
120
149
"""Clone this bzrdir and its contents to url verbatim.
122
151
If urls last component does not exist, it will be created.
126
155
:param force_new_repo: Do not use a shared repository for the target
127
156
even if one is available.
130
basis_repo, basis_branch, basis_tree = self._get_basis_components(basis)
131
result = self._format.initialize(url)
158
return self.clone_on_transport(get_transport(url),
159
revision_id=revision_id,
160
force_new_repo=force_new_repo)
162
def clone_on_transport(self, transport, revision_id=None,
163
force_new_repo=False):
164
"""Clone this bzrdir and its contents to transport verbatim.
166
If the target directory does not exist, it will be created.
168
if revision_id is not None, then the clone operation may tune
169
itself to download less data.
170
:param force_new_repo: Do not use a shared repository for the target
171
even if one is available.
173
transport.ensure_base()
174
result = self._format.initialize_on_transport(transport)
133
176
local_repo = self.find_repository()
134
177
except errors.NoRepositoryPresent:
138
181
if force_new_repo:
139
182
result_repo = local_repo.clone(
141
revision_id=revision_id,
184
revision_id=revision_id)
143
185
result_repo.set_make_working_trees(local_repo.make_working_trees())
146
188
result_repo = result.find_repository()
147
189
# fetch content this dir needs.
149
# XXX FIXME RBC 20060214 need tests for this when the basis
151
result_repo.fetch(basis_repo, revision_id=revision_id)
152
190
result_repo.fetch(local_repo, revision_id=revision_id)
153
191
except errors.NoRepositoryPresent:
154
192
# needed to make one anyway.
155
193
result_repo = local_repo.clone(
157
revision_id=revision_id,
195
revision_id=revision_id)
159
196
result_repo.set_make_working_trees(local_repo.make_working_trees())
160
197
# 1 if there is a branch present
161
198
# make sure its content is available in the target repository
165
202
except errors.NotBranchError:
168
self.open_workingtree().clone(result, basis=basis_tree)
205
self.open_workingtree().clone(result)
169
206
except (errors.NoWorkingTree, errors.NotLocalUrl):
173
def _get_basis_components(self, basis):
174
"""Retrieve the basis components that are available at basis."""
176
return None, None, None
178
basis_tree = basis.open_workingtree()
179
basis_branch = basis_tree.branch
180
basis_repo = basis_branch.repository
181
except (errors.NoWorkingTree, errors.NotLocalUrl):
184
basis_branch = basis.open_branch()
185
basis_repo = basis_branch.repository
186
except errors.NotBranchError:
189
basis_repo = basis.open_repository()
190
except errors.NoRepositoryPresent:
192
return basis_repo, basis_branch, basis_tree
194
210
# TODO: This should be given a Transport, and should chdir up; otherwise
195
211
# this will open a new connection.
196
212
def _make_tail(self, url):
197
head, tail = urlutils.split(url)
198
if tail and tail != '.':
199
t = get_transport(head)
202
except errors.FileExists:
213
t = get_transport(url)
205
216
# TODO: Should take a Transport
351
357
raise NotImplementedError(self.create_workingtree)
359
def retire_bzrdir(self):
360
"""Permanently disable the bzrdir.
362
This is done by renaming it to give the user some ability to recover
363
if there was a problem.
365
This will have horrible consequences if anyone has anything locked or
368
for i in xrange(10000):
370
to_path = '.bzr.retired.%d' % i
371
self.root_transport.rename('.bzr', to_path)
372
note("renamed %s to %s"
373
% (self.root_transport.abspath('.bzr'), to_path))
375
except (errors.TransportError, IOError, errors.PathError):
353
378
def destroy_workingtree(self):
354
379
"""Destroy the working tree at this BzrDir.
398
if ((found_bzrdir.root_transport.base ==
423
if ((found_bzrdir.root_transport.base ==
399
424
self.root_transport.base) or repository.is_shared()):
400
425
return repository
402
427
raise errors.NoRepositoryPresent(self)
403
428
raise errors.NoRepositoryPresent(self)
430
def get_branch_reference(self):
431
"""Return the referenced URL for the branch in this bzrdir.
433
:raises NotBranchError: If there is no Branch.
434
:return: The URL the branch in this bzrdir references if it is a
435
reference branch, or None for regular branches.
405
439
def get_branch_transport(self, branch_format):
406
440
"""Get the transport for use by branch format in this BzrDir.
432
466
"""Get the transport for use by workingtree format in this BzrDir.
434
468
Note that bzr dirs that do not support format strings will raise
435
IncompatibleFormat if the workingtree format they are given has
436
a format string, and vice versa.
469
IncompatibleFormat if the workingtree format they are given has a
470
format string, and vice versa.
438
472
If workingtree_format is None, the transport is returned with no
439
473
checking. if it is not None, then the returned transport is
499
533
return BzrDir.open_from_transport(t, _unsupported=_unsupported)
502
def open_from_transport(transport, _unsupported=False):
536
def open_from_transport(transport, _unsupported=False,
537
_server_formats=True):
503
538
"""Open a bzrdir within a particular directory.
505
540
:param transport: Transport containing the bzrdir.
506
541
:param _unsupported: private.
508
format = BzrDirFormat.find_format(transport)
543
base = transport.base
545
def find_format(transport):
546
return transport, BzrDirFormat.find_format(
547
transport, _server_formats=_server_formats)
549
def redirected(transport, e, redirection_notice):
550
qualified_source = e.get_source_url()
551
relpath = transport.relpath(qualified_source)
552
if not e.target.endswith(relpath):
553
# Not redirected to a branch-format, not a branch
554
raise errors.NotBranchError(path=e.target)
555
target = e.target[:-len(relpath)]
556
note('%s is%s redirected to %s',
557
transport.base, e.permanently, target)
558
# Let's try with a new transport
559
qualified_target = e.get_target_url()[:-len(relpath)]
560
# FIXME: If 'transport' has a qualifier, this should
561
# be applied again to the new transport *iff* the
562
# schemes used are the same. It's a bit tricky to
563
# verify, so I'll punt for now
565
return get_transport(target)
568
transport, format = do_catching_redirections(find_format,
571
except errors.TooManyRedirections:
572
raise errors.NotBranchError(base)
509
574
BzrDir._check_supported(format, _unsupported)
510
575
return format.open(transport, _found=True)
551
616
return result, urlutils.unescape(a_transport.relpath(url))
552
617
except errors.NotBranchError, e:
554
new_t = a_transport.clone('..')
620
new_t = a_transport.clone('..')
621
except errors.InvalidURLJoin:
622
# reached the root, whatever that may be
623
raise errors.NotBranchError(path=url)
555
624
if new_t.base == a_transport.base:
556
625
# reached the root, whatever that may be
557
626
raise errors.NotBranchError(path=url)
590
659
raise NotImplementedError(self.open_repository)
592
def open_workingtree(self, _unsupported=False):
661
def open_workingtree(self, _unsupported=False,
662
recommend_upgrade=True):
593
663
"""Open the workingtree object at this BzrDir if one is present.
595
TODO: static convenience version of this?
665
:param recommend_upgrade: Optional keyword parameter, when True (the
666
default), emit through the ui module a recommendation that the user
667
upgrade the working tree when the workingtree being opened is old
668
(but still fully supported).
597
670
raise NotImplementedError(self.open_workingtree)
620
693
workingtree and discards it, and that's somewhat expensive.)
623
self.open_workingtree()
696
self.open_workingtree(recommend_upgrade=False)
625
698
except errors.NoWorkingTree:
628
def cloning_metadir(self, basis=None):
701
def _cloning_metadir(self):
629
702
"""Produce a metadir suitable for cloning with"""
630
def related_repository(bzrdir):
703
result_format = self._format.__class__()
632
branch = bzrdir.open_branch()
633
return branch.repository
706
branch = self.open_branch()
707
source_repository = branch.repository
634
708
except errors.NotBranchError:
635
709
source_branch = None
636
return bzrdir.open_repository()
637
result_format = self._format.__class__()
710
source_repository = self.open_repository()
711
except errors.NoRepositoryPresent:
712
source_repository = None
714
# XXX TODO: This isinstance is here because we have not implemented
715
# the fix recommended in bug # 103195 - to delegate this choice the
717
repo_format = source_repository._format
718
if not isinstance(repo_format, remote.RemoteRepositoryFormat):
719
result_format.repository_format = repo_format
640
source_repository = related_repository(self)
641
except errors.NoRepositoryPresent:
644
source_repository = related_repository(self)
645
result_format.repository_format = source_repository._format
646
except errors.NoRepositoryPresent:
650
def sprout(self, url, revision_id=None, basis=None, force_new_repo=False):
721
# TODO: Couldn't we just probe for the format in these cases,
722
# rather than opening the whole tree? It would be a little
723
# faster. mbp 20070401
724
tree = self.open_workingtree(recommend_upgrade=False)
725
except (errors.NoWorkingTree, errors.NotLocalUrl):
726
result_format.workingtree_format = None
728
result_format.workingtree_format = tree._format.__class__()
729
return result_format, source_repository
731
def cloning_metadir(self):
732
"""Produce a metadir suitable for cloning or sprouting with.
734
These operations may produce workingtrees (yes, even though they're
735
"cloning" something that doesn't have a tree, so a viable workingtree
736
format must be selected.
738
format, repository = self._cloning_metadir()
739
if format._workingtree_format is None:
740
if repository is None:
742
tree_format = repository._format._matchingbzrdir.workingtree_format
743
format.workingtree_format = tree_format.__class__()
746
def checkout_metadir(self):
747
return self.cloning_metadir()
749
def sprout(self, url, revision_id=None, force_new_repo=False,
651
751
"""Create a copy of this bzrdir prepared for use as a new line of
661
761
if revision_id is not None, then the clone operation may tune
662
762
itself to download less data.
665
cloning_format = self.cloning_metadir(basis)
666
result = cloning_format.initialize(url)
667
basis_repo, basis_branch, basis_tree = self._get_basis_components(basis)
764
target_transport = get_transport(url)
765
target_transport.ensure_base()
766
cloning_format = self.cloning_metadir()
767
result = cloning_format.initialize_on_transport(target_transport)
669
769
source_branch = self.open_branch()
670
770
source_repository = source_branch.repository
690
788
result.create_repository()
691
789
elif source_repository is not None and result_repo is None:
692
790
# have source, and want to make a new target repo
693
# we don't clone the repo because that preserves attributes
694
# like is_shared(), and we have not yet implemented a
695
# repository sprout().
696
result_repo = result.create_repository()
697
if result_repo is not None:
791
result_repo = source_repository.sprout(result, revision_id=revision_id)
698
793
# fetch needed content into target.
700
# XXX FIXME RBC 20060214 need tests for this when the basis
702
result_repo.fetch(basis_repo, revision_id=revision_id)
703
794
if source_repository is not None:
796
# source_repository.copy_content_into(result_repo, revision_id=revision_id)
797
# so we can override the copy method
704
798
result_repo.fetch(source_repository, revision_id=revision_id)
705
799
if source_branch is not None:
706
800
source_branch.sprout(result, revision_id=revision_id)
710
804
# case that the newly sprouted branch is a remote one
711
805
if result_repo is None or result_repo.make_working_trees():
712
806
wt = result.create_workingtree()
713
if wt.inventory.root is None:
715
wt.set_root_id(self.open_workingtree.get_root_id())
716
except errors.NoWorkingTree:
809
if wt.path2id('') is None:
811
wt.set_root_id(self.open_workingtree.get_root_id())
812
except errors.NoWorkingTree:
818
if recurse == 'down':
820
basis = wt.basis_tree()
822
subtrees = basis.iter_references()
823
recurse_branch = wt.branch
824
elif source_branch is not None:
825
basis = source_branch.basis_tree()
827
subtrees = basis.iter_references()
828
recurse_branch = source_branch
833
for path, file_id in subtrees:
834
target = urlutils.join(url, urlutils.escape(path))
835
sublocation = source_branch.reference_parent(file_id, path)
836
sublocation.bzrdir.sprout(target,
837
basis.get_reference_revision(file_id, path),
838
force_new_repo=force_new_repo, recurse=recurse)
840
if basis is not None:
735
859
"""Pre-splitout bzrdirs do not suffer from stale locks."""
736
860
raise NotImplementedError(self.break_lock)
738
def clone(self, url, revision_id=None, basis=None, force_new_repo=False):
862
def clone(self, url, revision_id=None, force_new_repo=False):
739
863
"""See BzrDir.clone()."""
740
864
from bzrlib.workingtree import WorkingTreeFormat2
741
865
self._make_tail(url)
742
866
result = self._format._initialize_for_clone(url)
743
basis_repo, basis_branch, basis_tree = self._get_basis_components(basis)
744
self.open_repository().clone(result, revision_id=revision_id, basis=basis_repo)
867
self.open_repository().clone(result, revision_id=revision_id)
745
868
from_branch = self.open_branch()
746
869
from_branch.clone(result, revision_id=revision_id)
748
self.open_workingtree().clone(result, basis=basis_tree)
871
self.open_workingtree().clone(result)
749
872
except errors.NotLocalUrl:
750
873
# make a new one, this format always has to have one.
769
892
def create_workingtree(self, revision_id=None):
770
893
"""See BzrDir.create_workingtree."""
771
894
# this looks buggy but is not -really-
895
# because this format creates the workingtree when the bzrdir is
772
897
# clone and sprout will have set the revision_id
773
898
# and that will have set it for us, its only
774
899
# specific uses of create_workingtree in isolation
775
900
# that can do wonky stuff here, and that only
776
901
# happens for creating checkouts, which cannot be
777
902
# done on this format anyway. So - acceptable wart.
778
result = self.open_workingtree()
903
result = self.open_workingtree(recommend_upgrade=False)
779
904
if revision_id is not None:
780
905
if revision_id == _mod_revision.NULL_REVISION:
781
906
result.set_parent_ids([])
837
962
self._check_supported(format, unsupported)
838
963
return format.open(self, _found=True)
840
def sprout(self, url, revision_id=None, basis=None, force_new_repo=False):
965
def sprout(self, url, revision_id=None, force_new_repo=False):
841
966
"""See BzrDir.sprout()."""
842
967
from bzrlib.workingtree import WorkingTreeFormat2
843
968
self._make_tail(url)
844
969
result = self._format._initialize_for_clone(url)
845
basis_repo, basis_branch, basis_tree = self._get_basis_components(basis)
847
self.open_repository().clone(result, revision_id=revision_id, basis=basis_repo)
971
self.open_repository().clone(result, revision_id=revision_id)
848
972
except errors.NoRepositoryPresent:
887
1011
from bzrlib.repofmt.weaverepo import RepositoryFormat5
888
1012
return RepositoryFormat5().open(self, _found=True)
890
def open_workingtree(self, _unsupported=False):
1014
def open_workingtree(self, _unsupported=False,
1015
recommend_upgrade=True):
891
1016
"""See BzrDir.create_workingtree."""
892
1017
from bzrlib.workingtree import WorkingTreeFormat2
893
return WorkingTreeFormat2().open(self, _found=True)
1018
wt_format = WorkingTreeFormat2()
1019
# we don't warn here about upgrades; that ought to be handled for the
1021
return wt_format.open(self, _found=True)
896
1024
class BzrDir6(BzrDirPreSplitOut):
904
1032
from bzrlib.repofmt.weaverepo import RepositoryFormat6
905
1033
return RepositoryFormat6().open(self, _found=True)
907
def open_workingtree(self, _unsupported=False):
1035
def open_workingtree(self, _unsupported=False,
1036
recommend_upgrade=True):
908
1037
"""See BzrDir.create_workingtree."""
1038
# we don't warn here about upgrades; that ought to be handled for the
909
1040
from bzrlib.workingtree import WorkingTreeFormat2
910
1041
return WorkingTreeFormat2().open(self, _found=True)
934
1065
def create_workingtree(self, revision_id=None):
935
1066
"""See BzrDir.create_workingtree."""
936
1067
from bzrlib.workingtree import WorkingTreeFormat
937
return WorkingTreeFormat.get_default_format().initialize(self, revision_id)
1068
return self._format.workingtree_format.initialize(self, revision_id)
939
1070
def destroy_workingtree(self):
940
1071
"""See BzrDir.destroy_workingtree."""
941
wt = self.open_workingtree()
1072
wt = self.open_workingtree(recommend_upgrade=False)
942
1073
repository = wt.branch.repository
943
1074
empty = repository.revision_tree(_mod_revision.NULL_REVISION)
944
1075
wt.revert([], old_tree=empty)
947
1078
def destroy_workingtree_metadata(self):
948
1079
self.transport.delete_tree('checkout')
1081
def find_branch_format(self):
1082
"""Find the branch 'format' for this bzrdir.
1084
This might be a synthetic object for e.g. RemoteBranch and SVN.
1086
from bzrlib.branch import BranchFormat
1087
return BranchFormat.find_format(self)
950
1089
def _get_mkdir_mode(self):
951
1090
"""Figure out the mode to use when creating a bzrdir subdir."""
952
1091
temp_control = lockable_files.LockableFiles(self.transport, '',
953
1092
lockable_files.TransportLock)
954
1093
return temp_control._dir_mode
1095
def get_branch_reference(self):
1096
"""See BzrDir.get_branch_reference()."""
1097
from bzrlib.branch import BranchFormat
1098
format = BranchFormat.find_format(self)
1099
return format.get_reference(self)
956
1101
def get_branch_transport(self, branch_format):
957
1102
"""See BzrDir.get_branch_transport()."""
958
1103
if branch_format is None:
1014
1159
if not isinstance(self.open_branch()._format,
1015
1160
format.get_branch_format().__class__):
1016
# the repository needs an upgrade.
1161
# the branch needs an upgrade.
1018
1163
except errors.NotBranchError:
1020
# currently there are no other possible conversions for meta1 formats.
1166
my_wt = self.open_workingtree(recommend_upgrade=False)
1167
if not isinstance(my_wt._format,
1168
format.workingtree_format.__class__):
1169
# the workingtree needs an upgrade.
1171
except (errors.NoWorkingTree, errors.NotLocalUrl):
1023
1175
def open_branch(self, unsupported=False):
1024
1176
"""See BzrDir.open_branch."""
1025
from bzrlib.branch import BranchFormat
1026
format = BranchFormat.find_format(self)
1177
format = self.find_branch_format()
1027
1178
self._check_supported(format, unsupported)
1028
1179
return format.open(self, _found=True)
1034
1185
self._check_supported(format, unsupported)
1035
1186
return format.open(self, _found=True)
1037
def open_workingtree(self, unsupported=False):
1188
def open_workingtree(self, unsupported=False,
1189
recommend_upgrade=True):
1038
1190
"""See BzrDir.open_workingtree."""
1039
1191
from bzrlib.workingtree import WorkingTreeFormat
1040
1192
format = WorkingTreeFormat.find_format(self)
1041
self._check_supported(format, unsupported)
1193
self._check_supported(format, unsupported,
1195
basedir=self.root_transport.base)
1042
1196
return format.open(self, _found=True)
1071
1225
This is a list of BzrDirFormat objects.
1228
_control_server_formats = []
1229
"""The registered control server formats, e.g. RemoteBzrDirs.
1231
This is a list of BzrDirFormat objects.
1074
1234
_lock_file_name = 'branch-lock'
1076
1236
# _lock_class must be set in subclasses to the lock type, typ.
1077
1237
# TransportLock or LockDir
1080
def find_format(klass, transport):
1240
def find_format(klass, transport, _server_formats=True):
1081
1241
"""Return the format present at transport."""
1082
for format in klass._control_formats:
1243
formats = klass._control_server_formats + klass._control_formats
1245
formats = klass._control_formats
1246
for format in formats:
1084
1248
return format.probe_transport(transport)
1085
1249
except errors.NotBranchError:
1235
1399
klass._control_formats.append(format)
1402
def register_control_server_format(klass, format):
1403
"""Register a control format for client-server environments.
1405
These formats will be tried before ones registered with
1406
register_control_format. This gives implementations that decide to the
1407
chance to grab it before anything looks at the contents of the format
1410
klass._control_server_formats.append(format)
1238
1413
@symbol_versioning.deprecated_method(symbol_versioning.zero_fourteen)
1239
1414
def set_default_format(klass, format):
1240
1415
klass._set_default_format(format)
1492
1676
repository_format = property(__return_repository_format, __set_repository_format)
1678
def __get_workingtree_format(self):
1679
if self._workingtree_format is None:
1680
from bzrlib.workingtree import WorkingTreeFormat
1681
self._workingtree_format = WorkingTreeFormat.get_default_format()
1682
return self._workingtree_format
1684
def __set_workingtree_format(self, wt_format):
1685
self._workingtree_format = wt_format
1687
workingtree_format = property(__get_workingtree_format,
1688
__set_workingtree_format)
1691
# Register bzr control format
1692
BzrDirFormat.register_control_format(BzrDirFormat)
1694
# Register bzr formats
1495
1695
BzrDirFormat.register_format(BzrDirFormat4())
1496
1696
BzrDirFormat.register_format(BzrDirFormat5())
1497
1697
BzrDirFormat.register_format(BzrDirFormat6())
1509
1709
easy to identify.
1512
def __init__(self, transport_server, transport_readonly_server, formats):
1712
def __init__(self, vfs_factory, transport_server, transport_readonly_server,
1714
"""Create an object to adapt tests.
1716
:param vfs_server: A factory to create a Transport Server which has
1717
all the VFS methods working, and is writable.
1719
self._vfs_factory = vfs_factory
1513
1720
self._transport_server = transport_server
1514
1721
self._transport_readonly_server = transport_readonly_server
1515
1722
self._formats = formats
2000
2210
_mod_branch.BzrBranchFormat6):
2001
2211
branch_converter = _mod_branch.Converter5to6()
2002
2212
branch_converter.convert(branch)
2214
tree = self.bzrdir.open_workingtree(recommend_upgrade=False)
2215
except (errors.NoWorkingTree, errors.NotLocalUrl):
2218
# TODO: conversions of Branch and Tree should be done by
2219
# InterXFormat lookups
2220
if (isinstance(tree, workingtree.WorkingTree3) and
2221
not isinstance(tree, workingtree_4.WorkingTree4) and
2222
isinstance(self.target_format.workingtree_format,
2223
workingtree_4.WorkingTreeFormat4)):
2224
workingtree_4.Converter3to4().convert(tree)
2003
2225
return to_convert
2228
# This is not in remote.py because it's small, and needs to be registered.
2229
# Putting it in remote.py creates a circular import problem.
2230
# we can make it a lazy object if the control formats is turned into something
2232
class RemoteBzrDirFormat(BzrDirMetaFormat1):
2233
"""Format representing bzrdirs accessed via a smart server"""
2235
def get_format_description(self):
2236
return 'bzr remote bzrdir'
2239
def probe_transport(klass, transport):
2240
"""Return a RemoteBzrDirFormat object if it looks possible."""
2242
client = transport.get_smart_client()
2243
except (NotImplementedError, AttributeError,
2244
errors.TransportNotPossible):
2245
# no smart server, so not a branch for this format type.
2246
raise errors.NotBranchError(path=transport.base)
2248
# Send a 'hello' request in protocol version one, and decline to
2249
# open it if the server doesn't support our required version (2) so
2250
# that the VFS-based transport will do it.
2251
request = client.get_request()
2252
smart_protocol = protocol.SmartClientRequestProtocolOne(request)
2253
server_version = smart_protocol.query_version()
2254
if server_version != 2:
2255
raise errors.NotBranchError(path=transport.base)
2258
def initialize_on_transport(self, transport):
2260
# hand off the request to the smart server
2261
medium = transport.get_smart_medium()
2262
except errors.NoSmartMedium:
2263
# TODO: lookup the local format from a server hint.
2264
local_dir_format = BzrDirMetaFormat1()
2265
return local_dir_format.initialize_on_transport(transport)
2266
client = _SmartClient(medium)
2267
path = client.remote_path_from_transport(transport)
2268
response = _SmartClient(medium).call('BzrDirFormat.initialize', path)
2269
assert response[0] in ('ok', ), 'unexpected response code %s' % (response,)
2270
return remote.RemoteBzrDir(transport)
2272
def _open(self, transport):
2273
return remote.RemoteBzrDir(transport)
2275
def __eq__(self, other):
2276
if not isinstance(other, RemoteBzrDirFormat):
2278
return self.get_format_description() == other.get_format_description()
2281
BzrDirFormat.register_control_server_format(RemoteBzrDirFormat)
2006
2284
class BzrDirFormatInfo(object):
2008
def __init__(self, native, deprecated):
2286
def __init__(self, native, deprecated, hidden):
2009
2287
self.deprecated = deprecated
2010
2288
self.native = native
2289
self.hidden = hidden
2013
2292
class BzrDirFormatRegistry(registry.Registry):
2017
2296
e.g. BzrDirMeta1 with weave repository. Also, it's more user-oriented.
2020
def register_metadir(self, key, repo, help, native=True, deprecated=False,
2021
branch_format=None):
2299
def register_metadir(self, key,
2300
repository_format, help, native=True, deprecated=False,
2022
2304
"""Register a metadir subformat.
2024
2306
These all use a BzrDirMetaFormat1 bzrdir, but can be parameterized
2025
2307
by the Repository format.
2027
:param repo: The fully-qualified repository format class name as a
2309
:param repository_format: The fully-qualified repository format class
2311
:param branch_format: Fully-qualified branch format class name as
2313
:param tree_format: Fully-qualified tree format class name as
2030
2316
# This should be expanded to support setting WorkingTree and Branch
2031
2317
# formats, once BzrDirMetaFormat1 supports that.
2033
import bzrlib.branch
2034
mod_name, repo_factory_name = repo.rsplit('.', 1)
2318
def _load(full_name):
2319
mod_name, factory_name = full_name.rsplit('.', 1)
2036
2321
mod = __import__(mod_name, globals(), locals(),
2037
[repo_factory_name])
2038
2323
except ImportError, e:
2039
raise ImportError('failed to load repository %s: %s'
2324
raise ImportError('failed to load %s: %s' % (full_name, e))
2042
repo_format_class = getattr(mod, repo_factory_name)
2326
factory = getattr(mod, factory_name)
2043
2327
except AttributeError:
2044
raise AttributeError('no repository format %r in module %r'
2328
raise AttributeError('no factory %s in module %r'
2046
2333
bd = BzrDirMetaFormat1()
2047
bd.repository_format = repo_format_class()
2048
2334
if branch_format is not None:
2049
bd.set_branch_format(getattr(bzrlib.branch, branch_format)())
2335
bd.set_branch_format(_load(branch_format))
2336
if tree_format is not None:
2337
bd.workingtree_format = _load(tree_format)
2338
if repository_format is not None:
2339
bd.repository_format = _load(repository_format)
2051
self.register(key, helper, help, native, deprecated)
2341
self.register(key, helper, help, native, deprecated, hidden)
2053
def register(self, key, factory, help, native=True, deprecated=False):
2343
def register(self, key, factory, help, native=True, deprecated=False,
2054
2345
"""Register a BzrDirFormat factory.
2056
2347
The factory must be a callable that takes one parameter: the key.
2060
2351
supplied directly.
2062
2353
registry.Registry.register(self, key, factory, help,
2063
BzrDirFormatInfo(native, deprecated))
2354
BzrDirFormatInfo(native, deprecated, hidden))
2065
2356
def register_lazy(self, key, module_name, member_name, help, native=True,
2357
deprecated=False, hidden=False):
2067
2358
registry.Registry.register_lazy(self, key, module_name, member_name,
2068
help, BzrDirFormatInfo(native, deprecated))
2359
help, BzrDirFormatInfo(native, deprecated, hidden))
2070
2361
def set_default(self, key):
2071
2362
"""Set the 'default' key to be a clone of the supplied key.
2141
2434
deprecated=True)
2142
2435
format_registry.register_metadir('knit',
2143
2436
'bzrlib.repofmt.knitrepo.RepositoryFormatKnit1',
2144
'Format using knits. Recommended.',
2145
branch_format='BzrBranchFormat5')
2146
format_registry.set_default('knit')
2437
'Format using knits. Recommended for interoperation with bzr <= 0.14.',
2438
branch_format='bzrlib.branch.BzrBranchFormat5',
2439
tree_format='bzrlib.workingtree.WorkingTreeFormat3')
2147
2440
format_registry.register_metadir('metaweave',
2148
2441
'bzrlib.repofmt.weaverepo.RepositoryFormat7',
2149
2442
'Transitional format in 0.8. Slower than knit.',
2152
format_registry.register_metadir('experimental-knit2',
2153
'bzrlib.repofmt.knitrepo.RepositoryFormatKnit2',
2154
'Experimental successor to knit. Use at your own risk.',
2155
branch_format='BzrBranchFormat5')
2156
format_registry.register_metadir('experimental-branch6',
2157
'bzrlib.repofmt.knitrepo.RepositoryFormatKnit1',
2158
'Experimental successor to knit. Use at your own risk.',
2159
branch_format='BzrBranchFormat6')
2443
branch_format='bzrlib.branch.BzrBranchFormat5',
2444
tree_format='bzrlib.workingtree.WorkingTreeFormat3',
2446
format_registry.register_metadir('dirstate',
2447
'bzrlib.repofmt.knitrepo.RepositoryFormatKnit1',
2448
help='New in 0.15: Fast local operations. Compatible with bzr 0.8 and '
2449
'above when accessed over the network.',
2450
branch_format='bzrlib.branch.BzrBranchFormat5',
2451
# this uses bzrlib.workingtree.WorkingTreeFormat4 because importing
2452
# directly from workingtree_4 triggers a circular import.
2453
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
2455
format_registry.register_metadir('dirstate-tags',
2456
'bzrlib.repofmt.knitrepo.RepositoryFormatKnit1',
2457
help='New in 0.15: Fast local operations and improved scaling for '
2458
'network operations. Additionally adds support for tags.'
2459
' Incompatible with bzr < 0.15.',
2460
branch_format='bzrlib.branch.BzrBranchFormat6',
2461
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
2463
format_registry.register_metadir('dirstate-with-subtree',
2464
'bzrlib.repofmt.knitrepo.RepositoryFormatKnit3',
2465
help='New in 0.15: Fast local operations and improved scaling for '
2466
'network operations. Additionally adds support for versioning nested '
2467
'bzr branches. Incompatible with bzr < 0.15.',
2468
branch_format='bzrlib.branch.BzrBranchFormat6',
2469
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
2472
format_registry.set_default('dirstate')