378
379
accelerator_tree=None, hardlink=False, stacked=False,
379
380
source_branch=None, create_tree_if_local=True):
380
381
add_cleanup = op.add_cleanup
382
fetch_spec_factory = fetch.FetchSpecFactory()
383
if revision_id is not None:
384
fetch_spec_factory.add_revision_ids([revision_id])
385
fetch_spec_factory.source_branch_stop_revision_id = revision_id
381
386
target_transport = _mod_transport.get_transport(url,
382
387
possible_transports)
383
388
target_transport.ensure_base()
384
389
cloning_format = self.cloning_metadir(stacked)
385
390
# Create/update the result branch
386
391
result = cloning_format.initialize_on_transport(target_transport)
392
source_branch, source_repository = self._find_source_repo(
393
add_cleanup, source_branch)
394
fetch_spec_factory.source_branch = source_branch
387
395
# if a stacked branch wasn't requested, we don't create one
388
396
# even if the origin was stacked
389
stacked_branch_url = None
390
if source_branch is not None:
391
add_cleanup(source_branch.lock_read().unlock)
393
stacked_branch_url = self.root_transport.base
394
source_repository = source_branch.repository
397
if stacked and source_branch is not None:
398
stacked_branch_url = self.root_transport.base
397
source_branch = self.open_branch()
398
source_repository = source_branch.repository
400
stacked_branch_url = self.root_transport.base
401
except errors.NotBranchError:
404
source_repository = self.open_repository()
405
except errors.NoRepositoryPresent:
406
source_repository = None
408
add_cleanup(source_repository.lock_read().unlock)
410
add_cleanup(source_branch.lock_read().unlock)
400
stacked_branch_url = None
411
401
repository_policy = result.determine_repository_policy(
412
402
force_new_repo, stacked_branch_url, require_stacking=stacked)
413
403
result_repo, is_new_repo = repository_policy.acquire_repository()
414
404
add_cleanup(result_repo.lock_write().unlock)
415
is_stacked = stacked or (len(result_repo._fallback_repositories) != 0)
416
if is_new_repo and revision_id is not None and not is_stacked:
417
fetch_spec = graph.PendingAncestryResult(
418
[revision_id], source_repository)
405
fetch_spec_factory.source_repo = source_repository
406
fetch_spec_factory.target_repo = result_repo
407
if stacked or (len(result_repo._fallback_repositories) != 0):
408
target_repo_kind = fetch.TargetRepoKinds.STACKED
410
target_repo_kind = fetch.TargetRepoKinds.EMPTY
412
target_repo_kind = fetch.TargetRepoKinds.PREEXISTING
413
fetch_spec_factory.target_repo_kind = target_repo_kind
421
414
if source_repository is not None:
422
# Fetch while stacked to prevent unstacked fetch from
424
if fetch_spec is None:
425
result_repo.fetch(source_repository, revision_id=revision_id)
427
result_repo.fetch(source_repository, fetch_spec=fetch_spec)
415
fetch_spec = fetch_spec_factory.make_fetch_spec()
416
result_repo.fetch(source_repository, fetch_spec=fetch_spec)
429
418
if source_branch is None:
430
419
# this is for sprouting a controldir without a branch; is that
457
446
if recurse == 'down':
458
448
if wt is not None:
459
449
basis = wt.basis_tree()
461
subtrees = basis.iter_references()
462
450
elif result_branch is not None:
463
451
basis = result_branch.basis_tree()
465
subtrees = basis.iter_references()
466
452
elif source_branch is not None:
467
453
basis = source_branch.basis_tree()
454
if basis is not None:
455
add_cleanup(basis.lock_read().unlock)
469
456
subtrees = basis.iter_references()
474
for path, file_id in subtrees:
475
target = urlutils.join(url, urlutils.escape(path))
476
sublocation = source_branch.reference_parent(file_id, path)
477
sublocation.bzrdir.sprout(target,
478
basis.get_reference_revision(file_id, path),
479
force_new_repo=force_new_repo, recurse=recurse,
482
if basis is not None:
459
for path, file_id in subtrees:
460
target = urlutils.join(url, urlutils.escape(path))
461
sublocation = source_branch.reference_parent(file_id, path)
462
sublocation.bzrdir.sprout(target,
463
basis.get_reference_revision(file_id, path),
464
force_new_repo=force_new_repo, recurse=recurse,
468
def _find_source_repo(self, add_cleanup, source_branch):
469
"""Find the source branch and repo for a sprout operation.
471
This is helper intended for use by _sprout.
473
:returns: (source_branch, source_repository). Either or both may be
474
None. If not None, they will be read-locked (and their unlock(s)
475
scheduled via the add_cleanup param).
477
if source_branch is not None:
478
add_cleanup(source_branch.lock_read().unlock)
479
return source_branch, source_branch.repository
481
source_branch = self.open_branch()
482
source_repository = source_branch.repository
483
except errors.NotBranchError:
486
source_repository = self.open_repository()
487
except errors.NoRepositoryPresent:
488
source_repository = None
490
add_cleanup(source_repository.lock_read().unlock)
492
add_cleanup(source_branch.lock_read().unlock)
493
return source_branch, source_repository
486
495
def push_branch(self, source, revision_id=None, overwrite=False,
487
496
remember=False, create_prefix=False):
488
497
"""Push the source branch into this ControlDir."""