335
327
:param create_tree_if_local: If true, a working-tree will be created
336
328
when working locally.
338
operation = cleanup.OperationWithCleanups(self._sprout)
339
return operation.run(url, revision_id=revision_id,
340
force_new_repo=force_new_repo, recurse=recurse,
341
possible_transports=possible_transports,
342
accelerator_tree=accelerator_tree, hardlink=hardlink,
343
stacked=stacked, source_branch=source_branch,
344
create_tree_if_local=create_tree_if_local)
346
def _sprout(self, op, url, revision_id=None, force_new_repo=False,
347
recurse='down', possible_transports=None,
348
accelerator_tree=None, hardlink=False, stacked=False,
349
source_branch=None, create_tree_if_local=True):
350
add_cleanup = op.add_cleanup
351
fetch_spec_factory = fetch.FetchSpecFactory()
352
if revision_id is not None:
353
fetch_spec_factory.add_revision_ids([revision_id])
354
fetch_spec_factory.source_branch_stop_revision_id = revision_id
355
target_transport = _mod_transport.get_transport(url,
357
target_transport.ensure_base()
358
cloning_format = self.cloning_metadir(stacked)
359
# Create/update the result branch
360
result = cloning_format.initialize_on_transport(target_transport)
361
source_branch, source_repository = self._find_source_repo(
362
add_cleanup, source_branch)
363
fetch_spec_factory.source_branch = source_branch
364
# if a stacked branch wasn't requested, we don't create one
365
# even if the origin was stacked
366
if stacked and source_branch is not None:
367
stacked_branch_url = self.root_transport.base
369
stacked_branch_url = None
370
repository_policy = result.determine_repository_policy(
371
force_new_repo, stacked_branch_url, require_stacking=stacked)
372
result_repo, is_new_repo = repository_policy.acquire_repository()
373
add_cleanup(result_repo.lock_write().unlock)
374
fetch_spec_factory.source_repo = source_repository
375
fetch_spec_factory.target_repo = result_repo
376
if stacked or (len(result_repo._fallback_repositories) != 0):
377
target_repo_kind = fetch.TargetRepoKinds.STACKED
379
target_repo_kind = fetch.TargetRepoKinds.EMPTY
381
target_repo_kind = fetch.TargetRepoKinds.PREEXISTING
382
fetch_spec_factory.target_repo_kind = target_repo_kind
383
if source_repository is not None:
384
fetch_spec = fetch_spec_factory.make_fetch_spec()
385
result_repo.fetch(source_repository, fetch_spec=fetch_spec)
387
if source_branch is None:
388
# this is for sprouting a controldir without a branch; is that
390
# Not especially, but it's part of the contract.
391
result_branch = result.create_branch()
393
result_branch = source_branch.sprout(result,
394
revision_id=revision_id, repository_policy=repository_policy,
395
repository=result_repo)
396
mutter("created new branch %r" % (result_branch,))
398
# Create/update the result working tree
399
if (create_tree_if_local and
400
isinstance(target_transport, local.LocalTransport) and
401
(result_repo is None or result_repo.make_working_trees())):
402
wt = result.create_workingtree(accelerator_tree=accelerator_tree,
403
hardlink=hardlink, from_branch=result_branch)
406
if wt.path2id('') is None:
408
wt.set_root_id(self.open_workingtree.get_root_id())
409
except errors.NoWorkingTree:
415
if recurse == 'down':
418
basis = wt.basis_tree()
419
elif result_branch is not None:
420
basis = result_branch.basis_tree()
421
elif source_branch is not None:
422
basis = source_branch.basis_tree()
423
if basis is not None:
424
add_cleanup(basis.lock_read().unlock)
425
subtrees = basis.iter_references()
428
for path, file_id in subtrees:
429
target = urlutils.join(url, urlutils.escape(path))
430
sublocation = source_branch.reference_parent(file_id, path)
431
sublocation.bzrdir.sprout(target,
432
basis.get_reference_revision(file_id, path),
433
force_new_repo=force_new_repo, recurse=recurse,
437
def _find_source_repo(self, add_cleanup, source_branch):
438
"""Find the source branch and repo for a sprout operation.
440
This is helper intended for use by _sprout.
442
:returns: (source_branch, source_repository). Either or both may be
443
None. If not None, they will be read-locked (and their unlock(s)
444
scheduled via the add_cleanup param).
446
if source_branch is not None:
447
add_cleanup(source_branch.lock_read().unlock)
448
return source_branch, source_branch.repository
450
source_branch = self.open_branch()
451
source_repository = source_branch.repository
452
except errors.NotBranchError:
455
source_repository = self.open_repository()
456
except errors.NoRepositoryPresent:
457
source_repository = None
459
add_cleanup(source_repository.lock_read().unlock)
461
add_cleanup(source_branch.lock_read().unlock)
462
return source_branch, source_repository
330
raise NotImplementedError(self.sprout)
464
332
def push_branch(self, source, revision_id=None, overwrite=False,
465
333
remember=False, create_prefix=False):
602
476
"""Return the short description for this format."""
603
477
raise NotImplementedError(self.get_format_description)
479
def is_supported(self):
480
"""Is this format supported?
482
Supported formats must be initializable and openable.
483
Unsupported formats may not support initialization or committing or
484
some other features depending on the reason for not being supported.
488
def check_support_status(self, allow_unsupported, recommend_upgrade=True,
490
"""Give an error or warning on old formats.
492
:param allow_unsupported: If true, allow opening
493
formats that are strongly deprecated, and which may
494
have limited functionality.
496
:param recommend_upgrade: If true (default), warn
497
the user through the ui object that they may wish
498
to upgrade the object.
500
if not allow_unsupported and not self.is_supported():
501
# see open_downlevel to open legacy branches.
502
raise errors.UnsupportedFormatError(format=self)
503
if recommend_upgrade and self.upgrade_recommended:
504
ui.ui_factory.recommend_upgrade(
505
self.get_format_description(), basedir)
606
508
class ControlComponentFormatRegistry(registry.FormatRegistry):
607
509
"""A registry for control components (branch, workingtree, repository)."""