119
86
"""Return true if this bzrdir is one whose format we can convert from."""
122
def check_conversion_target(self, target_format):
123
target_repo_format = target_format.repository_format
124
source_repo_format = self._format.repository_format
125
source_repo_format.check_conversion_target(target_repo_format)
128
def _check_supported(format, allow_unsupported,
129
recommend_upgrade=True,
131
"""Give an error or warning on old formats.
133
:param format: may be any kind of format - workingtree, branch,
136
:param allow_unsupported: If true, allow opening
137
formats that are strongly deprecated, and which may
138
have limited functionality.
140
:param recommend_upgrade: If true (default), warn
141
the user through the ui object that they may wish
142
to upgrade the object.
90
def _check_supported(format, allow_unsupported):
91
"""Check whether format is a supported format.
93
If allow_unsupported is True, this is a no-op.
144
# TODO: perhaps move this into a base Format class; it's not BzrDir
145
# specific. mbp 20070323
146
95
if not allow_unsupported and not format.is_supported():
147
96
# see open_downlevel to open legacy branches.
148
97
raise errors.UnsupportedFormatError(format=format)
149
if recommend_upgrade \
150
and getattr(format, 'upgrade_recommended', False):
151
ui.ui_factory.recommend_upgrade(
152
format.get_format_description(),
155
def clone(self, url, revision_id=None, force_new_repo=False):
99
def clone(self, url, revision_id=None, basis=None, force_new_repo=False):
156
100
"""Clone this bzrdir and its contents to url verbatim.
158
If url's last component does not exist, it will be created.
160
if revision_id is not None, then the clone operation may tune
161
itself to download less data.
162
:param force_new_repo: Do not use a shared repository for the target
163
even if one is available.
165
return self.clone_on_transport(get_transport(url),
166
revision_id=revision_id,
167
force_new_repo=force_new_repo)
169
def clone_on_transport(self, transport, revision_id=None,
170
force_new_repo=False):
171
"""Clone this bzrdir and its contents to transport verbatim.
173
If the target directory does not exist, it will be created.
175
if revision_id is not None, then the clone operation may tune
176
itself to download less data.
177
:param force_new_repo: Do not use a shared repository for the target
178
even if one is available.
180
transport.ensure_base()
181
result = self._format.initialize_on_transport(transport)
102
If urls last component does not exist, it will be created.
104
if revision_id is not None, then the clone operation may tune
105
itself to download less data.
106
:param force_new_repo: Do not use a shared repository for the target
107
even if one is available.
110
basis_repo, basis_branch, basis_tree = self._get_basis_components(basis)
111
result = self._format.initialize(url)
183
113
local_repo = self.find_repository()
184
114
except errors.NoRepositoryPresent:
209
145
except errors.NotBranchError:
212
self.open_workingtree().clone(result)
148
self.open_workingtree().clone(result, basis=basis_tree)
213
149
except (errors.NoWorkingTree, errors.NotLocalUrl):
153
def _get_basis_components(self, basis):
154
"""Retrieve the basis components that are available at basis."""
156
return None, None, None
158
basis_tree = basis.open_workingtree()
159
basis_branch = basis_tree.branch
160
basis_repo = basis_branch.repository
161
except (errors.NoWorkingTree, errors.NotLocalUrl):
164
basis_branch = basis.open_branch()
165
basis_repo = basis_branch.repository
166
except errors.NotBranchError:
169
basis_repo = basis.open_repository()
170
except errors.NoRepositoryPresent:
172
return basis_repo, basis_branch, basis_tree
217
174
# TODO: This should be given a Transport, and should chdir up; otherwise
218
175
# this will open a new connection.
219
176
def _make_tail(self, url):
220
t = get_transport(url)
177
head, tail = urlutils.split(url)
178
if tail and tail != '.':
179
t = bzrlib.transport.get_transport(head)
182
except errors.FileExists:
185
# TODO: Should take a Transport
224
def create(cls, base, format=None, possible_transports=None):
187
def create(cls, base):
225
188
"""Create a new BzrDir at the url 'base'.
227
:param format: If supplied, the format of branch to create. If not
228
supplied, the default is used.
229
:param possible_transports: If supplied, a list of transports that
230
can be reused to share a remote connection.
190
This will call the current default formats initialize with base
191
as the only parameter.
193
If you need a specific format, consider creating an instance
194
of that and calling initialize().
232
196
if cls is not BzrDir:
233
raise AssertionError("BzrDir.create always creates the default"
234
" format, not one of %r" % cls)
235
t = get_transport(base, possible_transports)
238
format = BzrDirFormat.get_default_format()
239
return format.initialize_on_transport(t)
197
raise AssertionError("BzrDir.create always creates the default format, "
198
"not one of %r" % cls)
199
head, tail = urlutils.split(base)
200
if tail and tail != '.':
201
t = bzrlib.transport.get_transport(head)
204
except errors.FileExists:
206
return BzrDirFormat.get_default_format().initialize(safe_unicode(base))
241
208
def create_branch(self):
242
209
"""Create a branch in this BzrDir.
244
The bzrdir's format will control what branch format is created.
211
The bzrdirs format will control what branch format is created.
245
212
For more control see BranchFormatXX.create(a_bzrdir).
247
214
raise NotImplementedError(self.create_branch)
249
def destroy_branch(self):
250
"""Destroy the branch in this BzrDir"""
251
raise NotImplementedError(self.destroy_branch)
254
def create_branch_and_repo(base, force_new_repo=False, format=None):
217
def create_branch_and_repo(base, force_new_repo=False):
255
218
"""Create a new BzrDir, Branch and Repository at the url 'base'.
257
This will use the current default BzrDirFormat unless one is
258
specified, and use whatever
220
This will use the current default BzrDirFormat, and use whatever
259
221
repository format that that uses via bzrdir.create_branch and
260
222
create_repository. If a shared repository is available that is used
306
264
:param force_new_repo: If True a new repository is always created.
307
265
:param force_new_tree: If True or False force creation of a tree or
308
266
prevent such creation respectively.
309
:param format: Override for the bzrdir format to create.
310
:param possible_transports: An optional reusable transports list.
267
:param format: Override for the for the bzrdir format to create
312
269
if force_new_tree:
313
270
# check for non local urls
314
t = get_transport(base, possible_transports)
271
t = get_transport(safe_unicode(base))
315
272
if not isinstance(t, LocalTransport):
316
273
raise errors.NotLocalUrl(base)
317
bzrdir = BzrDir.create(base, format, possible_transports)
275
bzrdir = BzrDir.create(base)
277
bzrdir = format.initialize(base)
318
278
repo = bzrdir._find_or_create_repository(force_new_repo)
319
279
result = bzrdir.create_branch()
320
if force_new_tree or (repo.make_working_trees() and
280
if force_new_tree or (repo.make_working_trees() and
321
281
force_new_tree is None):
323
283
bzrdir.create_workingtree()
324
284
except errors.NotLocalUrl:
329
@deprecated_function(zero_ninetyone)
330
def create_repository(base, shared=False, format=None):
289
def create_repository(base, shared=False):
331
290
"""Create a new BzrDir and Repository at the url 'base'.
333
If no format is supplied, this will default to the current default
334
BzrDirFormat by default, and use whatever repository format that that
335
uses for bzrdirformat.create_repository.
292
This will use the current default BzrDirFormat, and use whatever
293
repository format that that uses for bzrdirformat.create_repository.
337
:param shared: Create a shared repository rather than a standalone
295
;param shared: Create a shared repository rather than a standalone
339
297
The Repository object is returned.
341
299
This must be overridden as an instance method in child classes, where
342
300
it should take no parameters and construct whatever repository format
343
301
that child class desires.
345
This method is deprecated, please call create_repository on a bzrdir
348
bzrdir = BzrDir.create(base, format)
303
bzrdir = BzrDir.create(base)
349
304
return bzrdir.create_repository(shared)
352
def create_standalone_workingtree(base, format=None):
307
def create_standalone_workingtree(base):
353
308
"""Create a new BzrDir, WorkingTree, Branch and Repository at 'base'.
355
310
'base' must be a local path or a file:// url.
357
This will use the current default BzrDirFormat unless one is
358
specified, and use whatever
312
This will use the current default BzrDirFormat, and use whatever
359
313
repository format that that uses for bzrdirformat.create_workingtree,
360
314
create_branch and create_repository.
362
:param format: Override for the bzrdir format to create.
363
:return: The WorkingTree object.
316
The WorkingTree object is returned.
365
t = get_transport(base)
318
t = get_transport(safe_unicode(base))
366
319
if not isinstance(t, LocalTransport):
367
320
raise errors.NotLocalUrl(base)
368
bzrdir = BzrDir.create_branch_and_repo(base,
370
format=format).bzrdir
321
bzrdir = BzrDir.create_branch_and_repo(safe_unicode(base),
322
force_new_repo=True).bzrdir
371
323
return bzrdir.create_workingtree()
373
325
def create_workingtree(self, revision_id=None):
551
454
return BzrDir.open(base, _unsupported=True)
554
def open(base, _unsupported=False, possible_transports=None):
555
"""Open an existing bzrdir, rooted at 'base' (url).
457
def open(base, _unsupported=False):
458
"""Open an existing bzrdir, rooted at 'base' (url)
557
:param _unsupported: a private parameter to the BzrDir class.
559
t = get_transport(base, possible_transports=possible_transports)
560
return BzrDir.open_from_transport(t, _unsupported=_unsupported)
563
def open_from_transport(transport, _unsupported=False,
564
_server_formats=True):
565
"""Open a bzrdir within a particular directory.
567
:param transport: Transport containing the bzrdir.
568
:param _unsupported: private.
570
base = transport.base
572
def find_format(transport):
573
return transport, BzrDirFormat.find_format(
574
transport, _server_formats=_server_formats)
576
def redirected(transport, e, redirection_notice):
577
qualified_source = e.get_source_url()
578
relpath = transport.relpath(qualified_source)
579
if not e.target.endswith(relpath):
580
# Not redirected to a branch-format, not a branch
581
raise errors.NotBranchError(path=e.target)
582
target = e.target[:-len(relpath)]
583
note('%s is%s redirected to %s',
584
transport.base, e.permanently, target)
585
# Let's try with a new transport
586
# FIXME: If 'transport' has a qualifier, this should
587
# be applied again to the new transport *iff* the
588
# schemes used are the same. Uncomment this code
589
# once the function (and tests) exist.
591
#target = urlutils.copy_url_qualifiers(original, target)
592
return get_transport(target)
595
transport, format = do_catching_redirections(find_format,
598
except errors.TooManyRedirections:
599
raise errors.NotBranchError(base)
460
_unsupported is a private parameter to the BzrDir class.
462
t = get_transport(base)
463
# mutter("trying to open %r with transport %r", base, t)
464
format = BzrDirFormat.find_format(t)
601
465
BzrDir._check_supported(format, _unsupported)
602
return format.open(transport, _found=True)
466
return format.open(t, _found=True)
604
468
def open_branch(self, unsupported=False):
605
469
"""Open the branch object at this BzrDir if one is present.
640
503
url = a_transport.base
643
result = BzrDir.open_from_transport(a_transport)
644
return result, urlutils.unescape(a_transport.relpath(url))
506
format = BzrDirFormat.find_format(a_transport)
507
BzrDir._check_supported(format, False)
508
return format.open(a_transport), urlutils.unescape(a_transport.relpath(url))
645
509
except errors.NotBranchError, e:
510
## mutter('not a branch in: %r %s', a_transport.base, e)
648
new_t = a_transport.clone('..')
649
except errors.InvalidURLJoin:
650
# reached the root, whatever that may be
651
raise errors.NotBranchError(path=url)
512
new_t = a_transport.clone('..')
652
513
if new_t.base == a_transport.base:
653
514
# reached the root, whatever that may be
654
515
raise errors.NotBranchError(path=url)
655
516
a_transport = new_t
658
def open_containing_tree_or_branch(klass, location):
659
"""Return the branch and working tree contained by a location.
661
Returns (tree, branch, relpath).
662
If there is no tree at containing the location, tree will be None.
663
If there is no branch containing the location, an exception will be
665
relpath is the portion of the path that is contained by the branch.
667
bzrdir, relpath = klass.open_containing(location)
669
tree = bzrdir.open_workingtree()
670
except (errors.NoWorkingTree, errors.NotLocalUrl):
672
branch = bzrdir.open_branch()
675
return tree, branch, relpath
677
518
def open_repository(self, _unsupported=False):
678
519
"""Open the repository object at this BzrDir if one is present.
680
This will not follow the Branch object pointer - it's strictly a direct
521
This will not follow the Branch object pointer - its strictly a direct
681
522
open facility. Most client code should use open_branch().repository to
682
523
get at a repository.
684
:param _unsupported: a private parameter, not part of the api.
525
_unsupported is a private parameter, not part of the api.
685
526
TODO: static convenience version of this?
687
528
raise NotImplementedError(self.open_repository)
689
def open_workingtree(self, _unsupported=False,
690
recommend_upgrade=True):
530
def open_workingtree(self, _unsupported=False):
691
531
"""Open the workingtree object at this BzrDir if one is present.
693
:param recommend_upgrade: Optional keyword parameter, when True (the
694
default), emit through the ui module a recommendation that the user
695
upgrade the working tree when the workingtree being opened is old
696
(but still fully supported).
533
TODO: static convenience version of this?
698
535
raise NotImplementedError(self.open_workingtree)
721
558
workingtree and discards it, and that's somewhat expensive.)
724
self.open_workingtree(recommend_upgrade=False)
561
self.open_workingtree()
726
563
except errors.NoWorkingTree:
729
def _cloning_metadir(self):
730
"""Produce a metadir suitable for cloning with."""
731
result_format = self._format.__class__()
734
branch = self.open_branch()
735
source_repository = branch.repository
736
except errors.NotBranchError:
738
source_repository = self.open_repository()
739
except errors.NoRepositoryPresent:
740
source_repository = None
742
# XXX TODO: This isinstance is here because we have not implemented
743
# the fix recommended in bug # 103195 - to delegate this choice the
745
repo_format = source_repository._format
746
if not isinstance(repo_format, remote.RemoteRepositoryFormat):
747
result_format.repository_format = repo_format
749
# TODO: Couldn't we just probe for the format in these cases,
750
# rather than opening the whole tree? It would be a little
751
# faster. mbp 20070401
752
tree = self.open_workingtree(recommend_upgrade=False)
753
except (errors.NoWorkingTree, errors.NotLocalUrl):
754
result_format.workingtree_format = None
756
result_format.workingtree_format = tree._format.__class__()
757
return result_format, source_repository
759
def cloning_metadir(self):
760
"""Produce a metadir suitable for cloning or sprouting with.
762
These operations may produce workingtrees (yes, even though they're
763
"cloning" something that doesn't have a tree), so a viable workingtree
764
format must be selected.
766
format, repository = self._cloning_metadir()
767
if format._workingtree_format is None:
768
if repository is None:
770
tree_format = repository._format._matchingbzrdir.workingtree_format
771
format.workingtree_format = tree_format.__class__()
774
def checkout_metadir(self):
775
return self.cloning_metadir()
777
def sprout(self, url, revision_id=None, force_new_repo=False,
778
recurse='down', possible_transports=None):
566
def sprout(self, url, revision_id=None, basis=None, force_new_repo=False):
779
567
"""Create a copy of this bzrdir prepared for use as a new line of
782
If url's last component does not exist, it will be created.
570
If urls last component does not exist, it will be created.
784
572
Attributes related to the identity of the source branch like
785
573
branch nickname will be cleaned, a working tree is created
816
605
result.create_repository()
817
606
elif source_repository is not None and result_repo is None:
818
607
# have source, and want to make a new target repo
819
result_repo = source_repository.sprout(result,
820
revision_id=revision_id)
608
# we don't clone the repo because that preserves attributes
609
# like is_shared(), and we have not yet implemented a
610
# repository sprout().
611
result_repo = result.create_repository()
612
if result_repo is not None:
822
613
# fetch needed content into target.
823
if source_repository is not None:
825
# source_repository.copy_content_into(result_repo,
826
# revision_id=revision_id)
827
# so we can override the copy method
828
result_repo.fetch(source_repository, revision_id=revision_id)
615
# XXX FIXME RBC 20060214 need tests for this when the basis
617
result_repo.fetch(basis_repo, revision_id=revision_id)
618
result_repo.fetch(source_repository, revision_id=revision_id)
829
619
if source_branch is not None:
830
620
source_branch.sprout(result, revision_id=revision_id)
832
622
result.create_branch()
833
if isinstance(target_transport, LocalTransport) and (
834
result_repo is None or result_repo.make_working_trees()):
835
wt = result.create_workingtree()
838
if wt.path2id('') is None:
840
wt.set_root_id(self.open_workingtree.get_root_id())
841
except errors.NoWorkingTree:
847
if recurse == 'down':
849
basis = wt.basis_tree()
851
subtrees = basis.iter_references()
852
recurse_branch = wt.branch
853
elif source_branch is not None:
854
basis = source_branch.basis_tree()
856
subtrees = basis.iter_references()
857
recurse_branch = source_branch
862
for path, file_id in subtrees:
863
target = urlutils.join(url, urlutils.escape(path))
864
sublocation = source_branch.reference_parent(file_id, path)
865
sublocation.bzrdir.sprout(target,
866
basis.get_reference_revision(file_id, path),
867
force_new_repo=force_new_repo, recurse=recurse)
869
if basis is not None:
623
# TODO: jam 20060426 we probably need a test in here in the
624
# case that the newly sprouted branch is a remote one
625
if result_repo is None or result_repo.make_working_trees():
626
result.create_workingtree()
2104
1729
# we hard code the formats here because we are converting into
2105
1730
# the meta format. The meta format upgrader can take this to a
2106
1731
# future format within each component.
2107
self.put_format('repository', RepositoryFormat7())
1732
self.put_format('repository', bzrlib.repository.RepositoryFormat7())
2108
1733
for entry in repository_names:
2109
1734
self.move_entry('repository', entry)
2111
1736
self.step('Upgrading branch ')
2112
1737
self.bzrdir.transport.mkdir('branch', mode=self.dir_mode)
2113
1738
self.make_lock('branch')
2114
self.put_format('branch', BzrBranchFormat5())
1739
self.put_format('branch', bzrlib.branch.BzrBranchFormat5())
2115
1740
branch_files = [('revision-history', True),
2116
1741
('branch-name', True),
2117
1742
('parent', False)]
2118
1743
for entry in branch_files:
2119
1744
self.move_entry('branch', entry)
1746
self.step('Upgrading working tree')
1747
self.bzrdir.transport.mkdir('checkout', mode=self.dir_mode)
1748
self.make_lock('checkout')
1749
self.put_format('checkout', bzrlib.workingtree.WorkingTreeFormat3())
1750
self.bzrdir.transport.delete_multi(self.garbage_inventories, self.pb)
2121
1751
checkout_files = [('pending-merges', True),
2122
1752
('inventory', True),
2123
1753
('stat-cache', False)]
2124
# If a mandatory checkout file is not present, the branch does not have
2125
# a functional checkout. Do not create a checkout in the converted
2127
for name, mandatory in checkout_files:
2128
if mandatory and name not in bzrcontents:
2129
has_checkout = False
2133
if not has_checkout:
2134
self.pb.note('No working tree.')
2135
# If some checkout files are there, we may as well get rid of them.
2136
for name, mandatory in checkout_files:
2137
if name in bzrcontents:
2138
self.bzrdir.transport.delete(name)
2140
from bzrlib.workingtree import WorkingTreeFormat3
2141
self.step('Upgrading working tree')
2142
self.bzrdir.transport.mkdir('checkout', mode=self.dir_mode)
2143
self.make_lock('checkout')
2145
'checkout', WorkingTreeFormat3())
2146
self.bzrdir.transport.delete_multi(
2147
self.garbage_inventories, self.pb)
2148
for entry in checkout_files:
2149
self.move_entry('checkout', entry)
2150
if last_revision is not None:
2151
self.bzrdir._control_files.put_utf8(
2152
'checkout/last-revision', last_revision)
2153
self.bzrdir._control_files.put_utf8(
2154
'branch-format', BzrDirMetaFormat1().get_format_string())
1754
for entry in checkout_files:
1755
self.move_entry('checkout', entry)
1756
if last_revision is not None:
1757
self.bzrdir._control_files.put_utf8('checkout/last-revision',
1759
self.bzrdir._control_files.put_utf8('branch-format', BzrDirMetaFormat1().get_format_string())
2155
1760
return BzrDir.open(self.bzrdir.root_transport.base)
2157
1762
def make_lock(self, name):
2158
1763
"""Make a lock for the new control dir name."""
2159
1764
self.step('Make %s lock' % name)
2160
ld = lockdir.LockDir(self.bzrdir.transport,
2162
file_modebits=self.file_mode,
2163
dir_modebits=self.dir_mode)
1765
ld = LockDir(self.bzrdir.transport,
1767
file_modebits=self.file_mode,
1768
dir_modebits=self.dir_mode)
2166
1771
def move_entry(self, new_dir, entry):
2205
1810
self.pb.note('starting repository conversion')
2206
1811
converter = CopyConverter(self.target_format.repository_format)
2207
1812
converter.convert(repo, pb)
2209
branch = self.bzrdir.open_branch()
2210
except errors.NotBranchError:
2213
# TODO: conversions of Branch and Tree should be done by
2214
# InterXFormat lookups
2215
# Avoid circular imports
2216
from bzrlib import branch as _mod_branch
2217
if (branch._format.__class__ is _mod_branch.BzrBranchFormat5 and
2218
self.target_format.get_branch_format().__class__ is
2219
_mod_branch.BzrBranchFormat6):
2220
branch_converter = _mod_branch.Converter5to6()
2221
branch_converter.convert(branch)
2223
tree = self.bzrdir.open_workingtree(recommend_upgrade=False)
2224
except (errors.NoWorkingTree, errors.NotLocalUrl):
2227
# TODO: conversions of Branch and Tree should be done by
2228
# InterXFormat lookups
2229
if (isinstance(tree, workingtree.WorkingTree3) and
2230
not isinstance(tree, workingtree_4.WorkingTree4) and
2231
isinstance(self.target_format.workingtree_format,
2232
workingtree_4.WorkingTreeFormat4)):
2233
workingtree_4.Converter3to4().convert(tree)
2234
1813
return to_convert
2237
# This is not in remote.py because it's small, and needs to be registered.
2238
# Putting it in remote.py creates a circular import problem.
2239
# we can make it a lazy object if the control formats is turned into something
2241
class RemoteBzrDirFormat(BzrDirMetaFormat1):
2242
"""Format representing bzrdirs accessed via a smart server"""
2244
def get_format_description(self):
2245
return 'bzr remote bzrdir'
2248
def probe_transport(klass, transport):
2249
"""Return a RemoteBzrDirFormat object if it looks possible."""
2251
client = transport.get_smart_client()
2252
except (NotImplementedError, AttributeError,
2253
errors.TransportNotPossible):
2254
# no smart server, so not a branch for this format type.
2255
raise errors.NotBranchError(path=transport.base)
2257
# Send a 'hello' request in protocol version one, and decline to
2258
# open it if the server doesn't support our required version (2) so
2259
# that the VFS-based transport will do it.
2260
request = client.get_request()
2261
smart_protocol = protocol.SmartClientRequestProtocolOne(request)
2262
server_version = smart_protocol.query_version()
2263
if server_version != 2:
2264
raise errors.NotBranchError(path=transport.base)
2267
def initialize_on_transport(self, transport):
2269
# hand off the request to the smart server
2270
shared_medium = transport.get_shared_medium()
2271
except errors.NoSmartMedium:
2272
# TODO: lookup the local format from a server hint.
2273
local_dir_format = BzrDirMetaFormat1()
2274
return local_dir_format.initialize_on_transport(transport)
2275
client = _SmartClient(shared_medium)
2276
path = client.remote_path_from_transport(transport)
2277
response = _SmartClient(shared_medium).call('BzrDirFormat.initialize',
2279
assert response[0] in ('ok', ), 'unexpected response code %s' % (response,)
2280
return remote.RemoteBzrDir(transport)
2282
def _open(self, transport):
2283
return remote.RemoteBzrDir(transport)
2285
def __eq__(self, other):
2286
if not isinstance(other, RemoteBzrDirFormat):
2288
return self.get_format_description() == other.get_format_description()
2291
BzrDirFormat.register_control_server_format(RemoteBzrDirFormat)
2294
class BzrDirFormatInfo(object):
2296
def __init__(self, native, deprecated, hidden):
2297
self.deprecated = deprecated
2298
self.native = native
2299
self.hidden = hidden
2302
class BzrDirFormatRegistry(registry.Registry):
2303
"""Registry of user-selectable BzrDir subformats.
2305
Differs from BzrDirFormat._control_formats in that it provides sub-formats,
2306
e.g. BzrDirMeta1 with weave repository. Also, it's more user-oriented.
2309
def register_metadir(self, key,
2310
repository_format, help, native=True, deprecated=False,
2314
"""Register a metadir subformat.
2316
These all use a BzrDirMetaFormat1 bzrdir, but can be parameterized
2317
by the Repository format.
2319
:param repository_format: The fully-qualified repository format class
2321
:param branch_format: Fully-qualified branch format class name as
2323
:param tree_format: Fully-qualified tree format class name as
2326
# This should be expanded to support setting WorkingTree and Branch
2327
# formats, once BzrDirMetaFormat1 supports that.
2328
def _load(full_name):
2329
mod_name, factory_name = full_name.rsplit('.', 1)
2331
mod = __import__(mod_name, globals(), locals(),
2333
except ImportError, e:
2334
raise ImportError('failed to load %s: %s' % (full_name, e))
2336
factory = getattr(mod, factory_name)
2337
except AttributeError:
2338
raise AttributeError('no factory %s in module %r'
2343
bd = BzrDirMetaFormat1()
2344
if branch_format is not None:
2345
bd.set_branch_format(_load(branch_format))
2346
if tree_format is not None:
2347
bd.workingtree_format = _load(tree_format)
2348
if repository_format is not None:
2349
bd.repository_format = _load(repository_format)
2351
self.register(key, helper, help, native, deprecated, hidden)
2353
def register(self, key, factory, help, native=True, deprecated=False,
2355
"""Register a BzrDirFormat factory.
2357
The factory must be a callable that takes one parameter: the key.
2358
It must produce an instance of the BzrDirFormat when called.
2360
This function mainly exists to prevent the info object from being
2363
registry.Registry.register(self, key, factory, help,
2364
BzrDirFormatInfo(native, deprecated, hidden))
2366
def register_lazy(self, key, module_name, member_name, help, native=True,
2367
deprecated=False, hidden=False):
2368
registry.Registry.register_lazy(self, key, module_name, member_name,
2369
help, BzrDirFormatInfo(native, deprecated, hidden))
2371
def set_default(self, key):
2372
"""Set the 'default' key to be a clone of the supplied key.
2374
This method must be called once and only once.
2376
registry.Registry.register(self, 'default', self.get(key),
2377
self.get_help(key), info=self.get_info(key))
2379
def set_default_repository(self, key):
2380
"""Set the FormatRegistry default and Repository default.
2382
This is a transitional method while Repository.set_default_format
2385
if 'default' in self:
2386
self.remove('default')
2387
self.set_default(key)
2388
format = self.get('default')()
2389
assert isinstance(format, BzrDirMetaFormat1)
2391
def make_bzrdir(self, key):
2392
return self.get(key)()
2394
def help_topic(self, topic):
2395
output = textwrap.dedent("""\
2396
These formats can be used for creating branches, working trees, and
2400
default_realkey = None
2401
default_help = self.get_help('default')
2403
for key in self.keys():
2404
if key == 'default':
2406
help = self.get_help(key)
2407
if help == default_help:
2408
default_realkey = key
2410
help_pairs.append((key, help))
2412
def wrapped(key, help, info):
2414
help = '(native) ' + help
2415
return ':%s:\n%s\n\n' % (key,
2416
textwrap.fill(help, initial_indent=' ',
2417
subsequent_indent=' '))
2418
if default_realkey is not None:
2419
output += wrapped(default_realkey, '(default) %s' % default_help,
2420
self.get_info('default'))
2421
deprecated_pairs = []
2422
for key, help in help_pairs:
2423
info = self.get_info(key)
2426
elif info.deprecated:
2427
deprecated_pairs.append((key, help))
2429
output += wrapped(key, help, info)
2430
if len(deprecated_pairs) > 0:
2431
output += "Deprecated formats are shown below.\n\n"
2432
for key, help in deprecated_pairs:
2433
info = self.get_info(key)
2434
output += wrapped(key, help, info)
2439
format_registry = BzrDirFormatRegistry()
2440
format_registry.register('weave', BzrDirFormat6,
2441
'Pre-0.8 format. Slower than knit and does not'
2442
' support checkouts or shared repositories.',
2444
format_registry.register_metadir('knit',
2445
'bzrlib.repofmt.knitrepo.RepositoryFormatKnit1',
2446
'Format using knits. Recommended for interoperation with bzr <= 0.14.',
2447
branch_format='bzrlib.branch.BzrBranchFormat5',
2448
tree_format='bzrlib.workingtree.WorkingTreeFormat3')
2449
format_registry.register_metadir('metaweave',
2450
'bzrlib.repofmt.weaverepo.RepositoryFormat7',
2451
'Transitional format in 0.8. Slower than knit.',
2452
branch_format='bzrlib.branch.BzrBranchFormat5',
2453
tree_format='bzrlib.workingtree.WorkingTreeFormat3',
2455
format_registry.register_metadir('dirstate',
2456
'bzrlib.repofmt.knitrepo.RepositoryFormatKnit1',
2457
help='New in 0.15: Fast local operations. Compatible with bzr 0.8 and '
2458
'above when accessed over the network.',
2459
branch_format='bzrlib.branch.BzrBranchFormat5',
2460
# this uses bzrlib.workingtree.WorkingTreeFormat4 because importing
2461
# directly from workingtree_4 triggers a circular import.
2462
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
2464
format_registry.register_metadir('dirstate-tags',
2465
'bzrlib.repofmt.knitrepo.RepositoryFormatKnit1',
2466
help='New in 0.15: Fast local operations and improved scaling for '
2467
'network operations. Additionally adds support for tags.'
2468
' Incompatible with bzr < 0.15.',
2469
branch_format='bzrlib.branch.BzrBranchFormat6',
2470
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
2472
format_registry.register_metadir('dirstate-with-subtree',
2473
'bzrlib.repofmt.knitrepo.RepositoryFormatKnit3',
2474
help='New in 0.15: Fast local operations and improved scaling for '
2475
'network operations. Additionally adds support for versioning nested '
2476
'bzr branches. Incompatible with bzr < 0.15.',
2477
branch_format='bzrlib.branch.BzrBranchFormat6',
2478
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
2481
format_registry.register_metadir('experimental',
2482
'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack1',
2483
help='New in XXX: Experimental format with data compatible with dirstate '
2484
'format repositories. Cannot be read except with bzr.dev. '
2485
'WARNING: This format is unstable and data in it will not be upgradable'
2486
' to release formats of bzr.',
2487
branch_format='bzrlib.branch.BzrBranchFormat6',
2488
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
2491
format_registry.register_metadir('experimental-subtree',
2492
'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack3',
2493
help='New in XXX: Experimental format with data compatible with '
2494
'dirstate-with-subtree format repositories. Cannot be read except with'
2495
' bzr.dev. WARNING: This format is unstable and data in it will not be'
2496
' upgradable to release formats of bzr.',
2497
branch_format='bzrlib.branch.BzrBranchFormat6',
2498
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
2501
format_registry.set_default('dirstate-tags')