217
215
raise errors.NoColocatedBranchSupport(self)
218
def get_branch_transport(self, branch_format, name=None):
219
"""Get the transport for use by branch format in this ControlDir.
221
Note that bzr dirs that do not support format strings will raise
222
IncompatibleFormat if the branch format they are given has
223
a format string, and vice versa.
225
If branch_format is None, the transport is returned with no
226
checking. If it is not None, then the returned transport is
227
guaranteed to point to an existing directory ready for use.
229
raise NotImplementedError(self.get_branch_transport)
231
def get_repository_transport(self, repository_format):
232
"""Get the transport for use by repository format in this ControlDir.
234
Note that bzr dirs that do not support format strings will raise
235
IncompatibleFormat if the repository format they are given has
236
a format string, and vice versa.
238
If repository_format is None, the transport is returned with no
239
checking. If it is not None, then the returned transport is
240
guaranteed to point to an existing directory ready for use.
242
raise NotImplementedError(self.get_repository_transport)
244
def get_workingtree_transport(self, tree_format):
245
"""Get the transport for use by workingtree format in this ControlDir.
247
Note that bzr dirs that do not support format strings will raise
248
IncompatibleFormat if the workingtree format they are given has a
249
format string, and vice versa.
251
If workingtree_format is None, the transport is returned with no
252
checking. If it is not None, then the returned transport is
253
guaranteed to point to an existing directory ready for use.
255
raise NotImplementedError(self.get_workingtree_transport)
220
257
def open_branch(self, name=None, unsupported=False,
221
258
ignore_fallbacks=False):
222
259
"""Open the branch object at this ControlDir if one is present.
348
374
:param create_tree_if_local: If true, a working-tree will be created
349
375
when working locally.
351
raise NotImplementedError(self.sprout)
377
operation = cleanup.OperationWithCleanups(self._sprout)
378
return operation.run(url, revision_id=revision_id,
379
force_new_repo=force_new_repo, recurse=recurse,
380
possible_transports=possible_transports,
381
accelerator_tree=accelerator_tree, hardlink=hardlink,
382
stacked=stacked, source_branch=source_branch,
383
create_tree_if_local=create_tree_if_local)
385
def _sprout(self, op, url, revision_id=None, force_new_repo=False,
386
recurse='down', possible_transports=None,
387
accelerator_tree=None, hardlink=False, stacked=False,
388
source_branch=None, create_tree_if_local=True):
389
add_cleanup = op.add_cleanup
390
fetch_spec_factory = fetch.FetchSpecFactory()
391
if revision_id is not None:
392
fetch_spec_factory.add_revision_ids([revision_id])
393
fetch_spec_factory.source_branch_stop_revision_id = revision_id
394
target_transport = _mod_transport.get_transport(url,
396
target_transport.ensure_base()
397
cloning_format = self.cloning_metadir(stacked)
398
# Create/update the result branch
399
result = cloning_format.initialize_on_transport(target_transport)
400
source_branch, source_repository = self._find_source_repo(
401
add_cleanup, source_branch)
402
fetch_spec_factory.source_branch = source_branch
403
# if a stacked branch wasn't requested, we don't create one
404
# even if the origin was stacked
405
if stacked and source_branch is not None:
406
stacked_branch_url = self.root_transport.base
408
stacked_branch_url = None
409
repository_policy = result.determine_repository_policy(
410
force_new_repo, stacked_branch_url, require_stacking=stacked)
411
result_repo, is_new_repo = repository_policy.acquire_repository()
412
add_cleanup(result_repo.lock_write().unlock)
413
fetch_spec_factory.source_repo = source_repository
414
fetch_spec_factory.target_repo = result_repo
415
if stacked or (len(result_repo._fallback_repositories) != 0):
416
target_repo_kind = fetch.TargetRepoKinds.STACKED
418
target_repo_kind = fetch.TargetRepoKinds.EMPTY
420
target_repo_kind = fetch.TargetRepoKinds.PREEXISTING
421
fetch_spec_factory.target_repo_kind = target_repo_kind
422
if source_repository is not None:
423
fetch_spec = fetch_spec_factory.make_fetch_spec()
424
result_repo.fetch(source_repository, fetch_spec=fetch_spec)
426
if source_branch is None:
427
# this is for sprouting a controldir without a branch; is that
429
# Not especially, but it's part of the contract.
430
result_branch = result.create_branch()
432
result_branch = source_branch.sprout(result,
433
revision_id=revision_id, repository_policy=repository_policy,
434
repository=result_repo)
435
mutter("created new branch %r" % (result_branch,))
437
# Create/update the result working tree
438
if (create_tree_if_local and
439
isinstance(target_transport, local.LocalTransport) and
440
(result_repo is None or result_repo.make_working_trees())):
441
wt = result.create_workingtree(accelerator_tree=accelerator_tree,
442
hardlink=hardlink, from_branch=result_branch)
445
if wt.path2id('') is None:
447
wt.set_root_id(self.open_workingtree.get_root_id())
448
except errors.NoWorkingTree:
454
if recurse == 'down':
457
basis = wt.basis_tree()
458
elif result_branch is not None:
459
basis = result_branch.basis_tree()
460
elif source_branch is not None:
461
basis = source_branch.basis_tree()
462
if basis is not None:
463
add_cleanup(basis.lock_read().unlock)
464
subtrees = basis.iter_references()
467
for path, file_id in subtrees:
468
target = urlutils.join(url, urlutils.escape(path))
469
sublocation = source_branch.reference_parent(file_id, path)
470
sublocation.bzrdir.sprout(target,
471
basis.get_reference_revision(file_id, path),
472
force_new_repo=force_new_repo, recurse=recurse,
476
def _find_source_repo(self, add_cleanup, source_branch):
477
"""Find the source branch and repo for a sprout operation.
479
This is helper intended for use by _sprout.
481
:returns: (source_branch, source_repository). Either or both may be
482
None. If not None, they will be read-locked (and their unlock(s)
483
scheduled via the add_cleanup param).
485
if source_branch is not None:
486
add_cleanup(source_branch.lock_read().unlock)
487
return source_branch, source_branch.repository
489
source_branch = self.open_branch()
490
source_repository = source_branch.repository
491
except errors.NotBranchError:
494
source_repository = self.open_repository()
495
except errors.NoRepositoryPresent:
496
source_repository = None
498
add_cleanup(source_repository.lock_read().unlock)
500
add_cleanup(source_branch.lock_read().unlock)
501
return source_branch, source_repository
353
503
def push_branch(self, source, revision_id=None, overwrite=False,
354
504
remember=False, create_prefix=False):
497
641
"""Return the short description for this format."""
498
642
raise NotImplementedError(self.get_format_description)
500
def is_supported(self):
501
"""Is this format supported?
503
Supported formats must be initializable and openable.
504
Unsupported formats may not support initialization or committing or
505
some other features depending on the reason for not being supported.
509
def check_support_status(self, allow_unsupported, recommend_upgrade=True,
511
"""Give an error or warning on old formats.
513
:param allow_unsupported: If true, allow opening
514
formats that are strongly deprecated, and which may
515
have limited functionality.
517
:param recommend_upgrade: If true (default), warn
518
the user through the ui object that they may wish
519
to upgrade the object.
521
if not allow_unsupported and not self.is_supported():
522
# see open_downlevel to open legacy branches.
523
raise errors.UnsupportedFormatError(format=self)
524
if recommend_upgrade and self.upgrade_recommended:
525
ui.ui_factory.recommend_upgrade(
526
self.get_format_description(), basedir)
529
645
class ControlComponentFormatRegistry(registry.FormatRegistry):
530
646
"""A registry for control components (branch, workingtree, repository)."""
681
784
def is_supported(self):
682
785
"""Is this format supported?
684
Supported formats must be openable.
787
Supported formats must be initializable and openable.
685
788
Unsupported formats may not support initialization or committing or
686
789
some other features depending on the reason for not being supported.
690
def is_initializable(self):
691
"""Whether new control directories of this format can be initialized.
693
return self.is_supported()
695
def check_support_status(self, allow_unsupported, recommend_upgrade=True,
697
"""Give an error or warning on old formats.
699
:param allow_unsupported: If true, allow opening
700
formats that are strongly deprecated, and which may
701
have limited functionality.
703
:param recommend_upgrade: If true (default), warn
704
the user through the ui object that they may wish
705
to upgrade the object.
707
if not allow_unsupported and not self.is_supported():
708
# see open_downlevel to open legacy branches.
709
raise errors.UnsupportedFormatError(format=self)
710
if recommend_upgrade and self.upgrade_recommended:
711
ui.ui_factory.recommend_upgrade(
712
self.get_format_description(), basedir)
714
793
def same_model(self, target_format):
715
794
return (self.repository_format.rich_root_data ==
716
795
target_format.rich_root_data)