366
364
:param create_tree_if_local: If true, a working-tree will be created
367
365
when working locally.
369
operation = cleanup.OperationWithCleanups(self._sprout)
370
return operation.run(url, revision_id=revision_id,
371
force_new_repo=force_new_repo, recurse=recurse,
372
possible_transports=possible_transports,
373
accelerator_tree=accelerator_tree, hardlink=hardlink,
374
stacked=stacked, source_branch=source_branch,
375
create_tree_if_local=create_tree_if_local)
377
def _sprout(self, op, url, revision_id=None, force_new_repo=False,
378
recurse='down', possible_transports=None,
379
accelerator_tree=None, hardlink=False, stacked=False,
380
source_branch=None, create_tree_if_local=True):
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
386
target_transport = _mod_transport.get_transport(url,
367
target_transport = get_transport(url, possible_transports)
388
368
target_transport.ensure_base()
389
369
cloning_format = self.cloning_metadir(stacked)
390
370
# Create/update the result branch
391
371
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
395
372
# if a stacked branch wasn't requested, we don't create one
396
373
# even if the origin was stacked
397
if stacked and source_branch is not None:
398
stacked_branch_url = self.root_transport.base
374
stacked_branch_url = None
375
if source_branch is not None:
377
stacked_branch_url = self.root_transport.base
378
source_repository = source_branch.repository
400
stacked_branch_url = None
381
source_branch = self.open_branch()
382
source_repository = source_branch.repository
384
stacked_branch_url = self.root_transport.base
385
except errors.NotBranchError:
388
source_repository = self.open_repository()
389
except errors.NoRepositoryPresent:
390
source_repository = None
401
391
repository_policy = result.determine_repository_policy(
402
392
force_new_repo, stacked_branch_url, require_stacking=stacked)
403
393
result_repo, is_new_repo = repository_policy.acquire_repository()
404
add_cleanup(result_repo.lock_write().unlock)
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
394
is_stacked = stacked or (len(result_repo._fallback_repositories) != 0)
395
if is_new_repo and revision_id is not None and not is_stacked:
396
fetch_spec = graph.PendingAncestryResult(
397
[revision_id], source_repository)
412
target_repo_kind = fetch.TargetRepoKinds.PREEXISTING
413
fetch_spec_factory.target_repo_kind = target_repo_kind
414
400
if source_repository is not None:
415
fetch_spec = fetch_spec_factory.make_fetch_spec()
416
result_repo.fetch(source_repository, fetch_spec=fetch_spec)
401
# Fetch while stacked to prevent unstacked fetch from
403
if fetch_spec is None:
404
result_repo.fetch(source_repository, revision_id=revision_id)
406
result_repo.fetch(source_repository, fetch_spec=fetch_spec)
418
408
if source_branch is None:
419
409
# this is for sprouting a controldir without a branch; is that
446
435
if recurse == 'down':
448
436
if wt is not None:
449
437
basis = wt.basis_tree()
439
subtrees = basis.iter_references()
450
440
elif result_branch is not None:
451
441
basis = result_branch.basis_tree()
443
subtrees = basis.iter_references()
452
444
elif source_branch is not None:
453
445
basis = source_branch.basis_tree()
454
if basis is not None:
455
add_cleanup(basis.lock_read().unlock)
456
447
subtrees = basis.iter_references()
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,
452
for path, file_id in subtrees:
453
target = urlutils.join(url, urlutils.escape(path))
454
sublocation = source_branch.reference_parent(file_id, path)
455
sublocation.bzrdir.sprout(target,
456
basis.get_reference_revision(file_id, path),
457
force_new_repo=force_new_repo, recurse=recurse,
460
if basis is not None:
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
495
464
def push_branch(self, source, revision_id=None, overwrite=False,
496
465
remember=False, create_prefix=False):
497
466
"""Push the source branch into this ControlDir."""
595
564
:param preserve_stacking: When cloning a stacked branch, stack the
596
565
new branch on top of the other branch's stacked-on branch.
598
return self.clone_on_transport(_mod_transport.get_transport(url),
567
return self.clone_on_transport(get_transport(url),
599
568
revision_id=revision_id,
600
569
force_new_repo=force_new_repo,
601
570
preserve_stacking=preserve_stacking)
603
572
def clone_on_transport(self, transport, revision_id=None,
604
573
force_new_repo=False, preserve_stacking=False, stacked_on=None,
605
create_prefix=False, use_existing_dir=True, no_tree=False):
574
create_prefix=False, use_existing_dir=True):
606
575
"""Clone this bzrdir and its contents to transport verbatim.
608
577
:param transport: The transport for the location to produce the clone