860
1073
raise errors.NotBranchError(location)
861
1074
return tree, branch, branch.repository, relpath
1076
def open_repository(self, _unsupported=False):
1077
"""Open the repository object at this BzrDir if one is present.
1079
This will not follow the Branch object pointer - it's strictly a direct
1080
open facility. Most client code should use open_branch().repository to
1081
get at a repository.
1083
:param _unsupported: a private parameter, not part of the api.
1084
TODO: static convenience version of this?
1086
raise NotImplementedError(self.open_repository)
1088
def open_workingtree(self, _unsupported=False,
1089
recommend_upgrade=True, from_branch=None):
1090
"""Open the workingtree object at this BzrDir if one is present.
1092
:param recommend_upgrade: Optional keyword parameter, when True (the
1093
default), emit through the ui module a recommendation that the user
1094
upgrade the working tree when the workingtree being opened is old
1095
(but still fully supported).
1096
:param from_branch: override bzrdir branch (for lightweight checkouts)
1098
raise NotImplementedError(self.open_workingtree)
1100
def has_branch(self, name=None):
1101
"""Tell if this bzrdir contains a branch.
1103
Note: if you're going to open the branch, you should just go ahead
1104
and try, and not ask permission first. (This method just opens the
1105
branch and discards it, and that's somewhat expensive.)
1108
self.open_branch(name)
1110
except errors.NotBranchError:
1113
def has_workingtree(self):
1114
"""Tell if this bzrdir contains a working tree.
1116
This will still raise an exception if the bzrdir has a workingtree that
1117
is remote & inaccessible.
1119
Note: if you're going to open the working tree, you should just go ahead
1120
and try, and not ask permission first. (This method just opens the
1121
workingtree and discards it, and that's somewhat expensive.)
1124
self.open_workingtree(recommend_upgrade=False)
1126
except errors.NoWorkingTree:
863
1129
def _cloning_metadir(self):
864
1130
"""Produce a metadir suitable for cloning with.
923
1189
format.require_stacking()
927
def create(cls, base, format=None, possible_transports=None):
928
"""Create a new BzrDir at the url 'base'.
930
:param format: If supplied, the format of branch to create. If not
931
supplied, the default is used.
932
:param possible_transports: If supplied, a list of transports that
933
can be reused to share a remote connection.
1192
def checkout_metadir(self):
1193
return self.cloning_metadir()
1195
def sprout(self, url, revision_id=None, force_new_repo=False,
1196
recurse='down', possible_transports=None,
1197
accelerator_tree=None, hardlink=False, stacked=False,
1198
source_branch=None, create_tree_if_local=True):
1199
"""Create a copy of this bzrdir prepared for use as a new line of
1202
If url's last component does not exist, it will be created.
1204
Attributes related to the identity of the source branch like
1205
branch nickname will be cleaned, a working tree is created
1206
whether one existed before or not; and a local branch is always
1209
if revision_id is not None, then the clone operation may tune
1210
itself to download less data.
1211
:param accelerator_tree: A tree which can be used for retrieving file
1212
contents more quickly than the revision tree, i.e. a workingtree.
1213
The revision tree will be used for cases where accelerator_tree's
1214
content is different.
1215
:param hardlink: If true, hard-link files from accelerator_tree,
1217
:param stacked: If true, create a stacked branch referring to the
1218
location of this control directory.
1219
:param create_tree_if_local: If true, a working-tree will be created
1220
when working locally.
935
if cls is not BzrDir:
936
raise AssertionError("BzrDir.create always creates the"
937
"default format, not one of %r" % cls)
938
t = get_transport(base, possible_transports)
941
format = controldir.ControlDirFormat.get_default_format()
942
return format.initialize_on_transport(t)
1222
target_transport = get_transport(url, possible_transports)
1223
target_transport.ensure_base()
1224
cloning_format = self.cloning_metadir(stacked)
1225
# Create/update the result branch
1226
result = cloning_format.initialize_on_transport(target_transport)
1227
# if a stacked branch wasn't requested, we don't create one
1228
# even if the origin was stacked
1229
stacked_branch_url = None
1230
if source_branch is not None:
1232
stacked_branch_url = self.root_transport.base
1233
source_repository = source_branch.repository
1236
source_branch = self.open_branch()
1237
source_repository = source_branch.repository
1239
stacked_branch_url = self.root_transport.base
1240
except errors.NotBranchError:
1241
source_branch = None
1243
source_repository = self.open_repository()
1244
except errors.NoRepositoryPresent:
1245
source_repository = None
1246
repository_policy = result.determine_repository_policy(
1247
force_new_repo, stacked_branch_url, require_stacking=stacked)
1248
result_repo, is_new_repo = repository_policy.acquire_repository()
1249
is_stacked = stacked or (len(result_repo._fallback_repositories) != 0)
1250
if is_new_repo and revision_id is not None and not is_stacked:
1251
fetch_spec = graph.PendingAncestryResult(
1252
[revision_id], source_repository)
1255
if source_repository is not None:
1256
# Fetch while stacked to prevent unstacked fetch from
1258
if fetch_spec is None:
1259
result_repo.fetch(source_repository, revision_id=revision_id)
1261
result_repo.fetch(source_repository, fetch_spec=fetch_spec)
1263
if source_branch is None:
1264
# this is for sprouting a bzrdir without a branch; is that
1266
# Not especially, but it's part of the contract.
1267
result_branch = result.create_branch()
1269
result_branch = source_branch.sprout(result,
1270
revision_id=revision_id, repository_policy=repository_policy)
1271
mutter("created new branch %r" % (result_branch,))
1273
# Create/update the result working tree
1274
if (create_tree_if_local and
1275
isinstance(target_transport, local.LocalTransport) and
1276
(result_repo is None or result_repo.make_working_trees())):
1277
wt = result.create_workingtree(accelerator_tree=accelerator_tree,
1281
if wt.path2id('') is None:
1283
wt.set_root_id(self.open_workingtree.get_root_id())
1284
except errors.NoWorkingTree:
1290
if recurse == 'down':
1292
basis = wt.basis_tree()
1294
subtrees = basis.iter_references()
1295
elif result_branch is not None:
1296
basis = result_branch.basis_tree()
1298
subtrees = basis.iter_references()
1299
elif source_branch is not None:
1300
basis = source_branch.basis_tree()
1302
subtrees = basis.iter_references()
1307
for path, file_id in subtrees:
1308
target = urlutils.join(url, urlutils.escape(path))
1309
sublocation = source_branch.reference_parent(file_id, path)
1310
sublocation.bzrdir.sprout(target,
1311
basis.get_reference_revision(file_id, path),
1312
force_new_repo=force_new_repo, recurse=recurse,
1315
if basis is not None:
1319
def push_branch(self, source, revision_id=None, overwrite=False,
1320
remember=False, create_prefix=False):
1321
"""Push the source branch into this BzrDir."""
1323
# If we can open a branch, use its direct repository, otherwise see
1324
# if there is a repository without a branch.
1326
br_to = self.open_branch()
1327
except errors.NotBranchError:
1328
# Didn't find a branch, can we find a repository?
1329
repository_to = self.find_repository()
1331
# Found a branch, so we must have found a repository
1332
repository_to = br_to.repository
1334
push_result = PushResult()
1335
push_result.source_branch = source
1337
# We have a repository but no branch, copy the revisions, and then
1339
repository_to.fetch(source.repository, revision_id=revision_id)
1340
br_to = source.clone(self, revision_id=revision_id)
1341
if source.get_push_location() is None or remember:
1342
source.set_push_location(br_to.base)
1343
push_result.stacked_on = None
1344
push_result.branch_push_result = None
1345
push_result.old_revno = None
1346
push_result.old_revid = _mod_revision.NULL_REVISION
1347
push_result.target_branch = br_to
1348
push_result.master_branch = None
1349
push_result.workingtree_updated = False
1351
# We have successfully opened the branch, remember if necessary:
1352
if source.get_push_location() is None or remember:
1353
source.set_push_location(br_to.base)
1355
tree_to = self.open_workingtree()
1356
except errors.NotLocalUrl:
1357
push_result.branch_push_result = source.push(br_to,
1358
overwrite, stop_revision=revision_id)
1359
push_result.workingtree_updated = False
1360
except errors.NoWorkingTree:
1361
push_result.branch_push_result = source.push(br_to,
1362
overwrite, stop_revision=revision_id)
1363
push_result.workingtree_updated = None # Not applicable
1365
tree_to.lock_write()
1367
push_result.branch_push_result = source.push(
1368
tree_to.branch, overwrite, stop_revision=revision_id)
1372
push_result.workingtree_updated = True
1373
push_result.old_revno = push_result.branch_push_result.old_revno
1374
push_result.old_revid = push_result.branch_push_result.old_revid
1375
push_result.target_branch = \
1376
push_result.branch_push_result.target_branch
946
1380
class BzrDirHooks(hooks.Hooks):
1459
1893
return config.TransportConfig(self.transport, 'control.conf')
1462
class BzrProber(controldir.Prober):
1463
"""Prober for formats that use a .bzr/ control directory."""
1466
"""The known .bzr formats."""
1469
def register_bzrdir_format(klass, format):
1470
klass._formats[format.get_format_string()] = format
1473
def unregister_bzrdir_format(klass, format):
1474
del klass._formats[format.get_format_string()]
1477
def probe_transport(klass, transport):
1478
"""Return the .bzrdir style format present in a directory."""
1480
format_string = transport.get_bytes(".bzr/branch-format")
1481
except errors.NoSuchFile:
1482
raise errors.NotBranchError(path=transport.base)
1484
return klass._formats[format_string]
1486
raise errors.UnknownFormatError(format=format_string, kind='bzrdir')
1489
controldir.ControlDirFormat.register_prober(BzrProber)
1492
class RemoteBzrProber(controldir.Prober):
1493
"""Prober for remote servers that provide a Bazaar smart server."""
1496
def probe_transport(klass, transport):
1497
"""Return a RemoteBzrDirFormat object if it looks possible."""
1499
medium = transport.get_smart_medium()
1500
except (NotImplementedError, AttributeError,
1501
errors.TransportNotPossible, errors.NoSmartMedium,
1502
errors.SmartProtocolError):
1503
# no smart server, so not a branch for this format type.
1504
raise errors.NotBranchError(path=transport.base)
1506
# Decline to open it if the server doesn't support our required
1507
# version (3) so that the VFS-based transport will do it.
1508
if medium.should_probe():
1510
server_version = medium.protocol_version()
1511
except errors.SmartProtocolError:
1512
# Apparently there's no usable smart server there, even though
1513
# the medium supports the smart protocol.
1514
raise errors.NotBranchError(path=transport.base)
1515
if server_version != '2':
1516
raise errors.NotBranchError(path=transport.base)
1517
return RemoteBzrDirFormat()
1520
class BzrDirFormat(controldir.ControlDirFormat):
1521
"""ControlDirFormat base class for .bzr/ directories.
1896
class BzrDirFormat(object):
1897
"""An encapsulation of the initialization and open routines for a format.
1899
Formats provide three things:
1900
* An initialization routine,
1523
1904
Formats are placed in a dict by their format string for reference
1524
1905
during bzrdir opening. These should be subclasses of BzrDirFormat
1527
1908
Once a format is deprecated, just deprecate the initialize and open
1528
1909
methods on the format class. Do not deprecate the object, as the
1529
1910
object will be created every system load.
1912
:cvar colocated_branches: Whether this formats supports colocated branches.
1915
_default_format = None
1916
"""The default format used for new .bzr dirs."""
1919
"""The known formats."""
1921
_control_formats = []
1922
"""The registered control formats - .bzr, ....
1924
This is a list of BzrDirFormat objects.
1927
_control_server_formats = []
1928
"""The registered control server formats, e.g. RemoteBzrDirs.
1930
This is a list of BzrDirFormat objects.
1532
1933
_lock_file_name = 'branch-lock'
1935
colocated_branches = False
1936
"""Whether co-located branches are supported for this control dir format.
1534
1939
# _lock_class must be set in subclasses to the lock type, typ.
1535
1940
# TransportLock or LockDir
1943
def find_format(klass, transport, _server_formats=True):
1944
"""Return the format present at transport."""
1946
formats = klass._control_server_formats + klass._control_formats
1948
formats = klass._control_formats
1949
for format in formats:
1951
return format.probe_transport(transport)
1952
except errors.NotBranchError:
1953
# this format does not find a control dir here.
1955
raise errors.NotBranchError(path=transport.base)
1958
def probe_transport(klass, transport):
1959
"""Return the .bzrdir style format present in a directory."""
1961
format_string = transport.get_bytes(".bzr/branch-format")
1962
except errors.NoSuchFile:
1963
raise errors.NotBranchError(path=transport.base)
1965
return klass._formats[format_string]
1967
raise errors.UnknownFormatError(format=format_string, kind='bzrdir')
1970
def get_default_format(klass):
1971
"""Return the current default format."""
1972
return klass._default_format
1537
1974
def get_format_string(self):
1538
1975
"""Return the ASCII format string that identifies this format."""
1539
1976
raise NotImplementedError(self.get_format_string)
1978
def get_format_description(self):
1979
"""Return the short description for this format."""
1980
raise NotImplementedError(self.get_format_description)
1982
def get_converter(self, format=None):
1983
"""Return the converter to use to convert bzrdirs needing converts.
1985
This returns a bzrlib.bzrdir.Converter object.
1987
This should return the best upgrader to step this format towards the
1988
current default format. In the case of plugins we can/should provide
1989
some means for them to extend the range of returnable converters.
1991
:param format: Optional format to override the default format of the
1994
raise NotImplementedError(self.get_converter)
1996
def initialize(self, url, possible_transports=None):
1997
"""Create a bzr control dir at this url and return an opened copy.
1999
While not deprecated, this method is very specific and its use will
2000
lead to many round trips to setup a working environment. See
2001
initialize_on_transport_ex for a [nearly] all-in-one method.
2003
Subclasses should typically override initialize_on_transport
2004
instead of this method.
2006
return self.initialize_on_transport(get_transport(url,
2007
possible_transports))
1541
2009
def initialize_on_transport(self, transport):
1542
2010
"""Initialize a new bzrdir in the base directory of a Transport."""
1691
2159
control_files.unlock()
1692
2160
return self.open(transport, _found=True)
2162
def is_supported(self):
2163
"""Is this format supported?
2165
Supported formats must be initializable and openable.
2166
Unsupported formats may not support initialization or committing or
2167
some other features depending on the reason for not being supported.
2171
def network_name(self):
2172
"""A simple byte string uniquely identifying this format for RPC calls.
2174
Bzr control formats use thir disk format string to identify the format
2175
over the wire. Its possible that other control formats have more
2176
complex detection requirements, so we permit them to use any unique and
2177
immutable string they desire.
2179
raise NotImplementedError(self.network_name)
2181
def same_model(self, target_format):
2182
return (self.repository_format.rich_root_data ==
2183
target_format.rich_root_data)
2186
def known_formats(klass):
2187
"""Return all the known formats.
2189
Concrete formats should override _known_formats.
2191
# There is double indirection here to make sure that control
2192
# formats used by more than one dir format will only be probed
2193
# once. This can otherwise be quite expensive for remote connections.
2195
for format in klass._control_formats:
2196
result.update(format._known_formats())
2200
def _known_formats(klass):
2201
"""Return the known format instances for this control format."""
2202
return set(klass._formats.values())
1694
2204
def open(self, transport, _found=False):
1695
2205
"""Return an instance of this format for the dir transport points at.
1697
2207
_found is a private parameter, do not use it.
1700
found_format = controldir.ControlDirFormat.find_format(transport)
2210
found_format = BzrDirFormat.find_format(transport)
1701
2211
if not isinstance(found_format, self.__class__):
1702
2212
raise AssertionError("%s was asked to open %s, but it seems to need "
2934
3503
BzrDirMetaFormat1._set_repository_format) #.im_func)
2937
controldir.ControlDirFormat.register_server_prober(RemoteBzrProber)
3506
BzrDirFormat.register_control_server_format(RemoteBzrDirFormat)
3509
class BzrDirFormatInfo(object):
3511
def __init__(self, native, deprecated, hidden, experimental):
3512
self.deprecated = deprecated
3513
self.native = native
3514
self.hidden = hidden
3515
self.experimental = experimental
3518
class BzrDirFormatRegistry(registry.Registry):
3519
"""Registry of user-selectable BzrDir subformats.
3521
Differs from BzrDirFormat._control_formats in that it provides sub-formats,
3522
e.g. BzrDirMeta1 with weave repository. Also, it's more user-oriented.
3526
"""Create a BzrDirFormatRegistry."""
3527
self._aliases = set()
3528
self._registration_order = list()
3529
super(BzrDirFormatRegistry, self).__init__()
3532
"""Return a set of the format names which are aliases."""
3533
return frozenset(self._aliases)
3535
def register_metadir(self, key,
3536
repository_format, help, native=True, deprecated=False,
3542
"""Register a metadir subformat.
3544
These all use a BzrDirMetaFormat1 bzrdir, but can be parameterized
3545
by the Repository/Branch/WorkingTreeformats.
3547
:param repository_format: The fully-qualified repository format class
3549
:param branch_format: Fully-qualified branch format class name as
3551
:param tree_format: Fully-qualified tree format class name as
3554
# This should be expanded to support setting WorkingTree and Branch
3555
# formats, once BzrDirMetaFormat1 supports that.
3556
def _load(full_name):
3557
mod_name, factory_name = full_name.rsplit('.', 1)
3559
mod = __import__(mod_name, globals(), locals(),
3561
except ImportError, e:
3562
raise ImportError('failed to load %s: %s' % (full_name, e))
3564
factory = getattr(mod, factory_name)
3565
except AttributeError:
3566
raise AttributeError('no factory %s in module %r'
3571
bd = BzrDirMetaFormat1()
3572
if branch_format is not None:
3573
bd.set_branch_format(_load(branch_format))
3574
if tree_format is not None:
3575
bd.workingtree_format = _load(tree_format)
3576
if repository_format is not None:
3577
bd.repository_format = _load(repository_format)
3579
self.register(key, helper, help, native, deprecated, hidden,
3580
experimental, alias)
3582
def register(self, key, factory, help, native=True, deprecated=False,
3583
hidden=False, experimental=False, alias=False):
3584
"""Register a BzrDirFormat factory.
3586
The factory must be a callable that takes one parameter: the key.
3587
It must produce an instance of the BzrDirFormat when called.
3589
This function mainly exists to prevent the info object from being
3592
registry.Registry.register(self, key, factory, help,
3593
BzrDirFormatInfo(native, deprecated, hidden, experimental))
3595
self._aliases.add(key)
3596
self._registration_order.append(key)
3598
def register_lazy(self, key, module_name, member_name, help, native=True,
3599
deprecated=False, hidden=False, experimental=False, alias=False):
3600
registry.Registry.register_lazy(self, key, module_name, member_name,
3601
help, BzrDirFormatInfo(native, deprecated, hidden, experimental))
3603
self._aliases.add(key)
3604
self._registration_order.append(key)
3606
def set_default(self, key):
3607
"""Set the 'default' key to be a clone of the supplied key.
3609
This method must be called once and only once.
3611
registry.Registry.register(self, 'default', self.get(key),
3612
self.get_help(key), info=self.get_info(key))
3613
self._aliases.add('default')
3615
def set_default_repository(self, key):
3616
"""Set the FormatRegistry default and Repository default.
3618
This is a transitional method while Repository.set_default_format
3621
if 'default' in self:
3622
self.remove('default')
3623
self.set_default(key)
3624
format = self.get('default')()
3626
def make_bzrdir(self, key):
3627
return self.get(key)()
3629
def help_topic(self, topic):
3631
default_realkey = None
3632
default_help = self.get_help('default')
3634
for key in self._registration_order:
3635
if key == 'default':
3637
help = self.get_help(key)
3638
if help == default_help:
3639
default_realkey = key
3641
help_pairs.append((key, help))
3643
def wrapped(key, help, info):
3645
help = '(native) ' + help
3646
return ':%s:\n%s\n\n' % (key,
3647
textwrap.fill(help, initial_indent=' ',
3648
subsequent_indent=' ',
3649
break_long_words=False))
3650
if default_realkey is not None:
3651
output += wrapped(default_realkey, '(default) %s' % default_help,
3652
self.get_info('default'))
3653
deprecated_pairs = []
3654
experimental_pairs = []
3655
for key, help in help_pairs:
3656
info = self.get_info(key)
3659
elif info.deprecated:
3660
deprecated_pairs.append((key, help))
3661
elif info.experimental:
3662
experimental_pairs.append((key, help))
3664
output += wrapped(key, help, info)
3665
output += "\nSee :doc:`formats-help` for more about storage formats."
3667
if len(experimental_pairs) > 0:
3668
other_output += "Experimental formats are shown below.\n\n"
3669
for key, help in experimental_pairs:
3670
info = self.get_info(key)
3671
other_output += wrapped(key, help, info)
3674
"No experimental formats are available.\n\n"
3675
if len(deprecated_pairs) > 0:
3676
other_output += "\nDeprecated formats are shown below.\n\n"
3677
for key, help in deprecated_pairs:
3678
info = self.get_info(key)
3679
other_output += wrapped(key, help, info)
3682
"\nNo deprecated formats are available.\n\n"
3684
"\nSee :doc:`formats-help` for more about storage formats."
3686
if topic == 'other-formats':
2940
3692
class RepositoryAcquisitionPolicy(object):
3094
3846
return self._repository, False
3097
def register_metadir(registry, key,
3098
repository_format, help, native=True, deprecated=False,
3104
"""Register a metadir subformat.
3106
These all use a BzrDirMetaFormat1 bzrdir, but can be parameterized
3107
by the Repository/Branch/WorkingTreeformats.
3109
:param repository_format: The fully-qualified repository format class
3111
:param branch_format: Fully-qualified branch format class name as
3113
:param tree_format: Fully-qualified tree format class name as
3116
# This should be expanded to support setting WorkingTree and Branch
3117
# formats, once BzrDirMetaFormat1 supports that.
3118
def _load(full_name):
3119
mod_name, factory_name = full_name.rsplit('.', 1)
3121
mod = __import__(mod_name, globals(), locals(),
3123
except ImportError, e:
3124
raise ImportError('failed to load %s: %s' % (full_name, e))
3126
factory = getattr(mod, factory_name)
3127
except AttributeError:
3128
raise AttributeError('no factory %s in module %r'
3133
bd = BzrDirMetaFormat1()
3134
if branch_format is not None:
3135
bd.set_branch_format(_load(branch_format))
3136
if tree_format is not None:
3137
bd.workingtree_format = _load(tree_format)
3138
if repository_format is not None:
3139
bd.repository_format = _load(repository_format)
3141
registry.register(key, helper, help, native, deprecated, hidden,
3142
experimental, alias)
3849
# Please register new formats after old formats so that formats
3850
# appear in chronological order and format descriptions can build
3852
format_registry = BzrDirFormatRegistry()
3144
3853
# The pre-0.8 formats have their repository format network name registered in
3145
3854
# repository.py. MetaDir formats have their repository format network name
3146
3855
# inferred from their disk format string.
3147
controldir.format_registry.register('weave', BzrDirFormat6,
3856
format_registry.register('weave', BzrDirFormat6,
3148
3857
'Pre-0.8 format. Slower than knit and does not'
3149
3858
' support checkouts or shared repositories.',
3151
3860
deprecated=True)
3152
register_metadir(controldir.format_registry, 'metaweave',
3861
format_registry.register_metadir('metaweave',
3153
3862
'bzrlib.repofmt.weaverepo.RepositoryFormat7',
3154
3863
'Transitional format in 0.8. Slower than knit.',
3155
3864
branch_format='bzrlib.branch.BzrBranchFormat5',
3156
3865
tree_format='bzrlib.workingtree.WorkingTreeFormat3',
3158
3867
deprecated=True)
3159
register_metadir(controldir.format_registry, 'knit',
3868
format_registry.register_metadir('knit',
3160
3869
'bzrlib.repofmt.knitrepo.RepositoryFormatKnit1',
3161
3870
'Format using knits. Recommended for interoperation with bzr <= 0.14.',
3162
3871
branch_format='bzrlib.branch.BzrBranchFormat5',
3163
3872
tree_format='bzrlib.workingtree.WorkingTreeFormat3',
3165
3874
deprecated=True)
3166
register_metadir(controldir.format_registry, 'dirstate',
3875
format_registry.register_metadir('dirstate',
3167
3876
'bzrlib.repofmt.knitrepo.RepositoryFormatKnit1',
3168
3877
help='New in 0.15: Fast local operations. Compatible with bzr 0.8 and '
3169
3878
'above when accessed over the network.',