107
124
source_repo_format.check_conversion_target(target_repo_format)
110
def _check_supported(format, allow_unsupported):
111
"""Check whether format is a supported format.
113
If allow_unsupported is True, this is a no-op.
127
def _check_supported(format, allow_unsupported,
128
recommend_upgrade=True,
130
"""Give an error or warning on old formats.
132
:param format: may be any kind of format - workingtree, branch,
135
:param allow_unsupported: If true, allow opening
136
formats that are strongly deprecated, and which may
137
have limited functionality.
139
:param recommend_upgrade: If true (default), warn
140
the user through the ui object that they may wish
141
to upgrade the object.
143
# TODO: perhaps move this into a base Format class; it's not BzrDir
144
# specific. mbp 20070323
115
145
if not allow_unsupported and not format.is_supported():
116
146
# see open_downlevel to open legacy branches.
117
147
raise errors.UnsupportedFormatError(format=format)
148
if recommend_upgrade \
149
and getattr(format, 'upgrade_recommended', False):
150
ui.ui_factory.recommend_upgrade(
151
format.get_format_description(),
119
def clone(self, url, revision_id=None, basis=None, force_new_repo=False):
154
def clone(self, url, revision_id=None, force_new_repo=False,
155
preserve_stacking=False):
120
156
"""Clone this bzrdir and its contents to url verbatim.
122
If urls last component does not exist, it will be created.
124
if revision_id is not None, then the clone operation may tune
125
itself to download less data.
126
:param force_new_repo: Do not use a shared repository for the target
127
even if one is available.
130
basis_repo, basis_branch, basis_tree = self._get_basis_components(basis)
131
result = self._format.initialize(url)
158
:param url: The url create the clone at. If url's last component does
159
not exist, it will be created.
160
:param revision_id: The tip revision-id to use for any branch or
161
working tree. If not None, then the clone operation may tune
162
itself to download less data.
163
:param force_new_repo: Do not use a shared repository for the target
164
even if one is available.
165
:param preserve_stacking: When cloning a stacked branch, stack the
166
new branch on top of the other branch's stacked-on branch.
168
return self.clone_on_transport(get_transport(url),
169
revision_id=revision_id,
170
force_new_repo=force_new_repo,
171
preserve_stacking=preserve_stacking)
173
def clone_on_transport(self, transport, revision_id=None,
174
force_new_repo=False, preserve_stacking=False,
176
"""Clone this bzrdir and its contents to transport verbatim.
178
:param transport: The transport for the location to produce the clone
179
at. If the target directory does not exist, it will be created.
180
:param revision_id: The tip revision-id to use for any branch or
181
working tree. If not None, then the clone operation may tune
182
itself to download less data.
183
:param force_new_repo: Do not use a shared repository for the target,
184
even if one is available.
185
:param preserve_stacking: When cloning a stacked branch, stack the
186
new branch on top of the other branch's stacked-on branch.
188
transport.ensure_base()
189
require_stacking = (stacked_on is not None)
190
metadir = self.cloning_metadir(require_stacking)
191
result = metadir.initialize_on_transport(transport)
192
repository_policy = None
133
194
local_repo = self.find_repository()
134
195
except errors.NoRepositoryPresent:
135
196
local_repo = None
198
local_branch = self.open_branch()
199
except errors.NotBranchError:
202
# enable fallbacks when branch is not a branch reference
203
if local_branch.repository.has_same_location(local_repo):
204
local_repo = local_branch.repository
205
if preserve_stacking:
207
stacked_on = local_branch.get_stacked_on_url()
208
except (errors.UnstackableBranchFormat,
209
errors.UnstackableRepositoryFormat,
137
214
# may need to copy content in
139
result_repo = local_repo.clone(
141
revision_id=revision_id,
143
result_repo.set_make_working_trees(local_repo.make_working_trees())
146
result_repo = result.find_repository()
147
# fetch content this dir needs.
149
# XXX FIXME RBC 20060214 need tests for this when the basis
151
result_repo.fetch(basis_repo, revision_id=revision_id)
152
result_repo.fetch(local_repo, revision_id=revision_id)
153
except errors.NoRepositoryPresent:
154
# needed to make one anyway.
155
result_repo = local_repo.clone(
157
revision_id=revision_id,
159
result_repo.set_make_working_trees(local_repo.make_working_trees())
215
repository_policy = result.determine_repository_policy(
216
force_new_repo, stacked_on, self.root_transport.base,
217
require_stacking=require_stacking)
218
make_working_trees = local_repo.make_working_trees()
219
result_repo = repository_policy.acquire_repository(
220
make_working_trees, local_repo.is_shared())
221
if not require_stacking and repository_policy._require_stacking:
222
require_stacking = True
223
result._format.require_stacking()
224
result_repo.fetch(local_repo, revision_id=revision_id)
160
227
# 1 if there is a branch present
161
228
# make sure its content is available in the target repository
164
self.open_branch().clone(result, revision_id=revision_id)
165
except errors.NotBranchError:
168
self.open_workingtree().clone(result, basis=basis_tree)
169
except (errors.NoWorkingTree, errors.NotLocalUrl):
230
if local_branch is not None:
231
result_branch = local_branch.clone(result, revision_id=revision_id)
232
if repository_policy is not None:
233
repository_policy.configure_branch(result_branch)
234
if result_repo is None or result_repo.make_working_trees():
236
self.open_workingtree().clone(result)
237
except (errors.NoWorkingTree, errors.NotLocalUrl):
173
def _get_basis_components(self, basis):
174
"""Retrieve the basis components that are available at basis."""
176
return None, None, None
178
basis_tree = basis.open_workingtree()
179
basis_branch = basis_tree.branch
180
basis_repo = basis_branch.repository
181
except (errors.NoWorkingTree, errors.NotLocalUrl):
184
basis_branch = basis.open_branch()
185
basis_repo = basis_branch.repository
186
except errors.NotBranchError:
189
basis_repo = basis.open_repository()
190
except errors.NoRepositoryPresent:
192
return basis_repo, basis_branch, basis_tree
194
241
# TODO: This should be given a Transport, and should chdir up; otherwise
195
242
# this will open a new connection.
196
243
def _make_tail(self, url):
197
head, tail = urlutils.split(url)
198
if tail and tail != '.':
199
t = get_transport(head)
202
except errors.FileExists:
244
t = get_transport(url)
205
# TODO: Should take a Transport
207
def create(cls, base, format=None):
248
def create(cls, base, format=None, possible_transports=None):
208
249
"""Create a new BzrDir at the url 'base'.
210
This will call the current default formats initialize with base
211
as the only parameter.
213
251
:param format: If supplied, the format of branch to create. If not
214
252
supplied, the default is used.
253
:param possible_transports: If supplied, a list of transports that
254
can be reused to share a remote connection.
216
256
if cls is not BzrDir:
217
257
raise AssertionError("BzrDir.create always creates the default"
218
258
" format, not one of %r" % cls)
219
head, tail = urlutils.split(base)
220
if tail and tail != '.':
221
t = get_transport(head)
224
except errors.FileExists:
259
t = get_transport(base, possible_transports)
226
261
if format is None:
227
262
format = BzrDirFormat.get_default_format()
228
return format.initialize(safe_unicode(base))
263
return format.initialize_on_transport(t)
266
def find_bzrdirs(transport, evaluate=None, list_current=None):
267
"""Find bzrdirs recursively from current location.
269
This is intended primarily as a building block for more sophisticated
270
functionality, like finding trees under a directory, or finding
271
branches that use a given repository.
272
:param evaluate: An optional callable that yields recurse, value,
273
where recurse controls whether this bzrdir is recursed into
274
and value is the value to yield. By default, all bzrdirs
275
are recursed into, and the return value is the bzrdir.
276
:param list_current: if supplied, use this function to list the current
277
directory, instead of Transport.list_dir
278
:return: a generator of found bzrdirs, or whatever evaluate returns.
280
if list_current is None:
281
def list_current(transport):
282
return transport.list_dir('')
284
def evaluate(bzrdir):
287
pending = [transport]
288
while len(pending) > 0:
289
current_transport = pending.pop()
292
bzrdir = BzrDir.open_from_transport(current_transport)
293
except errors.NotBranchError:
296
recurse, value = evaluate(bzrdir)
299
subdirs = list_current(current_transport)
300
except errors.NoSuchFile:
303
for subdir in sorted(subdirs, reverse=True):
304
pending.append(current_transport.clone(subdir))
307
def find_branches(transport):
308
"""Find all branches under a transport.
310
This will find all branches below the transport, including branches
311
inside other branches. Where possible, it will use
312
Repository.find_branches.
314
To list all the branches that use a particular Repository, see
315
Repository.find_branches
317
def evaluate(bzrdir):
319
repository = bzrdir.open_repository()
320
except errors.NoRepositoryPresent:
323
return False, (None, repository)
325
branch = bzrdir.open_branch()
326
except errors.NotBranchError:
327
return True, (None, None)
329
return True, (branch, None)
331
for branch, repo in BzrDir.find_bzrdirs(transport, evaluate=evaluate):
333
branches.extend(repo.find_branches())
334
if branch is not None:
335
branches.append(branch)
338
def destroy_repository(self):
339
"""Destroy the repository in this BzrDir"""
340
raise NotImplementedError(self.destroy_repository)
230
342
def create_branch(self):
231
343
"""Create a branch in this BzrDir.
233
The bzrdirs format will control what branch format is created.
345
The bzrdir's format will control what branch format is created.
234
346
For more control see BranchFormatXX.create(a_bzrdir).
236
348
raise NotImplementedError(self.create_branch)
350
def destroy_branch(self):
351
"""Destroy the branch in this BzrDir"""
352
raise NotImplementedError(self.destroy_branch)
239
355
def create_branch_and_repo(base, force_new_repo=False, format=None):
240
356
"""Create a new BzrDir, Branch and Repository at the url 'base'.
242
This will use the current default BzrDirFormat, and use whatever
358
This will use the current default BzrDirFormat unless one is
359
specified, and use whatever
243
360
repository format that that uses via bzrdir.create_branch and
244
361
create_repository. If a shared repository is available that is used
249
366
:param base: The URL to create the branch at.
250
367
:param force_new_repo: If True a new repository is always created.
368
:param format: If supplied, the format of branch to create. If not
369
supplied, the default is used.
252
371
bzrdir = BzrDir.create(base, format)
253
372
bzrdir._find_or_create_repository(force_new_repo)
254
373
return bzrdir.create_branch()
375
def determine_repository_policy(self, force_new_repo=False, stack_on=None,
376
stack_on_pwd=None, require_stacking=False):
377
"""Return an object representing a policy to use.
379
This controls whether a new repository is created, or a shared
380
repository used instead.
382
If stack_on is supplied, will not seek a containing shared repo.
384
:param force_new_repo: If True, require a new repository to be created.
385
:param stack_on: If supplied, the location to stack on. If not
386
supplied, a default_stack_on location may be used.
387
:param stack_on_pwd: If stack_on is relative, the location it is
390
def repository_policy(found_bzrdir):
393
config = found_bzrdir.get_config()
395
if config is not None:
396
stack_on = config.get_default_stack_on()
397
if stack_on is not None:
398
stack_on_pwd = found_bzrdir.root_transport.base
400
note('Using default stacking branch %s at %s', stack_on,
402
# does it have a repository ?
404
repository = found_bzrdir.open_repository()
405
except errors.NoRepositoryPresent:
408
if ((found_bzrdir.root_transport.base !=
409
self.root_transport.base) and not repository.is_shared()):
416
return UseExistingRepository(repository, stack_on,
417
stack_on_pwd, require_stacking=require_stacking), True
419
return CreateRepository(self, stack_on, stack_on_pwd,
420
require_stacking=require_stacking), True
422
if not force_new_repo:
424
policy = self._find_containing(repository_policy)
425
if policy is not None:
429
return UseExistingRepository(self.open_repository(),
430
stack_on, stack_on_pwd,
431
require_stacking=require_stacking)
432
except errors.NoRepositoryPresent:
434
return CreateRepository(self, stack_on, stack_on_pwd,
435
require_stacking=require_stacking)
256
437
def _find_or_create_repository(self, force_new_repo):
257
438
"""Create a new repository if needed, returning the repository."""
259
return self.create_repository()
261
return self.find_repository()
262
except errors.NoRepositoryPresent:
263
return self.create_repository()
439
policy = self.determine_repository_policy(force_new_repo)
440
return policy.acquire_repository()
266
443
def create_branch_convenience(base, force_new_repo=False,
267
force_new_tree=None, format=None):
444
force_new_tree=None, format=None,
445
possible_transports=None):
268
446
"""Create a new BzrDir, Branch and Repository at the url 'base'.
270
448
This is a convenience function - it will use an existing repository
271
449
if possible, can be told explicitly whether to create a working tree or
274
This will use the current default BzrDirFormat, and use whatever
452
This will use the current default BzrDirFormat unless one is
453
specified, and use whatever
275
454
repository format that that uses via bzrdir.create_branch and
276
455
create_repository. If a shared repository is available that is used
277
456
preferentially. Whatever repository is used, its tree creation policy
620
991
workingtree and discards it, and that's somewhat expensive.)
623
self.open_workingtree()
994
self.open_workingtree(recommend_upgrade=False)
625
996
except errors.NoWorkingTree:
628
def cloning_metadir(self, basis=None):
629
"""Produce a metadir suitable for cloning with"""
630
def related_repository(bzrdir):
632
branch = bzrdir.open_branch()
633
return branch.repository
634
except errors.NotBranchError:
636
return bzrdir.open_repository()
999
def _cloning_metadir(self):
1000
"""Produce a metadir suitable for cloning with.
1002
:returns: (destination_bzrdir_format, source_repository)
637
1004
result_format = self._format.__class__()
640
source_repository = related_repository(self)
641
except errors.NoRepositoryPresent:
644
source_repository = related_repository(self)
645
result_format.repository_format = source_repository._format
1007
branch = self.open_branch()
1008
source_repository = branch.repository
1009
result_format._branch_format = branch._format
1010
except errors.NotBranchError:
1011
source_branch = None
1012
source_repository = self.open_repository()
646
1013
except errors.NoRepositoryPresent:
650
def sprout(self, url, revision_id=None, basis=None, force_new_repo=False):
1014
source_repository = None
1016
# XXX TODO: This isinstance is here because we have not implemented
1017
# the fix recommended in bug # 103195 - to delegate this choice the
1018
# repository itself.
1019
repo_format = source_repository._format
1020
if isinstance(repo_format, remote.RemoteRepositoryFormat):
1021
source_repository._ensure_real()
1022
repo_format = source_repository._real_repository._format
1023
result_format.repository_format = repo_format
1025
# TODO: Couldn't we just probe for the format in these cases,
1026
# rather than opening the whole tree? It would be a little
1027
# faster. mbp 20070401
1028
tree = self.open_workingtree(recommend_upgrade=False)
1029
except (errors.NoWorkingTree, errors.NotLocalUrl):
1030
result_format.workingtree_format = None
1032
result_format.workingtree_format = tree._format.__class__()
1033
return result_format, source_repository
1035
def cloning_metadir(self, require_stacking=False):
1036
"""Produce a metadir suitable for cloning or sprouting with.
1038
These operations may produce workingtrees (yes, even though they're
1039
"cloning" something that doesn't have a tree), so a viable workingtree
1040
format must be selected.
1042
:require_stacking: If True, non-stackable formats will be upgraded
1043
to similar stackable formats.
1044
:returns: a BzrDirFormat with all component formats either set
1045
appropriately or set to None if that component should not be
1048
format, repository = self._cloning_metadir()
1049
if format._workingtree_format is None:
1050
if repository is None:
1052
tree_format = repository._format._matchingbzrdir.workingtree_format
1053
format.workingtree_format = tree_format.__class__()
1054
if require_stacking:
1055
format.require_stacking()
1058
def checkout_metadir(self):
1059
return self.cloning_metadir()
1061
def sprout(self, url, revision_id=None, force_new_repo=False,
1062
recurse='down', possible_transports=None,
1063
accelerator_tree=None, hardlink=False, stacked=False,
1064
source_branch=None):
651
1065
"""Create a copy of this bzrdir prepared for use as a new line of
654
If urls last component does not exist, it will be created.
1068
If url's last component does not exist, it will be created.
656
1070
Attributes related to the identity of the source branch like
657
1071
branch nickname will be cleaned, a working tree is created
661
1075
if revision_id is not None, then the clone operation may tune
662
1076
itself to download less data.
1077
:param accelerator_tree: A tree which can be used for retrieving file
1078
contents more quickly than the revision tree, i.e. a workingtree.
1079
The revision tree will be used for cases where accelerator_tree's
1080
content is different.
1081
:param hardlink: If true, hard-link files from accelerator_tree,
1083
:param stacked: If true, create a stacked branch referring to the
1084
location of this control directory.
665
cloning_format = self.cloning_metadir(basis)
666
result = cloning_format.initialize(url)
667
basis_repo, basis_branch, basis_tree = self._get_basis_components(basis)
669
source_branch = self.open_branch()
1086
target_transport = get_transport(url, possible_transports)
1087
target_transport.ensure_base()
1088
cloning_format = self.cloning_metadir(stacked)
1089
# Create/update the result branch
1090
result = cloning_format.initialize_on_transport(target_transport)
1091
# if a stacked branch wasn't requested, we don't create one
1092
# even if the origin was stacked
1093
stacked_branch_url = None
1094
if source_branch is not None:
1096
stacked_branch_url = self.root_transport.base
670
1097
source_repository = source_branch.repository
671
except errors.NotBranchError:
674
source_repository = self.open_repository()
675
except errors.NoRepositoryPresent:
676
# copy the entire basis one if there is one
677
# but there is no repository.
678
source_repository = basis_repo
683
result_repo = result.find_repository()
684
except errors.NoRepositoryPresent:
686
if source_repository is None and result_repo is not None:
688
elif source_repository is None and result_repo is None:
689
# no repo available, make a new one
690
result.create_repository()
691
elif source_repository is not None and result_repo is None:
692
# have source, and want to make a new target repo
693
# we don't clone the repo because that preserves attributes
694
# like is_shared(), and we have not yet implemented a
695
# repository sprout().
696
result_repo = result.create_repository()
697
if result_repo is not None:
698
# fetch needed content into target.
700
# XXX FIXME RBC 20060214 need tests for this when the basis
702
result_repo.fetch(basis_repo, revision_id=revision_id)
703
if source_repository is not None:
704
result_repo.fetch(source_repository, revision_id=revision_id)
1100
source_branch = self.open_branch()
1101
source_repository = source_branch.repository
1103
stacked_branch_url = self.root_transport.base
1104
except errors.NotBranchError:
1105
source_branch = None
1107
source_repository = self.open_repository()
1108
except errors.NoRepositoryPresent:
1109
source_repository = None
1110
repository_policy = result.determine_repository_policy(
1111
force_new_repo, stacked_branch_url, require_stacking=stacked)
1112
result_repo = repository_policy.acquire_repository()
1113
if source_repository is not None:
1114
# Fetch while stacked to prevent unstacked fetch from
1116
result_repo.fetch(source_repository, revision_id=revision_id)
1118
if source_branch is None:
1119
# this is for sprouting a bzrdir without a branch; is that
1121
# Not especially, but it's part of the contract.
1122
result_branch = result.create_branch()
1124
# Force NULL revision to avoid using repository before stacking
1126
result_branch = source_branch.sprout(
1127
result, revision_id=_mod_revision.NULL_REVISION)
1128
parent_location = result_branch.get_parent()
1129
mutter("created new branch %r" % (result_branch,))
1130
repository_policy.configure_branch(result_branch)
705
1131
if source_branch is not None:
706
source_branch.sprout(result, revision_id=revision_id)
708
result.create_branch()
709
# TODO: jam 20060426 we probably need a test in here in the
710
# case that the newly sprouted branch is a remote one
711
if result_repo is None or result_repo.make_working_trees():
712
wt = result.create_workingtree()
1132
source_branch.copy_content_into(result_branch, revision_id)
1133
# Override copy_content_into
1134
result_branch.set_parent(parent_location)
1136
# Create/update the result working tree
1137
if isinstance(target_transport, local.LocalTransport) and (
1138
result_repo is None or result_repo.make_working_trees()):
1139
wt = result.create_workingtree(accelerator_tree=accelerator_tree,
715
1143
if wt.path2id('') is None:
1997
2586
except errors.NotBranchError:
2589
# TODO: conversions of Branch and Tree should be done by
2590
# InterXFormat lookups/some sort of registry.
2000
2591
# Avoid circular imports
2001
2592
from bzrlib import branch as _mod_branch
2002
if (branch._format.__class__ is _mod_branch.BzrBranchFormat5 and
2003
self.target_format.get_branch_format().__class__ is
2004
_mod_branch.BzrBranchFormat6):
2005
branch_converter = _mod_branch.Converter5to6()
2593
old = branch._format.__class__
2594
new = self.target_format.get_branch_format().__class__
2596
if (old == _mod_branch.BzrBranchFormat5 and
2597
new in (_mod_branch.BzrBranchFormat6,
2598
_mod_branch.BzrBranchFormat7)):
2599
branch_converter = _mod_branch.Converter5to6()
2600
elif (old == _mod_branch.BzrBranchFormat6 and
2601
new == _mod_branch.BzrBranchFormat7):
2602
branch_converter = _mod_branch.Converter6to7()
2604
raise errors.BadConversionTarget("No converter", new)
2006
2605
branch_converter.convert(branch)
2606
branch = self.bzrdir.open_branch()
2607
old = branch._format.__class__
2609
tree = self.bzrdir.open_workingtree(recommend_upgrade=False)
2610
except (errors.NoWorkingTree, errors.NotLocalUrl):
2613
# TODO: conversions of Branch and Tree should be done by
2614
# InterXFormat lookups
2615
if (isinstance(tree, workingtree.WorkingTree3) and
2616
not isinstance(tree, workingtree_4.DirStateWorkingTree) and
2617
isinstance(self.target_format.workingtree_format,
2618
workingtree_4.DirStateWorkingTreeFormat)):
2619
workingtree_4.Converter3to4().convert(tree)
2620
if (isinstance(tree, workingtree_4.DirStateWorkingTree) and
2621
not isinstance(tree, workingtree_4.WorkingTree5) and
2622
isinstance(self.target_format.workingtree_format,
2623
workingtree_4.WorkingTreeFormat5)):
2624
workingtree_4.Converter4to5().convert(tree)
2007
2625
return to_convert
2628
# This is not in remote.py because it's small, and needs to be registered.
2629
# Putting it in remote.py creates a circular import problem.
2630
# we can make it a lazy object if the control formats is turned into something
2632
class RemoteBzrDirFormat(BzrDirMetaFormat1):
2633
"""Format representing bzrdirs accessed via a smart server"""
2635
def get_format_description(self):
2636
return 'bzr remote bzrdir'
2639
def probe_transport(klass, transport):
2640
"""Return a RemoteBzrDirFormat object if it looks possible."""
2642
medium = transport.get_smart_medium()
2643
except (NotImplementedError, AttributeError,
2644
errors.TransportNotPossible, errors.NoSmartMedium,
2645
errors.SmartProtocolError):
2646
# no smart server, so not a branch for this format type.
2647
raise errors.NotBranchError(path=transport.base)
2649
# Decline to open it if the server doesn't support our required
2650
# version (3) so that the VFS-based transport will do it.
2651
if medium.should_probe():
2653
server_version = medium.protocol_version()
2654
except errors.SmartProtocolError:
2655
# Apparently there's no usable smart server there, even though
2656
# the medium supports the smart protocol.
2657
raise errors.NotBranchError(path=transport.base)
2658
if server_version != '2':
2659
raise errors.NotBranchError(path=transport.base)
2662
def initialize_on_transport(self, transport):
2664
# hand off the request to the smart server
2665
client_medium = transport.get_smart_medium()
2666
except errors.NoSmartMedium:
2667
# TODO: lookup the local format from a server hint.
2668
local_dir_format = BzrDirMetaFormat1()
2669
return local_dir_format.initialize_on_transport(transport)
2670
client = _SmartClient(client_medium)
2671
path = client.remote_path_from_transport(transport)
2672
response = client.call('BzrDirFormat.initialize', path)
2673
if response[0] != 'ok':
2674
raise errors.SmartProtocolError('unexpected response code %s' % (response,))
2675
return remote.RemoteBzrDir(transport)
2677
def _open(self, transport):
2678
return remote.RemoteBzrDir(transport)
2680
def __eq__(self, other):
2681
if not isinstance(other, RemoteBzrDirFormat):
2683
return self.get_format_description() == other.get_format_description()
2686
def repository_format(self):
2687
# Using a property to avoid early loading of remote
2688
return remote.RemoteRepositoryFormat()
2691
BzrDirFormat.register_control_server_format(RemoteBzrDirFormat)
2010
2694
class BzrDirFormatInfo(object):
2012
def __init__(self, native, deprecated):
2696
def __init__(self, native, deprecated, hidden, experimental):
2013
2697
self.deprecated = deprecated
2014
2698
self.native = native
2699
self.hidden = hidden
2700
self.experimental = experimental
2017
2703
class BzrDirFormatRegistry(registry.Registry):
2021
2707
e.g. BzrDirMeta1 with weave repository. Also, it's more user-oriented.
2024
def register_metadir(self, key, repo, help, native=True, deprecated=False,
2025
branch_format=None):
2711
"""Create a BzrDirFormatRegistry."""
2712
self._aliases = set()
2713
self._registration_order = list()
2714
super(BzrDirFormatRegistry, self).__init__()
2717
"""Return a set of the format names which are aliases."""
2718
return frozenset(self._aliases)
2720
def register_metadir(self, key,
2721
repository_format, help, native=True, deprecated=False,
2026
2727
"""Register a metadir subformat.
2028
2729
These all use a BzrDirMetaFormat1 bzrdir, but can be parameterized
2029
2730
by the Repository format.
2031
:param repo: The fully-qualified repository format class name as a
2732
:param repository_format: The fully-qualified repository format class
2734
:param branch_format: Fully-qualified branch format class name as
2736
:param tree_format: Fully-qualified tree format class name as
2034
2739
# This should be expanded to support setting WorkingTree and Branch
2035
2740
# formats, once BzrDirMetaFormat1 supports that.
2037
import bzrlib.branch
2038
mod_name, repo_factory_name = repo.rsplit('.', 1)
2741
def _load(full_name):
2742
mod_name, factory_name = full_name.rsplit('.', 1)
2040
2744
mod = __import__(mod_name, globals(), locals(),
2041
[repo_factory_name])
2042
2746
except ImportError, e:
2043
raise ImportError('failed to load repository %s: %s'
2747
raise ImportError('failed to load %s: %s' % (full_name, e))
2046
repo_format_class = getattr(mod, repo_factory_name)
2749
factory = getattr(mod, factory_name)
2047
2750
except AttributeError:
2048
raise AttributeError('no repository format %r in module %r'
2751
raise AttributeError('no factory %s in module %r'
2050
2756
bd = BzrDirMetaFormat1()
2051
bd.repository_format = repo_format_class()
2052
2757
if branch_format is not None:
2053
bd.set_branch_format(getattr(bzrlib.branch, branch_format)())
2758
bd.set_branch_format(_load(branch_format))
2759
if tree_format is not None:
2760
bd.workingtree_format = _load(tree_format)
2761
if repository_format is not None:
2762
bd.repository_format = _load(repository_format)
2055
self.register(key, helper, help, native, deprecated)
2764
self.register(key, helper, help, native, deprecated, hidden,
2765
experimental, alias)
2057
def register(self, key, factory, help, native=True, deprecated=False):
2767
def register(self, key, factory, help, native=True, deprecated=False,
2768
hidden=False, experimental=False, alias=False):
2058
2769
"""Register a BzrDirFormat factory.
2060
2771
The factory must be a callable that takes one parameter: the key.
2117
2828
def wrapped(key, help, info):
2118
2829
if info.native:
2119
2830
help = '(native) ' + help
2120
return ' %s:\n%s\n\n' % (key,
2831
return ':%s:\n%s\n\n' % (key,
2121
2832
textwrap.fill(help, initial_indent=' ',
2122
2833
subsequent_indent=' '))
2123
output += wrapped('%s/default' % default_realkey, default_help,
2124
self.get_info('default'))
2834
if default_realkey is not None:
2835
output += wrapped(default_realkey, '(default) %s' % default_help,
2836
self.get_info('default'))
2125
2837
deprecated_pairs = []
2838
experimental_pairs = []
2126
2839
for key, help in help_pairs:
2127
2840
info = self.get_info(key)
2843
elif info.deprecated:
2129
2844
deprecated_pairs.append((key, help))
2845
elif info.experimental:
2846
experimental_pairs.append((key, help))
2131
2848
output += wrapped(key, help, info)
2849
output += "\nSee ``bzr help formats`` for more about storage formats."
2851
if len(experimental_pairs) > 0:
2852
other_output += "Experimental formats are shown below.\n\n"
2853
for key, help in experimental_pairs:
2854
info = self.get_info(key)
2855
other_output += wrapped(key, help, info)
2858
"No experimental formats are available.\n\n"
2132
2859
if len(deprecated_pairs) > 0:
2133
output += "Deprecated formats\n------------------\n\n"
2860
other_output += "\nDeprecated formats are shown below.\n\n"
2134
2861
for key, help in deprecated_pairs:
2135
2862
info = self.get_info(key)
2136
output += wrapped(key, help, info)
2863
other_output += wrapped(key, help, info)
2866
"\nNo deprecated formats are available.\n\n"
2868
"\nSee ``bzr help formats`` for more about storage formats."
2870
if topic == 'other-formats':
2876
class RepositoryAcquisitionPolicy(object):
2877
"""Abstract base class for repository acquisition policies.
2879
A repository acquisition policy decides how a BzrDir acquires a repository
2880
for a branch that is being created. The most basic policy decision is
2881
whether to create a new repository or use an existing one.
2883
def __init__(self, stack_on, stack_on_pwd, require_stacking):
2886
:param stack_on: A location to stack on
2887
:param stack_on_pwd: If stack_on is relative, the location it is
2889
:param require_stacking: If True, it is a failure to not stack.
2891
self._stack_on = stack_on
2892
self._stack_on_pwd = stack_on_pwd
2893
self._require_stacking = require_stacking
2895
def configure_branch(self, branch):
2896
"""Apply any configuration data from this policy to the branch.
2898
Default implementation sets repository stacking.
2900
if self._stack_on is None:
2902
if self._stack_on_pwd is None:
2903
stack_on = self._stack_on
2906
stack_on = urlutils.rebase_url(self._stack_on,
2908
branch.bzrdir.root_transport.base)
2909
except errors.InvalidRebaseURLs:
2910
stack_on = self._get_full_stack_on()
2912
branch.set_stacked_on_url(stack_on)
2913
except errors.UnstackableBranchFormat:
2914
if self._require_stacking:
2917
def _get_full_stack_on(self):
2918
"""Get a fully-qualified URL for the stack_on location."""
2919
if self._stack_on is None:
2921
if self._stack_on_pwd is None:
2922
return self._stack_on
2924
return urlutils.join(self._stack_on_pwd, self._stack_on)
2926
def _add_fallback(self, repository, possible_transports=None):
2927
"""Add a fallback to the supplied repository, if stacking is set."""
2928
stack_on = self._get_full_stack_on()
2929
if stack_on is None:
2931
stacked_dir = BzrDir.open(stack_on,
2932
possible_transports=possible_transports)
2934
stacked_repo = stacked_dir.open_branch().repository
2935
except errors.NotBranchError:
2936
stacked_repo = stacked_dir.open_repository()
2938
repository.add_fallback_repository(stacked_repo)
2939
except errors.UnstackableRepositoryFormat:
2940
if self._require_stacking:
2943
self._require_stacking = True
2945
def acquire_repository(self, make_working_trees=None, shared=False):
2946
"""Acquire a repository for this bzrdir.
2948
Implementations may create a new repository or use a pre-exising
2950
:param make_working_trees: If creating a repository, set
2951
make_working_trees to this value (if non-None)
2952
:param shared: If creating a repository, make it shared if True
2953
:return: A repository
2955
raise NotImplemented(RepositoryAcquisitionPolicy.acquire_repository)
2958
class CreateRepository(RepositoryAcquisitionPolicy):
2959
"""A policy of creating a new repository"""
2961
def __init__(self, bzrdir, stack_on=None, stack_on_pwd=None,
2962
require_stacking=False):
2965
:param bzrdir: The bzrdir to create the repository on.
2966
:param stack_on: A location to stack on
2967
:param stack_on_pwd: If stack_on is relative, the location it is
2970
RepositoryAcquisitionPolicy.__init__(self, stack_on, stack_on_pwd,
2972
self._bzrdir = bzrdir
2974
def acquire_repository(self, make_working_trees=None, shared=False):
2975
"""Implementation of RepositoryAcquisitionPolicy.acquire_repository
2977
Creates the desired repository in the bzrdir we already have.
2979
repository = self._bzrdir.create_repository(shared=shared)
2980
self._add_fallback(repository,
2981
possible_transports=[self._bzrdir.transport])
2982
if make_working_trees is not None:
2983
repository.set_make_working_trees(make_working_trees)
2987
class UseExistingRepository(RepositoryAcquisitionPolicy):
2988
"""A policy of reusing an existing repository"""
2990
def __init__(self, repository, stack_on=None, stack_on_pwd=None,
2991
require_stacking=False):
2994
:param repository: The repository to use.
2995
:param stack_on: A location to stack on
2996
:param stack_on_pwd: If stack_on is relative, the location it is
2999
RepositoryAcquisitionPolicy.__init__(self, stack_on, stack_on_pwd,
3001
self._repository = repository
3003
def acquire_repository(self, make_working_trees=None, shared=False):
3004
"""Implementation of RepositoryAcquisitionPolicy.acquire_repository
3006
Returns an existing repository to use
3008
self._add_fallback(self._repository,
3009
possible_transports=[self._repository.bzrdir.transport])
3010
return self._repository
3013
# Please register new formats after old formats so that formats
3014
# appear in chronological order and format descriptions can build
2141
3016
format_registry = BzrDirFormatRegistry()
2142
3017
format_registry.register('weave', BzrDirFormat6,
2143
3018
'Pre-0.8 format. Slower than knit and does not'
2144
3019
' support checkouts or shared repositories.',
2145
3020
deprecated=True)
2146
format_registry.register_metadir('knit',
2147
'bzrlib.repofmt.knitrepo.RepositoryFormatKnit1',
2148
'Format using knits. Recommended.',
2149
branch_format='BzrBranchFormat5')
2150
format_registry.set_default('knit')
2151
3021
format_registry.register_metadir('metaweave',
2152
3022
'bzrlib.repofmt.weaverepo.RepositoryFormat7',
2153
3023
'Transitional format in 0.8. Slower than knit.',
2156
format_registry.register_metadir('experimental-knit2',
2157
'bzrlib.repofmt.knitrepo.RepositoryFormatKnit2',
2158
'Experimental successor to knit. Use at your own risk.',
2159
branch_format='BzrBranchFormat5')
2160
format_registry.register_metadir('experimental-branch6',
2161
'bzrlib.repofmt.knitrepo.RepositoryFormatKnit1',
2162
'Experimental successor to knit. Use at your own risk.',
2163
branch_format='BzrBranchFormat6')
3024
branch_format='bzrlib.branch.BzrBranchFormat5',
3025
tree_format='bzrlib.workingtree.WorkingTreeFormat3',
3027
format_registry.register_metadir('knit',
3028
'bzrlib.repofmt.knitrepo.RepositoryFormatKnit1',
3029
'Format using knits. Recommended for interoperation with bzr <= 0.14.',
3030
branch_format='bzrlib.branch.BzrBranchFormat5',
3031
tree_format='bzrlib.workingtree.WorkingTreeFormat3',
3033
format_registry.register_metadir('dirstate',
3034
'bzrlib.repofmt.knitrepo.RepositoryFormatKnit1',
3035
help='New in 0.15: Fast local operations. Compatible with bzr 0.8 and '
3036
'above when accessed over the network.',
3037
branch_format='bzrlib.branch.BzrBranchFormat5',
3038
# this uses bzrlib.workingtree.WorkingTreeFormat4 because importing
3039
# directly from workingtree_4 triggers a circular import.
3040
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3042
format_registry.register_metadir('dirstate-tags',
3043
'bzrlib.repofmt.knitrepo.RepositoryFormatKnit1',
3044
help='New in 0.15: Fast local operations and improved scaling for '
3045
'network operations. Additionally adds support for tags.'
3046
' Incompatible with bzr < 0.15.',
3047
branch_format='bzrlib.branch.BzrBranchFormat6',
3048
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3050
format_registry.register_metadir('rich-root',
3051
'bzrlib.repofmt.knitrepo.RepositoryFormatKnit4',
3052
help='New in 1.0. Better handling of tree roots. Incompatible with'
3054
branch_format='bzrlib.branch.BzrBranchFormat6',
3055
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3057
format_registry.register_metadir('dirstate-with-subtree',
3058
'bzrlib.repofmt.knitrepo.RepositoryFormatKnit3',
3059
help='New in 0.15: Fast local operations and improved scaling for '
3060
'network operations. Additionally adds support for versioning nested '
3061
'bzr branches. Incompatible with bzr < 0.15.',
3062
branch_format='bzrlib.branch.BzrBranchFormat6',
3063
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3067
format_registry.register_metadir('pack-0.92',
3068
'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack1',
3069
help='New in 0.92: Pack-based format with data compatible with '
3070
'dirstate-tags format repositories. Interoperates with '
3071
'bzr repositories before 0.92 but cannot be read by bzr < 0.92. '
3072
'Previously called knitpack-experimental. '
3073
'For more information, see '
3074
'http://doc.bazaar-vcs.org/latest/developers/packrepo.html.',
3075
branch_format='bzrlib.branch.BzrBranchFormat6',
3076
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3078
format_registry.register_metadir('pack-0.92-subtree',
3079
'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack3',
3080
help='New in 0.92: Pack-based format with data compatible with '
3081
'dirstate-with-subtree format repositories. Interoperates with '
3082
'bzr repositories before 0.92 but cannot be read by bzr < 0.92. '
3083
'Previously called knitpack-experimental. '
3084
'For more information, see '
3085
'http://doc.bazaar-vcs.org/latest/developers/packrepo.html.',
3086
branch_format='bzrlib.branch.BzrBranchFormat6',
3087
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3091
format_registry.register_metadir('rich-root-pack',
3092
'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack4',
3093
help='New in 1.0: A variant of pack-0.92 that supports rich-root data '
3094
'(needed for bzr-svn).',
3095
branch_format='bzrlib.branch.BzrBranchFormat6',
3096
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3098
format_registry.register_metadir('1.6',
3099
'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack5',
3100
help='A format that allows a branch to indicate that there is another '
3101
'(stacked) repository that should be used to access data that is '
3102
'not present locally.',
3103
branch_format='bzrlib.branch.BzrBranchFormat7',
3104
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3106
format_registry.register_metadir('1.6.1-rich-root',
3107
'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack5RichRoot',
3108
help='A variant of 1.6 that supports rich-root data '
3109
'(needed for bzr-svn).',
3110
branch_format='bzrlib.branch.BzrBranchFormat7',
3111
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3113
format_registry.register_metadir('1.9',
3114
'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack6',
3115
help='A repository format using B+tree indexes. These indexes '
3116
'are smaller in size, have smarter caching and provide faster '
3117
'performance for most operations.',
3118
branch_format='bzrlib.branch.BzrBranchFormat7',
3119
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3121
format_registry.register_metadir('1.9-rich-root',
3122
'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack6RichRoot',
3123
help='A variant of 1.9 that supports rich-root data '
3124
'(needed for bzr-svn).',
3125
branch_format='bzrlib.branch.BzrBranchFormat7',
3126
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3128
format_registry.register_metadir('1.12-preview',
3129
'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack6',
3130
help='A working-tree format that supports views and content filtering.',
3131
branch_format='bzrlib.branch.BzrBranchFormat7',
3132
tree_format='bzrlib.workingtree_4.WorkingTreeFormat5',
3135
format_registry.register_metadir('1.12-preview-rich-root',
3136
'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack6RichRoot',
3137
help='A variant of 1.12-preview that supports rich-root data '
3138
'(needed for bzr-svn).',
3139
branch_format='bzrlib.branch.BzrBranchFormat7',
3140
tree_format='bzrlib.workingtree_4.WorkingTreeFormat5',
3143
# The following two formats should always just be aliases.
3144
format_registry.register_metadir('development',
3145
'bzrlib.repofmt.pack_repo.RepositoryFormatPackDevelopment2',
3146
help='Current development format. Can convert data to and from pack-0.92 '
3147
'(and anything compatible with pack-0.92) format repositories. '
3148
'Repositories and branches in this format can only be read by bzr.dev. '
3150
'http://doc.bazaar-vcs.org/latest/developers/development-repo.html '
3152
branch_format='bzrlib.branch.BzrBranchFormat7',
3153
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3157
format_registry.register_metadir('development-subtree',
3158
'bzrlib.repofmt.pack_repo.RepositoryFormatPackDevelopment2Subtree',
3159
help='Current development format, subtree variant. Can convert data to and '
3160
'from pack-0.92-subtree (and anything compatible with '
3161
'pack-0.92-subtree) format repositories. Repositories and branches in '
3162
'this format can only be read by bzr.dev. Please read '
3163
'http://doc.bazaar-vcs.org/latest/developers/development-repo.html '
3165
branch_format='bzrlib.branch.BzrBranchFormat7',
3166
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3170
# And the development formats above will have aliased one of the following:
3171
format_registry.register_metadir('development2',
3172
'bzrlib.repofmt.pack_repo.RepositoryFormatPackDevelopment2',
3173
help='1.6.1 with B+Tree based index. '
3175
'http://doc.bazaar-vcs.org/latest/developers/development-repo.html '
3177
branch_format='bzrlib.branch.BzrBranchFormat7',
3178
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3182
format_registry.register_metadir('development2-subtree',
3183
'bzrlib.repofmt.pack_repo.RepositoryFormatPackDevelopment2Subtree',
3184
help='1.6.1-subtree with B+Tree based index. '
3186
'http://doc.bazaar-vcs.org/latest/developers/development-repo.html '
3188
branch_format='bzrlib.branch.BzrBranchFormat7',
3189
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3193
# The current format that is made on 'bzr init'.
3194
format_registry.set_default('pack-0.92')