57
59
errors.BzrError.__init__(self, format=format, url=url)
60
class BranchReferenceLoop(errors.BzrError):
62
_fmt = "Can not create branch reference that points at branch itself."
64
def __init__(self, branch):
65
errors.BzrError.__init__(self, branch=branch)
68
62
class ControlComponent(object):
69
63
"""Abstract base class for control directory components.
128
122
return list(self.get_branches().values())
130
def branch_names(self):
131
"""List all branch names in this control directory.
133
:return: List of branch names
136
self.get_branch_reference()
137
except (errors.NotBranchError, errors.NoRepositoryPresent):
142
124
def get_branches(self):
143
125
"""Get all branches in this control directory, as a dictionary.
145
127
:return: Dictionary mapping branch names to instances.
148
return {"": self.open_branch()}
130
return { "": self.open_branch() }
149
131
except (errors.NotBranchError, errors.NoRepositoryPresent):
152
134
def is_control_filename(self, filename):
153
135
"""True if filename is the name of a path which is reserved for
162
144
this in the future - for instance to make bzr talk with svn working
165
return self._format.is_control_filename(filename)
147
raise NotImplementedError(self.is_control_filename)
167
149
def needs_format_conversion(self, format=None):
168
150
"""Return true if this controldir needs convert_format run on it.
204
186
def destroy_branch(self, name=None):
205
187
"""Destroy a branch in this ControlDir.
207
:param name: Name of the branch to destroy, None for the
189
:param name: Name of the branch to destroy, None for the
208
190
user selected branch or "" for the active branch.
209
191
:raise NotBranchError: When the branch does not exist
211
193
raise NotImplementedError(self.destroy_branch)
213
195
def create_workingtree(self, revision_id=None, from_branch=None,
214
accelerator_tree=None, hardlink=False):
196
accelerator_tree=None, hardlink=False):
215
197
"""Create a working tree at this ControlDir.
217
199
:param revision_id: create it as of this revision id.
218
:param from_branch: override controldir branch
200
:param from_branch: override controldir branch
219
201
(for lightweight checkouts)
220
202
:param accelerator_tree: A tree which can be used for retrieving file
221
203
contents more quickly than the revision tree, i.e. a workingtree.
382
364
def sprout(self, url, revision_id=None, force_new_repo=False,
383
365
recurse='down', possible_transports=None,
384
366
accelerator_tree=None, hardlink=False, stacked=False,
385
source_branch=None, create_tree_if_local=True,
367
source_branch=None, create_tree_if_local=True):
387
368
"""Create a copy of this controldir prepared for use as a new line of
410
391
raise NotImplementedError(self.sprout)
412
def push_branch(self, source, revision_id=None, overwrite=False,
413
remember=False, create_prefix=False, lossy=False,
393
def push_branch(self, source, revision_id=None, overwrite=False,
394
remember=False, create_prefix=False):
415
395
"""Push the source branch into this ControlDir."""
417
397
# If we can open a branch, use its direct repository, otherwise see
436
416
revision_id = source.last_revision()
437
417
repository_to.fetch(source.repository, revision_id=revision_id)
438
br_to = source.sprout(
439
self, revision_id=revision_id, lossy=lossy,
440
tag_selector=tag_selector)
418
br_to = source.clone(self, revision_id=revision_id)
441
419
if source.get_push_location() is None or remember:
442
420
# FIXME: Should be done only if we succeed ? -- vila 2012-01-18
443
421
source.set_push_location(br_to.base)
457
435
tree_to = self.open_workingtree()
458
436
except errors.NotLocalUrl:
459
push_result.branch_push_result = source.push(
460
br_to, overwrite, stop_revision=revision_id, lossy=lossy,
461
tag_selector=tag_selector)
437
push_result.branch_push_result = source.push(br_to,
438
overwrite, stop_revision=revision_id)
462
439
push_result.workingtree_updated = False
463
440
except errors.NoWorkingTree:
464
push_result.branch_push_result = source.push(
465
br_to, overwrite, stop_revision=revision_id, lossy=lossy,
466
tag_selector=tag_selector)
467
push_result.workingtree_updated = None # Not applicable
441
push_result.branch_push_result = source.push(br_to,
442
overwrite, stop_revision=revision_id)
443
push_result.workingtree_updated = None # Not applicable
469
with tree_to.lock_write():
470
447
push_result.branch_push_result = source.push(
471
tree_to.branch, overwrite, stop_revision=revision_id,
472
lossy=lossy, tag_selector=tag_selector)
448
tree_to.branch, overwrite, stop_revision=revision_id)
474
452
push_result.workingtree_updated = True
475
453
push_result.old_revno = push_result.branch_push_result.old_revno
476
454
push_result.old_revid = push_result.branch_push_result.old_revid
508
486
raise NotImplementedError(self.check_conversion_target)
510
488
def clone(self, url, revision_id=None, force_new_repo=False,
511
preserve_stacking=False, tag_selector=None):
489
preserve_stacking=False):
512
490
"""Clone this controldir and its contents to url verbatim.
514
492
:param url: The url create the clone at. If url's last component does
524
502
return self.clone_on_transport(_mod_transport.get_transport(url),
525
503
revision_id=revision_id,
526
504
force_new_repo=force_new_repo,
527
preserve_stacking=preserve_stacking,
528
tag_selector=tag_selector)
505
preserve_stacking=preserve_stacking)
530
507
def clone_on_transport(self, transport, revision_id=None,
531
force_new_repo=False, preserve_stacking=False, stacked_on=None,
532
create_prefix=False, use_existing_dir=True, no_tree=False,
508
force_new_repo=False, preserve_stacking=False, stacked_on=None,
509
create_prefix=False, use_existing_dir=True, no_tree=False):
534
510
"""Clone this controldir and its contents to transport verbatim.
536
512
:param transport: The transport for the location to produce the clone
580
556
controldir = klass.open_from_transport(current_transport)
581
except (errors.NotBranchError, errors.PermissionDenied,
582
errors.UnknownFormatError):
557
except (errors.NotBranchError, errors.PermissionDenied):
585
560
recurse, value = evaluate(controldir)
704
679
if not isinstance(t, local.LocalTransport):
705
680
raise errors.NotLocalUrl(base)
706
681
controldir = klass.create_branch_and_repo(base,
708
format=format).controldir
683
format=format).controldir
709
684
return controldir.create_workingtree()
723
698
t = _mod_transport.get_transport(base, possible_transports)
724
699
return klass.open_from_transport(t, probers=probers,
725
_unsupported=_unsupported)
700
_unsupported=_unsupported)
728
703
def open_from_transport(klass, transport, _unsupported=False,
737
712
# Keep initial base since 'transport' may be modified while following
738
713
# the redirections.
739
714
base = transport.base
741
715
def find_format(transport):
742
716
return transport, ControlDirFormat.find_format(transport,
745
719
def redirected(transport, e, redirection_notice):
746
720
redirected_transport = transport._redirected_to(e.source, e.target)
747
721
if redirected_transport is None:
748
722
raise errors.NotBranchError(base)
749
723
trace.note(gettext('{0} is{1} redirected to {2}').format(
750
transport.base, e.permanently, redirected_transport.base))
724
transport.base, e.permanently, redirected_transport.base))
751
725
return redirected_transport
792
766
result = klass.open_from_transport(a_transport)
793
767
return result, urlutils.unescape(a_transport.relpath(url))
794
except errors.NotBranchError:
768
except errors.NotBranchError as e:
796
770
except errors.PermissionDenied:
806
780
a_transport = new_t
809
def open_tree_or_branch(klass, location, name=None):
783
def open_tree_or_branch(klass, location):
810
784
"""Return the branch and working tree at a location.
812
786
If there is no tree at the location, tree will be None.
815
789
:return: (tree, branch)
817
791
controldir = klass.open(location)
818
return controldir._get_tree_branch(name=name)
792
return controldir._get_tree_branch()
821
795
def open_containing_tree_or_branch(klass, location,
822
possible_transports=None):
796
possible_transports=None):
823
797
"""Return the branch and working tree contained by a location.
825
799
Returns (tree, branch, relpath).
829
803
relpath is the portion of the path that is contained by the branch.
831
805
controldir, relpath = klass.open_containing(location,
832
possible_transports=possible_transports)
806
possible_transports=possible_transports)
833
807
tree, branch = controldir._get_tree_branch()
834
808
return tree, branch, relpath
870
844
if klass is not ControlDir:
871
845
raise AssertionError("ControlDir.create always creates the"
872
"default format, not one of %r" % klass)
846
"default format, not one of %r" % klass)
873
847
t = _mod_transport.get_transport(base, possible_transports)
875
849
if format is None:
884
858
"""Create the default hooks."""
885
859
hooks.Hooks.__init__(self, "breezy.controldir", "ControlDir.hooks")
886
860
self.add_hook('pre_open',
887
"Invoked before attempting to open a ControlDir with the transport "
888
"that the open will use.", (1, 14))
861
"Invoked before attempting to open a ControlDir with the transport "
862
"that the open will use.", (1, 14))
889
863
self.add_hook('post_repo_init',
890
"Invoked after a repository has been initialized. "
891
"post_repo_init is called with a "
892
"breezy.controldir.RepoInitHookParams.",
864
"Invoked after a repository has been initialized. "
865
"post_repo_init is called with a "
866
"breezy.controldir.RepoInitHookParams.",
896
869
# install the default hooks
897
870
ControlDir.hooks = ControlDirHooks()
918
891
def check_support_status(self, allow_unsupported, recommend_upgrade=True,
920
893
"""Give an error or warning on old formats.
922
895
:param allow_unsupported: If true, allow opening
976
949
registry._LazyObjectGetter(module_name, member_name))
978
951
def _get_extra(self):
979
"""Return getters for extra formats, not usable in meta directories."""
980
return [getter.get_obj for getter in self._extra_formats]
982
def _get_all_lazy(self):
983
"""Return getters for all formats, even those not usable in metadirs."""
984
result = [self._dict[name].get_obj for name in self.keys()]
985
result.extend(self._get_extra())
952
"""Return all "extra" formats, not usable in meta directories."""
954
for getter in self._extra_formats:
988
961
def _get_all(self):
989
"""Return all formats, even those not usable in metadirs."""
962
"""Return all formats, even those not usable in metadirs.
991
for getter in self._get_all_lazy():
965
for name in self.keys():
993
967
if callable(fmt):
995
969
result.append(fmt)
970
return result + self._get_extra()
998
972
def _get_all_modules(self):
999
973
"""Return a set of the modules providing objects."""
1045
1019
_default_format = None
1046
1020
"""The default format used for new control directories."""
1022
_server_probers = []
1023
"""The registered server format probers, e.g. RemoteBzrProber.
1025
This is a list of Prober-derived classes.
1049
1029
"""The registered format probers, e.g. BzrProber.
1099
1079
return self.is_supported()
1101
1081
def check_support_status(self, allow_unsupported, recommend_upgrade=True,
1103
1083
"""Give an error or warning on old formats.
1105
1085
:param allow_unsupported: If true, allow opening
1120
1100
def same_model(self, target_format):
1121
1101
return (self.repository_format.rich_root_data ==
1122
target_format.rich_root_data)
1102
target_format.rich_root_data)
1125
1105
def register_prober(klass, prober):
1136
1116
klass._probers.remove(prober)
1119
def register_server_prober(klass, prober):
1120
"""Register a control format prober for client-server environments.
1122
These probers will be used before ones registered with
1123
register_prober. This gives implementations that decide to the
1124
chance to grab it before anything looks at the contents of the format
1127
klass._server_probers.append(prober)
1138
1129
def __str__(self):
1139
1130
# Trim the newline
1140
1131
return self.get_format_description().rstrip()
1143
1134
def all_probers(klass):
1144
return klass._probers
1135
return klass._server_probers + klass._probers
1147
1138
def known_formats(klass):
1148
1139
"""Return all the known formats.
1151
1142
for prober_kls in klass.all_probers():
1152
result.extend(prober_kls.known_formats())
1143
result.update(prober_kls.known_formats())
1156
1147
def find_format(klass, transport, probers=None):
1157
1148
"""Return the format present at transport."""
1158
1149
if probers is None:
1160
klass.all_probers(),
1161
key=lambda prober: prober.priority(transport))
1150
probers = klass.all_probers()
1162
1151
for prober_kls in probers:
1163
1152
prober = prober_kls()
1186
1175
raise NotImplementedError(self.initialize_on_transport)
1188
1177
def initialize_on_transport_ex(self, transport, use_existing_dir=False,
1189
create_prefix=False, force_new_repo=False, stacked_on=None,
1190
stack_on_pwd=None, repo_format_name=None, make_working_trees=None,
1191
shared_repo=False, vfs_only=False):
1178
create_prefix=False, force_new_repo=False, stacked_on=None,
1179
stack_on_pwd=None, repo_format_name=None, make_working_trees=None,
1180
shared_repo=False, vfs_only=False):
1192
1181
"""Create this format on transport.
1194
1183
The directory to initialize will be created.
1250
1239
raise NotImplementedError(self.supports_transport)
1253
def is_control_filename(klass, filename):
1254
"""True if filename is the name of a path which is reserved for
1257
:param filename: A filename within the root transport of this
1260
This is true IF and ONLY IF the filename is part of the namespace reserved
1261
for bzr control dirs. Currently this is the '.bzr' directory in the root
1262
of the root_transport. it is expected that plugins will need to extend
1263
this in the future - for instance to make bzr talk with svn working
1266
raise NotImplementedError(self.is_control_filename)
1269
1242
class Prober(object):
1270
1243
"""Abstract class that can be used to detect a particular kind of
1278
1251
probers that detect .bzr/ directories and Bazaar smart servers,
1281
Probers should be registered using the register_prober methods on
1254
Probers should be registered using the register_server_prober or
1255
register_prober methods on ControlDirFormat.
1285
1258
def probe_transport(self, transport):
1304
1277
raise NotImplementedError(klass.known_formats)
1307
def priority(klass, transport):
1308
"""Priority of this prober.
1310
A lower value means the prober gets checked first.
1314
-10: This is a "server" prober
1316
10: This is a regular file-based prober
1317
100: This is a prober for an unsupported format
1322
1280
class ControlDirFormatInfo(object):
1338
1296
def __init__(self):
1339
1297
"""Create a ControlDirFormatRegistry."""
1298
self._aliases = set()
1340
1299
self._registration_order = list()
1341
1300
super(ControlDirFormatRegistry, self).__init__()
1303
"""Return a set of the format names which are aliases."""
1304
return frozenset(self._aliases)
1343
1306
def register(self, key, factory, help, native=True, deprecated=False,
1344
hidden=False, experimental=False):
1307
hidden=False, experimental=False, alias=False):
1345
1308
"""Register a ControlDirFormat factory.
1347
1310
The factory must be a callable that takes one parameter: the key.
1351
1314
supplied directly.
1353
1316
registry.Registry.register(self, key, factory, help,
1354
ControlDirFormatInfo(native, deprecated, hidden, experimental))
1317
ControlDirFormatInfo(native, deprecated, hidden, experimental))
1319
self._aliases.add(key)
1355
1320
self._registration_order.append(key)
1357
def register_alias(self, key, target, hidden=False):
1358
"""Register a format alias.
1360
:param key: Alias name
1361
:param target: Target format
1362
:param hidden: Whether the alias is hidden
1364
info = self.get_info(target)
1365
registry.Registry.register_alias(self, key, target,
1366
ControlDirFormatInfo(
1367
native=info.native, deprecated=info.deprecated,
1368
hidden=hidden, experimental=info.experimental))
1370
1322
def register_lazy(self, key, module_name, member_name, help, native=True,
1371
deprecated=False, hidden=False, experimental=False):
1323
deprecated=False, hidden=False, experimental=False, alias=False):
1372
1324
registry.Registry.register_lazy(self, key, module_name, member_name,
1373
help, ControlDirFormatInfo(native, deprecated, hidden, experimental))
1325
help, ControlDirFormatInfo(native, deprecated, hidden, experimental))
1327
self._aliases.add(key)
1374
1328
self._registration_order.append(key)
1376
1330
def set_default(self, key):
1379
1333
This method must be called once and only once.
1381
self.register_alias('default', key)
1335
registry.Registry.register(self, 'default', self.get(key),
1336
self.get_help(key), info=self.get_info(key))
1337
self._aliases.add('default')
1383
1339
def set_default_repository(self, key):
1384
1340
"""Set the FormatRegistry default and Repository default.
1412
1368
if info.native:
1413
1369
help = '(native) ' + help
1414
1370
return ':%s:\n%s\n\n' % (key,
1415
textwrap.fill(help, initial_indent=' ',
1416
subsequent_indent=' ',
1417
break_long_words=False))
1371
textwrap.fill(help, initial_indent=' ',
1372
subsequent_indent=' ',
1373
break_long_words=False))
1418
1374
if default_realkey is not None:
1419
1375
output += wrapped(default_realkey, '(default) %s' % default_help,
1420
1376
self.get_info('default'))
1487
1443
def __repr__(self):
1488
1444
if self.repository:
1489
1445
return "<%s for %s>" % (self.__class__.__name__,
1492
1448
return "<%s for %s>" % (self.__class__.__name__,
1496
1452
def is_control_filename(filename):
1497
1453
"""Check if filename is used for control directories."""
1498
# TODO(jelmer): Instead, have a function that returns all control
1500
for key, format in format_registry.items():
1501
if format().is_control_filename(filename):
1454
# TODO(jelmer): Allow registration by other VCSes
1455
return filename == '.bzr'
1507
1458
class RepositoryAcquisitionPolicy(object):
1511
1462
for a branch that is being created. The most basic policy decision is
1512
1463
whether to create a new repository or use an existing one.
1515
1465
def __init__(self, stack_on, stack_on_pwd, require_stacking):
1516
1466
"""Constructor.
1569
1519
stacked_dir = ControlDir.open(
1570
stack_on, possible_transports=possible_transports)
1520
stack_on, possible_transports=possible_transports)
1571
1521
except errors.JailBreak:
1572
1522
# We keep the stacking details, but we are in the server code so
1573
1523
# actually stacking is not needed.
1585
1535
self._require_stacking = True
1587
1537
def acquire_repository(self, make_working_trees=None, shared=False,
1588
possible_transports=None):
1538
possible_transports=None):
1589
1539
"""Acquire a repository for this controlrdir.
1591
1541
Implementations may create a new repository or use a pre-exising
1597
1547
:return: A repository, is_new_flag (True if the repository was
1600
raise NotImplementedError(
1601
RepositoryAcquisitionPolicy.acquire_repository)
1550
raise NotImplementedError(RepositoryAcquisitionPolicy.acquire_repository)
1604
1553
# Please register new formats after old formats so that formats