134
141
raise NotImplementedError(self.needs_format_conversion)
136
def create_repository(self, shared=False):
137
"""Create a new repository in this control directory.
139
:param shared: If a shared repository should be created
140
:return: The newly created repository
142
raise NotImplementedError(self.create_repository)
144
143
def destroy_repository(self):
145
144
"""Destroy the repository in this ControlDir."""
146
145
raise NotImplementedError(self.destroy_repository)
148
def create_branch(self, name=None, repository=None,
149
append_revisions_only=None):
147
def create_branch(self, name=None, repository=None):
150
148
"""Create a branch in this ControlDir.
152
150
:param name: Name of the colocated branch to create, None for
153
151
the default branch.
154
:param append_revisions_only: Whether this branch should only allow
155
appending new revisions to its history.
157
153
The controldirs format will control what branch format is created.
158
154
For more control see BranchFormatXX.create(a_controldir).
217
206
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)
220
248
def open_branch(self, name=None, unsupported=False,
221
249
ignore_fallbacks=False):
222
250
"""Open the branch object at this ControlDir if one is present.
348
365
:param create_tree_if_local: If true, a working-tree will be created
349
366
when working locally.
351
raise NotImplementedError(self.sprout)
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 = get_transport(url, possible_transports)
382
target_transport.ensure_base()
383
cloning_format = self.cloning_metadir(stacked)
384
# Create/update the result branch
385
result = cloning_format.initialize_on_transport(target_transport)
386
# if a stacked branch wasn't requested, we don't create one
387
# even if the origin was stacked
388
stacked_branch_url = None
389
if source_branch is not None:
390
add_cleanup(source_branch.lock_read().unlock)
392
stacked_branch_url = self.root_transport.base
393
source_repository = source_branch.repository
396
source_branch = self.open_branch()
397
source_repository = source_branch.repository
399
stacked_branch_url = self.root_transport.base
400
except errors.NotBranchError:
403
source_repository = self.open_repository()
404
except errors.NoRepositoryPresent:
405
source_repository = None
407
add_cleanup(source_repository.lock_read().unlock)
409
add_cleanup(source_branch.lock_read().unlock)
410
repository_policy = result.determine_repository_policy(
411
force_new_repo, stacked_branch_url, require_stacking=stacked)
412
result_repo, is_new_repo = repository_policy.acquire_repository()
413
add_cleanup(result_repo.lock_write().unlock)
414
is_stacked = stacked or (len(result_repo._fallback_repositories) != 0)
415
if is_new_repo and revision_id is not None and not is_stacked:
416
fetch_spec = graph.PendingAncestryResult(
417
[revision_id], source_repository)
420
if source_repository is not None:
421
# Fetch while stacked to prevent unstacked fetch from
423
if fetch_spec is None:
424
result_repo.fetch(source_repository, revision_id=revision_id)
426
result_repo.fetch(source_repository, fetch_spec=fetch_spec)
428
if source_branch is None:
429
# this is for sprouting a controldir without a branch; is that
431
# Not especially, but it's part of the contract.
432
result_branch = result.create_branch()
434
result_branch = source_branch.sprout(result,
435
revision_id=revision_id, repository_policy=repository_policy,
436
repository=result_repo)
437
mutter("created new branch %r" % (result_branch,))
439
# Create/update the result working tree
440
if (create_tree_if_local and
441
isinstance(target_transport, local.LocalTransport) and
442
(result_repo is None or result_repo.make_working_trees())):
443
wt = result.create_workingtree(accelerator_tree=accelerator_tree,
444
hardlink=hardlink, from_branch=result_branch)
447
if wt.path2id('') is None:
449
wt.set_root_id(self.open_workingtree.get_root_id())
450
except errors.NoWorkingTree:
456
if recurse == 'down':
458
basis = wt.basis_tree()
460
subtrees = basis.iter_references()
461
elif result_branch is not None:
462
basis = result_branch.basis_tree()
464
subtrees = basis.iter_references()
465
elif source_branch is not None:
466
basis = source_branch.basis_tree()
468
subtrees = basis.iter_references()
473
for path, file_id in subtrees:
474
target = urlutils.join(url, urlutils.escape(path))
475
sublocation = source_branch.reference_parent(file_id, path)
476
sublocation.bzrdir.sprout(target,
477
basis.get_reference_revision(file_id, path),
478
force_new_repo=force_new_repo, recurse=recurse,
481
if basis is not None:
353
485
def push_branch(self, source, revision_id=None, overwrite=False,
354
486
remember=False, create_prefix=False):
457
585
:param preserve_stacking: When cloning a stacked branch, stack the
458
586
new branch on top of the other branch's stacked-on branch.
460
return self.clone_on_transport(_mod_transport.get_transport(url),
588
return self.clone_on_transport(get_transport(url),
461
589
revision_id=revision_id,
462
590
force_new_repo=force_new_repo,
463
591
preserve_stacking=preserve_stacking)
465
593
def clone_on_transport(self, transport, revision_id=None,
466
594
force_new_repo=False, preserve_stacking=False, stacked_on=None,
467
create_prefix=False, use_existing_dir=True, no_tree=False):
595
create_prefix=False, use_existing_dir=True):
468
596
"""Clone this bzrdir and its contents to transport verbatim.
470
598
:param transport: The transport for the location to produce the clone
479
607
:param create_prefix: Create any missing directories leading up to
481
609
:param use_existing_dir: Use an existing directory if one exists.
482
:param no_tree: If set to true prevents creation of a working tree.
484
611
raise NotImplementedError(self.clone_on_transport)
487
class ControlComponentFormat(object):
488
"""A component that can live inside of a .bzr meta directory."""
490
upgrade_recommended = False
492
def get_format_string(self):
493
"""Return the format of this format, if usable in meta directories."""
494
raise NotImplementedError(self.get_format_string)
496
def get_format_description(self):
497
"""Return the short description for this format."""
498
raise NotImplementedError(self.get_format_description)
500
def is_supported(self):
501
"""Is this format supported?
503
Supported formats must be initializable and openable.
504
Unsupported formats may not support initialization or committing or
505
some other features depending on the reason for not being supported.
509
def check_support_status(self, allow_unsupported, recommend_upgrade=True,
511
"""Give an error or warning on old formats.
513
:param allow_unsupported: If true, allow opening
514
formats that are strongly deprecated, and which may
515
have limited functionality.
517
:param recommend_upgrade: If true (default), warn
518
the user through the ui object that they may wish
519
to upgrade the object.
521
if not allow_unsupported and not self.is_supported():
522
# see open_downlevel to open legacy branches.
523
raise errors.UnsupportedFormatError(format=self)
524
if recommend_upgrade and self.upgrade_recommended:
525
ui.ui_factory.recommend_upgrade(
526
self.get_format_description(), basedir)
529
class ControlComponentFormatRegistry(registry.FormatRegistry):
530
"""A registry for control components (branch, workingtree, repository)."""
532
def __init__(self, other_registry=None):
533
super(ControlComponentFormatRegistry, self).__init__(other_registry)
534
self._extra_formats = []
536
def register(self, format):
537
"""Register a new format."""
538
super(ControlComponentFormatRegistry, self).register(
539
format.get_format_string(), format)
541
def remove(self, format):
542
"""Remove a registered format."""
543
super(ControlComponentFormatRegistry, self).remove(
544
format.get_format_string())
546
def register_extra(self, format):
547
"""Register a format that can not be used in a metadir.
549
This is mainly useful to allow custom repository formats, such as older
550
Bazaar formats and foreign formats, to be tested.
552
self._extra_formats.append(registry._ObjectGetter(format))
554
def remove_extra(self, format):
555
"""Remove an extra format.
557
self._extra_formats.remove(registry._ObjectGetter(format))
559
def register_extra_lazy(self, module_name, member_name):
560
"""Register a format lazily.
562
self._extra_formats.append(
563
registry._LazyObjectGetter(module_name, member_name))
565
def _get_extra(self):
566
"""Return all "extra" formats, not usable in meta directories."""
568
for getter in self._extra_formats:
576
"""Return all formats, even those not usable in metadirs.
579
for name in self.keys():
584
return result + self._get_extra()
586
def _get_all_modules(self):
587
"""Return a set of the modules providing objects."""
589
for name in self.keys():
590
modules.add(self._get_module(name))
591
for getter in self._extra_formats:
592
modules.add(getter.get_module())
596
class Converter(object):
597
"""Converts a disk format object from one format to another."""
599
def convert(self, to_convert, pb):
600
"""Perform the conversion of to_convert, giving feedback via pb.
602
:param to_convert: The disk object to convert.
603
:param pb: a progress bar to use for progress information.
606
def step(self, message):
607
"""Update the pb by a step."""
609
self.pb.update(message, self.count, self.total)
612
614
class ControlDirFormat(object):
613
615
"""An encapsulation of the initialization and open routines for a format.
681
680
def is_supported(self):
682
681
"""Is this format supported?
684
Supported formats must be openable.
683
Supported formats must be initializable and openable.
685
684
Unsupported formats may not support initialization or committing or
686
685
some other features depending on the reason for not being supported.
690
def is_initializable(self):
691
"""Whether new control directories of this format can be initialized.
693
return self.is_supported()
695
def check_support_status(self, allow_unsupported, recommend_upgrade=True,
697
"""Give an error or warning on old formats.
699
:param allow_unsupported: If true, allow opening
700
formats that are strongly deprecated, and which may
701
have limited functionality.
703
:param recommend_upgrade: If true (default), warn
704
the user through the ui object that they may wish
705
to upgrade the object.
707
if not allow_unsupported and not self.is_supported():
708
# see open_downlevel to open legacy branches.
709
raise errors.UnsupportedFormatError(format=self)
710
if recommend_upgrade and self.upgrade_recommended:
711
ui.ui_factory.recommend_upgrade(
712
self.get_format_description(), basedir)
714
689
def same_model(self, target_format):
715
690
return (self.repository_format.rich_root_data ==
716
691
target_format.rich_root_data)