364
363
:param create_tree_if_local: If true, a working-tree will be created
365
364
when working locally.
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:
366
raise NotImplementedError(self.sprout)
464
368
def push_branch(self, source, revision_id=None, overwrite=False,
465
369
remember=False, create_prefix=False):
586
494
:param create_prefix: Create any missing directories leading up to
588
496
:param use_existing_dir: Use an existing directory if one exists.
497
:param no_tree: If set to true prevents creation of a working tree.
590
499
raise NotImplementedError(self.clone_on_transport)
502
def find_bzrdirs(klass, transport, evaluate=None, list_current=None):
503
"""Find control dirs recursively from current location.
505
This is intended primarily as a building block for more sophisticated
506
functionality, like finding trees under a directory, or finding
507
branches that use a given repository.
509
:param evaluate: An optional callable that yields recurse, value,
510
where recurse controls whether this controldir is recursed into
511
and value is the value to yield. By default, all bzrdirs
512
are recursed into, and the return value is the controldir.
513
:param list_current: if supplied, use this function to list the current
514
directory, instead of Transport.list_dir
515
:return: a generator of found bzrdirs, or whatever evaluate returns.
517
if list_current is None:
518
def list_current(transport):
519
return transport.list_dir('')
521
def evaluate(controldir):
522
return True, controldir
524
pending = [transport]
525
while len(pending) > 0:
526
current_transport = pending.pop()
529
controldir = klass.open_from_transport(current_transport)
530
except (errors.NotBranchError, errors.PermissionDenied):
533
recurse, value = evaluate(controldir)
536
subdirs = list_current(current_transport)
537
except (errors.NoSuchFile, errors.PermissionDenied):
540
for subdir in sorted(subdirs, reverse=True):
541
pending.append(current_transport.clone(subdir))
544
def find_branches(klass, transport):
545
"""Find all branches under a transport.
547
This will find all branches below the transport, including branches
548
inside other branches. Where possible, it will use
549
Repository.find_branches.
551
To list all the branches that use a particular Repository, see
552
Repository.find_branches
554
def evaluate(controldir):
556
repository = controldir.open_repository()
557
except errors.NoRepositoryPresent:
560
return False, ([], repository)
561
return True, (controldir.list_branches(), None)
563
for branches, repo in klass.find_bzrdirs(
564
transport, evaluate=evaluate):
566
ret.extend(repo.find_branches())
567
if branches is not None:
572
def create_branch_and_repo(klass, base, force_new_repo=False, format=None):
573
"""Create a new ControlDir, Branch and Repository at the url 'base'.
575
This will use the current default ControlDirFormat unless one is
576
specified, and use whatever
577
repository format that that uses via controldir.create_branch and
578
create_repository. If a shared repository is available that is used
581
The created Branch object is returned.
583
:param base: The URL to create the branch at.
584
:param force_new_repo: If True a new repository is always created.
585
:param format: If supplied, the format of branch to create. If not
586
supplied, the default is used.
588
controldir = klass.create(base, format)
589
controldir._find_or_create_repository(force_new_repo)
590
return controldir.create_branch()
593
def create_branch_convenience(klass, base, force_new_repo=False,
594
force_new_tree=None, format=None,
595
possible_transports=None):
596
"""Create a new ControlDir, Branch and Repository at the url 'base'.
598
This is a convenience function - it will use an existing repository
599
if possible, can be told explicitly whether to create a working tree or
602
This will use the current default ControlDirFormat unless one is
603
specified, and use whatever
604
repository format that that uses via ControlDir.create_branch and
605
create_repository. If a shared repository is available that is used
606
preferentially. Whatever repository is used, its tree creation policy
609
The created Branch object is returned.
610
If a working tree cannot be made due to base not being a file:// url,
611
no error is raised unless force_new_tree is True, in which case no
612
data is created on disk and NotLocalUrl is raised.
614
:param base: The URL to create the branch at.
615
:param force_new_repo: If True a new repository is always created.
616
:param force_new_tree: If True or False force creation of a tree or
617
prevent such creation respectively.
618
:param format: Override for the controldir format to create.
619
:param possible_transports: An optional reusable transports list.
622
# check for non local urls
623
t = _mod_transport.get_transport(base, possible_transports)
624
if not isinstance(t, local.LocalTransport):
625
raise errors.NotLocalUrl(base)
626
controldir = klass.create(base, format, possible_transports)
627
repo = controldir._find_or_create_repository(force_new_repo)
628
result = controldir.create_branch()
629
if force_new_tree or (repo.make_working_trees() and
630
force_new_tree is None):
632
controldir.create_workingtree()
633
except errors.NotLocalUrl:
638
def create_standalone_workingtree(klass, base, format=None):
639
"""Create a new ControlDir, WorkingTree, Branch and Repository at 'base'.
641
'base' must be a local path or a file:// url.
643
This will use the current default ControlDirFormat unless one is
644
specified, and use whatever
645
repository format that that uses for bzrdirformat.create_workingtree,
646
create_branch and create_repository.
648
:param format: Override for the controldir format to create.
649
:return: The WorkingTree object.
651
t = _mod_transport.get_transport(base)
652
if not isinstance(t, local.LocalTransport):
653
raise errors.NotLocalUrl(base)
654
controldir = klass.create_branch_and_repo(base,
656
format=format).bzrdir
657
return controldir.create_workingtree()
660
def open_unsupported(klass, base):
661
"""Open a branch which is not supported."""
662
return klass.open(base, _unsupported=True)
665
def open(klass, base, _unsupported=False, possible_transports=None):
666
"""Open an existing controldir, rooted at 'base' (url).
668
:param _unsupported: a private parameter to the ControlDir class.
670
t = _mod_transport.get_transport(base, possible_transports)
671
return klass.open_from_transport(t, _unsupported=_unsupported)
674
def open_from_transport(klass, transport, _unsupported=False,
675
_server_formats=True):
676
"""Open a controldir within a particular directory.
678
:param transport: Transport containing the controldir.
679
:param _unsupported: private.
681
for hook in klass.hooks['pre_open']:
683
# Keep initial base since 'transport' may be modified while following
685
base = transport.base
686
def find_format(transport):
687
return transport, ControlDirFormat.find_format(
688
transport, _server_formats=_server_formats)
690
def redirected(transport, e, redirection_notice):
691
redirected_transport = transport._redirected_to(e.source, e.target)
692
if redirected_transport is None:
693
raise errors.NotBranchError(base)
694
trace.note(gettext('{0} is{1} redirected to {2}').format(
695
transport.base, e.permanently, redirected_transport.base))
696
return redirected_transport
699
transport, format = _mod_transport.do_catching_redirections(
700
find_format, transport, redirected)
701
except errors.TooManyRedirections:
702
raise errors.NotBranchError(base)
704
format.check_support_status(_unsupported)
705
return format.open(transport, _found=True)
708
def open_containing(klass, url, possible_transports=None):
709
"""Open an existing branch which contains url.
711
:param url: url to search from.
713
See open_containing_from_transport for more detail.
715
transport = _mod_transport.get_transport(url, possible_transports)
716
return klass.open_containing_from_transport(transport)
719
def open_containing_from_transport(klass, a_transport):
720
"""Open an existing branch which contains a_transport.base.
722
This probes for a branch at a_transport, and searches upwards from there.
724
Basically we keep looking up until we find the control directory or
725
run into the root. If there isn't one, raises NotBranchError.
726
If there is one and it is either an unrecognised format or an unsupported
727
format, UnknownFormatError or UnsupportedFormatError are raised.
728
If there is one, it is returned, along with the unused portion of url.
730
:return: The ControlDir that contains the path, and a Unicode path
731
for the rest of the URL.
733
# this gets the normalised url back. I.e. '.' -> the full path.
734
url = a_transport.base
737
result = klass.open_from_transport(a_transport)
738
return result, urlutils.unescape(a_transport.relpath(url))
739
except errors.NotBranchError, e:
742
new_t = a_transport.clone('..')
743
except errors.InvalidURLJoin:
744
# reached the root, whatever that may be
745
raise errors.NotBranchError(path=url)
746
if new_t.base == a_transport.base:
747
# reached the root, whatever that may be
748
raise errors.NotBranchError(path=url)
752
def open_tree_or_branch(klass, location):
753
"""Return the branch and working tree at a location.
755
If there is no tree at the location, tree will be None.
756
If there is no branch at the location, an exception will be
758
:return: (tree, branch)
760
controldir = klass.open(location)
761
return controldir._get_tree_branch()
764
def open_containing_tree_or_branch(klass, location):
765
"""Return the branch and working tree contained by a location.
767
Returns (tree, branch, relpath).
768
If there is no tree at containing the location, tree will be None.
769
If there is no branch containing the location, an exception will be
771
relpath is the portion of the path that is contained by the branch.
773
controldir, relpath = klass.open_containing(location)
774
tree, branch = controldir._get_tree_branch()
775
return tree, branch, relpath
778
def open_containing_tree_branch_or_repository(klass, location):
779
"""Return the working tree, branch and repo contained by a location.
781
Returns (tree, branch, repository, relpath).
782
If there is no tree containing the location, tree will be None.
783
If there is no branch containing the location, branch will be None.
784
If there is no repository containing the location, repository will be
786
relpath is the portion of the path that is contained by the innermost
789
If no tree, branch or repository is found, a NotBranchError is raised.
791
controldir, relpath = klass.open_containing(location)
793
tree, branch = controldir._get_tree_branch()
794
except errors.NotBranchError:
796
repo = controldir.find_repository()
797
return None, None, repo, relpath
798
except (errors.NoRepositoryPresent):
799
raise errors.NotBranchError(location)
800
return tree, branch, branch.repository, relpath
803
def create(klass, base, format=None, possible_transports=None):
804
"""Create a new ControlDir at the url 'base'.
806
:param format: If supplied, the format of branch to create. If not
807
supplied, the default is used.
808
:param possible_transports: If supplied, a list of transports that
809
can be reused to share a remote connection.
811
if klass is not ControlDir:
812
raise AssertionError("ControlDir.create always creates the"
813
"default format, not one of %r" % klass)
814
t = _mod_transport.get_transport(base, possible_transports)
817
format = ControlDirFormat.get_default_format()
818
return format.initialize_on_transport(t)
821
class ControlDirHooks(hooks.Hooks):
822
"""Hooks for ControlDir operations."""
825
"""Create the default hooks."""
826
hooks.Hooks.__init__(self, "bzrlib.controldir", "ControlDir.hooks")
827
self.add_hook('pre_open',
828
"Invoked before attempting to open a ControlDir with the transport "
829
"that the open will use.", (1, 14))
830
self.add_hook('post_repo_init',
831
"Invoked after a repository has been initialized. "
832
"post_repo_init is called with a "
833
"bzrlib.controldir.RepoInitHookParams.",
836
# install the default hooks
837
ControlDir.hooks = ControlDirHooks()
840
class ControlComponentFormat(object):
841
"""A component that can live inside of a .bzr meta directory."""
843
upgrade_recommended = False
845
def get_format_description(self):
846
"""Return the short description for this format."""
847
raise NotImplementedError(self.get_format_description)
849
def is_supported(self):
850
"""Is this format supported?
852
Supported formats must be initializable and openable.
853
Unsupported formats may not support initialization or committing or
854
some other features depending on the reason for not being supported.
858
def check_support_status(self, allow_unsupported, recommend_upgrade=True,
860
"""Give an error or warning on old formats.
862
:param allow_unsupported: If true, allow opening
863
formats that are strongly deprecated, and which may
864
have limited functionality.
866
:param recommend_upgrade: If true (default), warn
867
the user through the ui object that they may wish
868
to upgrade the object.
870
if not allow_unsupported and not self.is_supported():
871
# see open_downlevel to open legacy branches.
872
raise errors.UnsupportedFormatError(format=self)
873
if recommend_upgrade and self.upgrade_recommended:
874
ui.ui_factory.recommend_upgrade(
875
self.get_format_description(), basedir)
878
def get_format_string(cls):
879
raise NotImplementedError(cls.get_format_string)
882
class ControlComponentFormatRegistry(registry.FormatRegistry):
883
"""A registry for control components (branch, workingtree, repository)."""
885
def __init__(self, other_registry=None):
886
super(ControlComponentFormatRegistry, self).__init__(other_registry)
887
self._extra_formats = []
889
def register(self, format):
890
"""Register a new format."""
891
super(ControlComponentFormatRegistry, self).register(
892
format.get_format_string(), format)
894
def remove(self, format):
895
"""Remove a registered format."""
896
super(ControlComponentFormatRegistry, self).remove(
897
format.get_format_string())
899
def register_extra(self, format):
900
"""Register a format that can not be used in a metadir.
902
This is mainly useful to allow custom repository formats, such as older
903
Bazaar formats and foreign formats, to be tested.
905
self._extra_formats.append(registry._ObjectGetter(format))
907
def remove_extra(self, format):
908
"""Remove an extra format.
910
self._extra_formats.remove(registry._ObjectGetter(format))
912
def register_extra_lazy(self, module_name, member_name):
913
"""Register a format lazily.
915
self._extra_formats.append(
916
registry._LazyObjectGetter(module_name, member_name))
918
def _get_extra(self):
919
"""Return all "extra" formats, not usable in meta directories."""
921
for getter in self._extra_formats:
929
"""Return all formats, even those not usable in metadirs.
932
for name in self.keys():
937
return result + self._get_extra()
939
def _get_all_modules(self):
940
"""Return a set of the modules providing objects."""
942
for name in self.keys():
943
modules.add(self._get_module(name))
944
for getter in self._extra_formats:
945
modules.add(getter.get_module())
949
class Converter(object):
950
"""Converts a disk format object from one format to another."""
952
def convert(self, to_convert, pb):
953
"""Perform the conversion of to_convert, giving feedback via pb.
955
:param to_convert: The disk object to convert.
956
:param pb: a progress bar to use for progress information.
959
def step(self, message):
960
"""Update the pb by a step."""
962
self.pb.update(message, self.count, self.total)
593
965
class ControlDirFormat(object):
594
966
"""An encapsulation of the initialization and open routines for a format.