352
364
:param create_tree_if_local: If true, a working-tree will be created
353
365
when working locally.
355
raise NotImplementedError(self.sprout)
367
target_transport = get_transport(url, possible_transports)
368
target_transport.ensure_base()
369
cloning_format = self.cloning_metadir(stacked)
370
# Create/update the result branch
371
result = cloning_format.initialize_on_transport(target_transport)
372
# if a stacked branch wasn't requested, we don't create one
373
# even if the origin was stacked
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
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
391
repository_policy = result.determine_repository_policy(
392
force_new_repo, stacked_branch_url, require_stacking=stacked)
393
result_repo, is_new_repo = repository_policy.acquire_repository()
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)
400
if source_repository is not None:
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)
408
if source_branch is None:
409
# this is for sprouting a controldir without a branch; is that
411
# Not especially, but it's part of the contract.
412
result_branch = result.create_branch()
414
result_branch = source_branch.sprout(result,
415
revision_id=revision_id, repository_policy=repository_policy)
416
mutter("created new branch %r" % (result_branch,))
418
# Create/update the result working tree
419
if (create_tree_if_local and
420
isinstance(target_transport, local.LocalTransport) and
421
(result_repo is None or result_repo.make_working_trees())):
422
wt = result.create_workingtree(accelerator_tree=accelerator_tree,
426
if wt.path2id('') is None:
428
wt.set_root_id(self.open_workingtree.get_root_id())
429
except errors.NoWorkingTree:
435
if recurse == 'down':
437
basis = wt.basis_tree()
439
subtrees = basis.iter_references()
440
elif result_branch is not None:
441
basis = result_branch.basis_tree()
443
subtrees = basis.iter_references()
444
elif source_branch is not None:
445
basis = source_branch.basis_tree()
447
subtrees = basis.iter_references()
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:
357
464
def push_branch(self, source, revision_id=None, overwrite=False,
358
465
remember=False, create_prefix=False):
483
586
:param create_prefix: Create any missing directories leading up to
485
588
:param use_existing_dir: Use an existing directory if one exists.
486
:param no_tree: If set to true prevents creation of a working tree.
488
590
raise NotImplementedError(self.clone_on_transport)
491
def find_bzrdirs(klass, transport, evaluate=None, list_current=None):
492
"""Find control dirs recursively from current location.
494
This is intended primarily as a building block for more sophisticated
495
functionality, like finding trees under a directory, or finding
496
branches that use a given repository.
498
:param evaluate: An optional callable that yields recurse, value,
499
where recurse controls whether this controldir is recursed into
500
and value is the value to yield. By default, all bzrdirs
501
are recursed into, and the return value is the controldir.
502
:param list_current: if supplied, use this function to list the current
503
directory, instead of Transport.list_dir
504
:return: a generator of found bzrdirs, or whatever evaluate returns.
506
if list_current is None:
507
def list_current(transport):
508
return transport.list_dir('')
510
def evaluate(controldir):
511
return True, controldir
513
pending = [transport]
514
while len(pending) > 0:
515
current_transport = pending.pop()
518
controldir = klass.open_from_transport(current_transport)
519
except (errors.NotBranchError, errors.PermissionDenied):
522
recurse, value = evaluate(controldir)
525
subdirs = list_current(current_transport)
526
except (errors.NoSuchFile, errors.PermissionDenied):
529
for subdir in sorted(subdirs, reverse=True):
530
pending.append(current_transport.clone(subdir))
533
def find_branches(klass, transport):
534
"""Find all branches under a transport.
536
This will find all branches below the transport, including branches
537
inside other branches. Where possible, it will use
538
Repository.find_branches.
540
To list all the branches that use a particular Repository, see
541
Repository.find_branches
543
def evaluate(controldir):
545
repository = controldir.open_repository()
546
except errors.NoRepositoryPresent:
549
return False, ([], repository)
550
return True, (controldir.list_branches(), None)
552
for branches, repo in klass.find_bzrdirs(
553
transport, evaluate=evaluate):
555
ret.extend(repo.find_branches())
556
if branches is not None:
561
def create_branch_and_repo(klass, base, force_new_repo=False, format=None):
562
"""Create a new ControlDir, Branch and Repository at the url 'base'.
564
This will use the current default ControlDirFormat unless one is
565
specified, and use whatever
566
repository format that that uses via controldir.create_branch and
567
create_repository. If a shared repository is available that is used
570
The created Branch object is returned.
572
:param base: The URL to create the branch at.
573
:param force_new_repo: If True a new repository is always created.
574
:param format: If supplied, the format of branch to create. If not
575
supplied, the default is used.
577
controldir = klass.create(base, format)
578
controldir._find_or_create_repository(force_new_repo)
579
return controldir.create_branch()
582
def create_branch_convenience(klass, base, force_new_repo=False,
583
force_new_tree=None, format=None,
584
possible_transports=None):
585
"""Create a new ControlDir, Branch and Repository at the url 'base'.
587
This is a convenience function - it will use an existing repository
588
if possible, can be told explicitly whether to create a working tree or
591
This will use the current default ControlDirFormat unless one is
592
specified, and use whatever
593
repository format that that uses via ControlDir.create_branch and
594
create_repository. If a shared repository is available that is used
595
preferentially. Whatever repository is used, its tree creation policy
598
The created Branch object is returned.
599
If a working tree cannot be made due to base not being a file:// url,
600
no error is raised unless force_new_tree is True, in which case no
601
data is created on disk and NotLocalUrl is raised.
603
:param base: The URL to create the branch at.
604
:param force_new_repo: If True a new repository is always created.
605
:param force_new_tree: If True or False force creation of a tree or
606
prevent such creation respectively.
607
:param format: Override for the controldir format to create.
608
:param possible_transports: An optional reusable transports list.
611
# check for non local urls
612
t = _mod_transport.get_transport(base, possible_transports)
613
if not isinstance(t, local.LocalTransport):
614
raise errors.NotLocalUrl(base)
615
controldir = klass.create(base, format, possible_transports)
616
repo = controldir._find_or_create_repository(force_new_repo)
617
result = controldir.create_branch()
618
if force_new_tree or (repo.make_working_trees() and
619
force_new_tree is None):
621
controldir.create_workingtree()
622
except errors.NotLocalUrl:
627
def create_standalone_workingtree(klass, base, format=None):
628
"""Create a new ControlDir, WorkingTree, Branch and Repository at 'base'.
630
'base' must be a local path or a file:// url.
632
This will use the current default ControlDirFormat unless one is
633
specified, and use whatever
634
repository format that that uses for bzrdirformat.create_workingtree,
635
create_branch and create_repository.
637
:param format: Override for the controldir format to create.
638
:return: The WorkingTree object.
640
t = _mod_transport.get_transport(base)
641
if not isinstance(t, local.LocalTransport):
642
raise errors.NotLocalUrl(base)
643
controldir = klass.create_branch_and_repo(base,
645
format=format).bzrdir
646
return controldir.create_workingtree()
649
def open_unsupported(klass, base):
650
"""Open a branch which is not supported."""
651
return klass.open(base, _unsupported=True)
654
def open(klass, base, _unsupported=False, possible_transports=None):
655
"""Open an existing controldir, rooted at 'base' (url).
657
:param _unsupported: a private parameter to the ControlDir class.
659
t = _mod_transport.get_transport(base, possible_transports)
660
return klass.open_from_transport(t, _unsupported=_unsupported)
663
def open_from_transport(klass, transport, _unsupported=False,
664
_server_formats=True):
665
"""Open a controldir within a particular directory.
667
:param transport: Transport containing the controldir.
668
:param _unsupported: private.
670
for hook in klass.hooks['pre_open']:
672
# Keep initial base since 'transport' may be modified while following
674
base = transport.base
675
def find_format(transport):
676
return transport, ControlDirFormat.find_format(
677
transport, _server_formats=_server_formats)
679
def redirected(transport, e, redirection_notice):
680
redirected_transport = transport._redirected_to(e.source, e.target)
681
if redirected_transport is None:
682
raise errors.NotBranchError(base)
683
trace.note(gettext('{0} is{1} redirected to {2}').format(
684
transport.base, e.permanently, redirected_transport.base))
685
return redirected_transport
688
transport, format = _mod_transport.do_catching_redirections(
689
find_format, transport, redirected)
690
except errors.TooManyRedirections:
691
raise errors.NotBranchError(base)
693
format.check_support_status(_unsupported)
694
return format.open(transport, _found=True)
697
def open_containing(klass, url, possible_transports=None):
698
"""Open an existing branch which contains url.
700
:param url: url to search from.
702
See open_containing_from_transport for more detail.
704
transport = _mod_transport.get_transport(url, possible_transports)
705
return klass.open_containing_from_transport(transport)
708
def open_containing_from_transport(klass, a_transport):
709
"""Open an existing branch which contains a_transport.base.
711
This probes for a branch at a_transport, and searches upwards from there.
713
Basically we keep looking up until we find the control directory or
714
run into the root. If there isn't one, raises NotBranchError.
715
If there is one and it is either an unrecognised format or an unsupported
716
format, UnknownFormatError or UnsupportedFormatError are raised.
717
If there is one, it is returned, along with the unused portion of url.
719
:return: The ControlDir that contains the path, and a Unicode path
720
for the rest of the URL.
722
# this gets the normalised url back. I.e. '.' -> the full path.
723
url = a_transport.base
726
result = klass.open_from_transport(a_transport)
727
return result, urlutils.unescape(a_transport.relpath(url))
728
except errors.NotBranchError, e:
731
new_t = a_transport.clone('..')
732
except errors.InvalidURLJoin:
733
# reached the root, whatever that may be
734
raise errors.NotBranchError(path=url)
735
if new_t.base == a_transport.base:
736
# reached the root, whatever that may be
737
raise errors.NotBranchError(path=url)
741
def open_tree_or_branch(klass, location):
742
"""Return the branch and working tree at a location.
744
If there is no tree at the location, tree will be None.
745
If there is no branch at the location, an exception will be
747
:return: (tree, branch)
749
controldir = klass.open(location)
750
return controldir._get_tree_branch()
753
def open_containing_tree_or_branch(klass, location):
754
"""Return the branch and working tree contained by a location.
756
Returns (tree, branch, relpath).
757
If there is no tree at containing the location, tree will be None.
758
If there is no branch containing the location, an exception will be
760
relpath is the portion of the path that is contained by the branch.
762
controldir, relpath = klass.open_containing(location)
763
tree, branch = controldir._get_tree_branch()
764
return tree, branch, relpath
767
def open_containing_tree_branch_or_repository(klass, location):
768
"""Return the working tree, branch and repo contained by a location.
770
Returns (tree, branch, repository, relpath).
771
If there is no tree containing the location, tree will be None.
772
If there is no branch containing the location, branch will be None.
773
If there is no repository containing the location, repository will be
775
relpath is the portion of the path that is contained by the innermost
778
If no tree, branch or repository is found, a NotBranchError is raised.
780
controldir, relpath = klass.open_containing(location)
782
tree, branch = controldir._get_tree_branch()
783
except errors.NotBranchError:
785
repo = controldir.find_repository()
786
return None, None, repo, relpath
787
except (errors.NoRepositoryPresent):
788
raise errors.NotBranchError(location)
789
return tree, branch, branch.repository, relpath
792
def create(klass, base, format=None, possible_transports=None):
793
"""Create a new ControlDir at the url 'base'.
795
:param format: If supplied, the format of branch to create. If not
796
supplied, the default is used.
797
:param possible_transports: If supplied, a list of transports that
798
can be reused to share a remote connection.
800
if klass is not ControlDir:
801
raise AssertionError("ControlDir.create always creates the"
802
"default format, not one of %r" % klass)
803
t = _mod_transport.get_transport(base, possible_transports)
806
format = ControlDirFormat.get_default_format()
807
return format.initialize_on_transport(t)
810
class ControlDirHooks(hooks.Hooks):
811
"""Hooks for ControlDir operations."""
814
"""Create the default hooks."""
815
hooks.Hooks.__init__(self, "bzrlib.controldir", "ControlDir.hooks")
816
self.add_hook('pre_open',
817
"Invoked before attempting to open a ControlDir with the transport "
818
"that the open will use.", (1, 14))
819
self.add_hook('post_repo_init',
820
"Invoked after a repository has been initialized. "
821
"post_repo_init is called with a "
822
"bzrlib.controldir.RepoInitHookParams.",
825
# install the default hooks
826
ControlDir.hooks = ControlDirHooks()
829
class ControlComponentFormat(object):
830
"""A component that can live inside of a .bzr meta directory."""
832
upgrade_recommended = False
834
def get_format_string(self):
835
"""Return the format of this format, if usable in meta directories."""
836
raise NotImplementedError(self.get_format_string)
838
def get_format_description(self):
839
"""Return the short description for this format."""
840
raise NotImplementedError(self.get_format_description)
842
def is_supported(self):
843
"""Is this format supported?
845
Supported formats must be initializable and openable.
846
Unsupported formats may not support initialization or committing or
847
some other features depending on the reason for not being supported.
851
def check_support_status(self, allow_unsupported, recommend_upgrade=True,
853
"""Give an error or warning on old formats.
855
:param allow_unsupported: If true, allow opening
856
formats that are strongly deprecated, and which may
857
have limited functionality.
859
:param recommend_upgrade: If true (default), warn
860
the user through the ui object that they may wish
861
to upgrade the object.
863
if not allow_unsupported and not self.is_supported():
864
# see open_downlevel to open legacy branches.
865
raise errors.UnsupportedFormatError(format=self)
866
if recommend_upgrade and self.upgrade_recommended:
867
ui.ui_factory.recommend_upgrade(
868
self.get_format_description(), basedir)
871
class ControlComponentFormatRegistry(registry.FormatRegistry):
872
"""A registry for control components (branch, workingtree, repository)."""
874
def __init__(self, other_registry=None):
875
super(ControlComponentFormatRegistry, self).__init__(other_registry)
876
self._extra_formats = []
878
def register(self, format):
879
"""Register a new format."""
880
super(ControlComponentFormatRegistry, self).register(
881
format.get_format_string(), format)
883
def remove(self, format):
884
"""Remove a registered format."""
885
super(ControlComponentFormatRegistry, self).remove(
886
format.get_format_string())
888
def register_extra(self, format):
889
"""Register a format that can not be used in a metadir.
891
This is mainly useful to allow custom repository formats, such as older
892
Bazaar formats and foreign formats, to be tested.
894
self._extra_formats.append(registry._ObjectGetter(format))
896
def remove_extra(self, format):
897
"""Remove an extra format.
899
self._extra_formats.remove(registry._ObjectGetter(format))
901
def register_extra_lazy(self, module_name, member_name):
902
"""Register a format lazily.
904
self._extra_formats.append(
905
registry._LazyObjectGetter(module_name, member_name))
907
def _get_extra(self):
908
"""Return all "extra" formats, not usable in meta directories."""
910
for getter in self._extra_formats:
918
"""Return all formats, even those not usable in metadirs.
921
for name in self.keys():
926
return result + self._get_extra()
928
def _get_all_modules(self):
929
"""Return a set of the modules providing objects."""
931
for name in self.keys():
932
modules.add(self._get_module(name))
933
for getter in self._extra_formats:
934
modules.add(getter.get_module())
938
class Converter(object):
939
"""Converts a disk format object from one format to another."""
941
def convert(self, to_convert, pb):
942
"""Perform the conversion of to_convert, giving feedback via pb.
944
:param to_convert: The disk object to convert.
945
:param pb: a progress bar to use for progress information.
948
def step(self, message):
949
"""Update the pb by a step."""
951
self.pb.update(message, self.count, self.total)
954
593
class ControlDirFormat(object):
955
594
"""An encapsulation of the initialization and open routines for a format.