206
207
raise errors.NoColocatedBranchSupport(self)
209
def get_branch_transport(self, branch_format, name=None):
210
"""Get the transport for use by branch format in this ControlDir.
212
Note that bzr dirs that do not support format strings will raise
213
IncompatibleFormat if the branch format they are given has
214
a format string, and vice versa.
216
If branch_format is None, the transport is returned with no
217
checking. If it is not None, then the returned transport is
218
guaranteed to point to an existing directory ready for use.
220
raise NotImplementedError(self.get_branch_transport)
222
def get_repository_transport(self, repository_format):
223
"""Get the transport for use by repository format in this ControlDir.
225
Note that bzr dirs that do not support format strings will raise
226
IncompatibleFormat if the repository format they are given has
227
a format string, and vice versa.
229
If repository_format is None, the transport is returned with no
230
checking. If it is not None, then the returned transport is
231
guaranteed to point to an existing directory ready for use.
233
raise NotImplementedError(self.get_repository_transport)
235
def get_workingtree_transport(self, tree_format):
236
"""Get the transport for use by workingtree format in this ControlDir.
238
Note that bzr dirs that do not support format strings will raise
239
IncompatibleFormat if the workingtree format they are given has a
240
format string, and vice versa.
242
If workingtree_format is None, the transport is returned with no
243
checking. If it is not None, then the returned transport is
244
guaranteed to point to an existing directory ready for use.
246
raise NotImplementedError(self.get_workingtree_transport)
248
210
def open_branch(self, name=None, unsupported=False,
249
211
ignore_fallbacks=False):
250
212
"""Open the branch object at this ControlDir if one is present.
365
328
:param create_tree_if_local: If true, a working-tree will be created
366
329
when working locally.
368
operation = cleanup.OperationWithCleanups(self._sprout)
369
return operation.run(url, revision_id=revision_id,
370
force_new_repo=force_new_repo, recurse=recurse,
371
possible_transports=possible_transports,
372
accelerator_tree=accelerator_tree, hardlink=hardlink,
373
stacked=stacked, source_branch=source_branch,
374
create_tree_if_local=create_tree_if_local)
376
def _sprout(self, op, url, revision_id=None, force_new_repo=False,
377
recurse='down', possible_transports=None,
378
accelerator_tree=None, hardlink=False, stacked=False,
379
source_branch=None, create_tree_if_local=True):
380
add_cleanup = op.add_cleanup
381
target_transport = _mod_transport.get_transport(url,
383
target_transport.ensure_base()
384
cloning_format = self.cloning_metadir(stacked)
385
# Create/update the result branch
386
result = cloning_format.initialize_on_transport(target_transport)
387
# if a stacked branch wasn't requested, we don't create one
388
# 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
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)
411
repository_policy = result.determine_repository_policy(
412
force_new_repo, stacked_branch_url, require_stacking=stacked)
413
result_repo, is_new_repo = repository_policy.acquire_repository()
414
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)
421
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)
429
if source_branch is None:
430
# this is for sprouting a controldir without a branch; is that
432
# Not especially, but it's part of the contract.
433
result_branch = result.create_branch()
435
result_branch = source_branch.sprout(result,
436
revision_id=revision_id, repository_policy=repository_policy,
437
repository=result_repo)
438
mutter("created new branch %r" % (result_branch,))
440
# Create/update the result working tree
441
if (create_tree_if_local and
442
isinstance(target_transport, local.LocalTransport) and
443
(result_repo is None or result_repo.make_working_trees())):
444
wt = result.create_workingtree(accelerator_tree=accelerator_tree,
445
hardlink=hardlink, from_branch=result_branch)
448
if wt.path2id('') is None:
450
wt.set_root_id(self.open_workingtree.get_root_id())
451
except errors.NoWorkingTree:
457
if recurse == 'down':
459
basis = wt.basis_tree()
461
subtrees = basis.iter_references()
462
elif result_branch is not None:
463
basis = result_branch.basis_tree()
465
subtrees = basis.iter_references()
466
elif source_branch is not None:
467
basis = source_branch.basis_tree()
469
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:
331
raise NotImplementedError(self.sprout)
486
333
def push_branch(self, source, revision_id=None, overwrite=False,
487
334
remember=False, create_prefix=False):
612
459
:param create_prefix: Create any missing directories leading up to
614
461
:param use_existing_dir: Use an existing directory if one exists.
462
:param no_tree: If set to true prevents creation of a working tree.
616
464
raise NotImplementedError(self.clone_on_transport)
467
class ControlComponentFormat(object):
468
"""A component that can live inside of a .bzr meta directory."""
470
upgrade_recommended = False
472
def get_format_string(self):
473
"""Return the format of this format, if usable in meta directories."""
474
raise NotImplementedError(self.get_format_string)
476
def get_format_description(self):
477
"""Return the short description for this format."""
478
raise NotImplementedError(self.get_format_description)
480
def is_supported(self):
481
"""Is this format supported?
483
Supported formats must be initializable and openable.
484
Unsupported formats may not support initialization or committing or
485
some other features depending on the reason for not being supported.
489
def check_support_status(self, allow_unsupported, recommend_upgrade=True,
491
"""Give an error or warning on old formats.
493
:param allow_unsupported: If true, allow opening
494
formats that are strongly deprecated, and which may
495
have limited functionality.
497
:param recommend_upgrade: If true (default), warn
498
the user through the ui object that they may wish
499
to upgrade the object.
501
if not allow_unsupported and not self.is_supported():
502
# see open_downlevel to open legacy branches.
503
raise errors.UnsupportedFormatError(format=self)
504
if recommend_upgrade and self.upgrade_recommended:
505
ui.ui_factory.recommend_upgrade(
506
self.get_format_description(), basedir)
509
class ControlComponentFormatRegistry(registry.FormatRegistry):
510
"""A registry for control components (branch, workingtree, repository)."""
512
def __init__(self, other_registry=None):
513
super(ControlComponentFormatRegistry, self).__init__(other_registry)
514
self._extra_formats = []
516
def register(self, format):
517
"""Register a new format."""
518
super(ControlComponentFormatRegistry, self).register(
519
format.get_format_string(), format)
521
def remove(self, format):
522
"""Remove a registered format."""
523
super(ControlComponentFormatRegistry, self).remove(
524
format.get_format_string())
526
def register_extra(self, format):
527
"""Register a format that can not be used in a metadir.
529
This is mainly useful to allow custom repository formats, such as older
530
Bazaar formats and foreign formats, to be tested.
532
self._extra_formats.append(registry._ObjectGetter(format))
534
def remove_extra(self, format):
535
"""Remove an extra format.
537
self._extra_formats.remove(registry._ObjectGetter(format))
539
def register_extra_lazy(self, module_name, member_name):
540
"""Register a format lazily.
542
self._extra_formats.append(
543
registry._LazyObjectGetter(module_name, member_name))
545
def _get_extra(self):
546
"""Return all "extra" formats, not usable in meta directories."""
548
for getter in self._extra_formats:
556
"""Return all formats, even those not usable in metadirs.
559
for name in self.keys():
564
return result + self._get_extra()
566
def _get_all_modules(self):
567
"""Return a set of the modules providing objects."""
569
for name in self.keys():
570
modules.add(self._get_module(name))
571
for getter in self._extra_formats:
572
modules.add(getter.get_module())
576
class Converter(object):
577
"""Converts a disk format object from one format to another."""
579
def convert(self, to_convert, pb):
580
"""Perform the conversion of to_convert, giving feedback via pb.
582
:param to_convert: The disk object to convert.
583
:param pb: a progress bar to use for progress information.
586
def step(self, message):
587
"""Update the pb by a step."""
589
self.pb.update(message, self.count, self.total)
619
592
class ControlDirFormat(object):
620
593
"""An encapsulation of the initialization and open routines for a format.
670
def check_support_status(self, allow_unsupported, recommend_upgrade=True,
672
"""Give an error or warning on old formats.
674
:param allow_unsupported: If true, allow opening
675
formats that are strongly deprecated, and which may
676
have limited functionality.
678
:param recommend_upgrade: If true (default), warn
679
the user through the ui object that they may wish
680
to upgrade the object.
682
if not allow_unsupported and not self.is_supported():
683
# see open_downlevel to open legacy branches.
684
raise errors.UnsupportedFormatError(format=self)
685
if recommend_upgrade and self.upgrade_recommended:
686
ui.ui_factory.recommend_upgrade(
687
self.get_format_description(), basedir)
694
689
def same_model(self, target_format):
695
690
return (self.repository_format.rich_root_data ==
696
691
target_format.rich_root_data)