84
121
"""Return true if this bzrdir is one whose format we can convert from."""
124
def check_conversion_target(self, target_format):
125
target_repo_format = target_format.repository_format
126
source_repo_format = self._format.repository_format
127
source_repo_format.check_conversion_target(target_repo_format)
88
def _check_supported(format, allow_unsupported):
89
"""Check whether format is a supported format.
91
If allow_unsupported is True, this is a no-op.
130
def _check_supported(format, allow_unsupported,
131
recommend_upgrade=True,
133
"""Give an error or warning on old formats.
135
:param format: may be any kind of format - workingtree, branch,
138
:param allow_unsupported: If true, allow opening
139
formats that are strongly deprecated, and which may
140
have limited functionality.
142
:param recommend_upgrade: If true (default), warn
143
the user through the ui object that they may wish
144
to upgrade the object.
146
# TODO: perhaps move this into a base Format class; it's not BzrDir
147
# specific. mbp 20070323
93
148
if not allow_unsupported and not format.is_supported():
94
149
# see open_downlevel to open legacy branches.
95
raise errors.UnsupportedFormatError(
96
'sorry, format %s not supported' % format,
97
['use a different bzr version',
98
'or remove the .bzr directory'
99
' and "bzr init" again'])
150
raise errors.UnsupportedFormatError(format=format)
151
if recommend_upgrade \
152
and getattr(format, 'upgrade_recommended', False):
153
ui.ui_factory.recommend_upgrade(
154
format.get_format_description(),
101
def clone(self, url, revision_id=None, basis=None, force_new_repo=False):
157
def clone(self, url, revision_id=None, force_new_repo=False):
102
158
"""Clone this bzrdir and its contents to url verbatim.
104
If urls last component does not exist, it will be created.
106
if revision_id is not None, then the clone operation may tune
107
itself to download less data.
108
:param force_new_repo: Do not use a shared repository for the target
109
even if one is available.
112
basis_repo, basis_branch, basis_tree = self._get_basis_components(basis)
113
result = self._format.initialize(url)
160
If url's last component does not exist, it will be created.
162
if revision_id is not None, then the clone operation may tune
163
itself to download less data.
164
:param force_new_repo: Do not use a shared repository for the target
165
even if one is available.
167
return self.clone_on_transport(get_transport(url),
168
revision_id=revision_id,
169
force_new_repo=force_new_repo)
171
def clone_on_transport(self, transport, revision_id=None,
172
force_new_repo=False):
173
"""Clone this bzrdir and its contents to transport verbatim.
175
If the target directory does not exist, it will be created.
177
if revision_id is not None, then the clone operation may tune
178
itself to download less data.
179
:param force_new_repo: Do not use a shared repository for the target
180
even if one is available.
182
transport.ensure_base()
183
result = self.cloning_metadir().initialize_on_transport(transport)
184
repository_policy = None
115
186
local_repo = self.find_repository()
116
187
except errors.NoRepositoryPresent:
117
188
local_repo = None
119
190
# may need to copy content in
121
result_repo = local_repo.clone(
123
revision_id=revision_id,
125
result_repo.set_make_working_trees(local_repo.make_working_trees())
128
result_repo = result.find_repository()
129
# fetch content this dir needs.
131
# XXX FIXME RBC 20060214 need tests for this when the basis
133
result_repo.fetch(basis_repo, revision_id=revision_id)
134
result_repo.fetch(local_repo, revision_id=revision_id)
135
except errors.NoRepositoryPresent:
136
# needed to make one anyway.
137
result_repo = local_repo.clone(
139
revision_id=revision_id,
141
result_repo.set_make_working_trees(local_repo.make_working_trees())
191
repository_policy = result.determine_repository_policy(
193
make_working_trees = local_repo.make_working_trees()
194
result_repo = repository_policy.acquire_repository(
195
make_working_trees, local_repo.is_shared())
196
result_repo.fetch(local_repo, revision_id=revision_id)
142
197
# 1 if there is a branch present
143
198
# make sure its content is available in the target repository
146
self.open_branch().clone(result, revision_id=revision_id)
201
local_branch = self.open_branch()
147
202
except errors.NotBranchError:
205
result_branch = local_branch.clone(result, revision_id=revision_id)
206
if repository_policy is not None:
207
repository_policy.configure_branch(result_branch)
150
self.open_workingtree().clone(result, basis=basis_tree)
151
except (errors.NoWorkingTree, errors.NotLocalUrl):
209
result_repo = result.find_repository()
210
except errors.NoRepositoryPresent:
212
if result_repo is None or result_repo.make_working_trees():
214
self.open_workingtree().clone(result)
215
except (errors.NoWorkingTree, errors.NotLocalUrl):
155
def _get_basis_components(self, basis):
156
"""Retrieve the basis components that are available at basis."""
158
return None, None, None
160
basis_tree = basis.open_workingtree()
161
basis_branch = basis_tree.branch
162
basis_repo = basis_branch.repository
163
except (errors.NoWorkingTree, errors.NotLocalUrl):
166
basis_branch = basis.open_branch()
167
basis_repo = basis_branch.repository
168
except errors.NotBranchError:
171
basis_repo = basis.open_repository()
172
except errors.NoRepositoryPresent:
174
return basis_repo, basis_branch, basis_tree
176
219
# TODO: This should be given a Transport, and should chdir up; otherwise
177
220
# this will open a new connection.
178
221
def _make_tail(self, url):
179
head, tail = urlutils.split(url)
180
if tail and tail != '.':
181
t = bzrlib.transport.get_transport(head)
184
except errors.FileExists:
222
t = get_transport(url)
187
# TODO: Should take a Transport
189
def create(cls, base):
226
def create(cls, base, format=None, possible_transports=None):
190
227
"""Create a new BzrDir at the url 'base'.
192
This will call the current default formats initialize with base
193
as the only parameter.
195
If you need a specific format, consider creating an instance
196
of that and calling initialize().
229
:param format: If supplied, the format of branch to create. If not
230
supplied, the default is used.
231
:param possible_transports: If supplied, a list of transports that
232
can be reused to share a remote connection.
198
234
if cls is not BzrDir:
199
raise AssertionError("BzrDir.create always creates the default format, "
200
"not one of %r" % cls)
201
head, tail = urlutils.split(base)
202
if tail and tail != '.':
203
t = bzrlib.transport.get_transport(head)
206
except errors.FileExists:
208
return BzrDirFormat.get_default_format().initialize(safe_unicode(base))
235
raise AssertionError("BzrDir.create always creates the default"
236
" format, not one of %r" % cls)
237
t = get_transport(base, possible_transports)
240
format = BzrDirFormat.get_default_format()
241
return format.initialize_on_transport(t)
244
def find_bzrdirs(transport, evaluate=None, list_current=None):
245
"""Find bzrdirs recursively from current location.
247
This is intended primarily as a building block for more sophisticated
248
functionality, like finding trees under a directory, or finding
249
branches that use a given repository.
250
:param evaluate: An optional callable that yields recurse, value,
251
where recurse controls whether this bzrdir is recursed into
252
and value is the value to yield. By default, all bzrdirs
253
are recursed into, and the return value is the bzrdir.
254
:param list_current: if supplied, use this function to list the current
255
directory, instead of Transport.list_dir
256
:return: a generator of found bzrdirs, or whatever evaluate returns.
258
if list_current is None:
259
def list_current(transport):
260
return transport.list_dir('')
262
def evaluate(bzrdir):
265
pending = [transport]
266
while len(pending) > 0:
267
current_transport = pending.pop()
270
bzrdir = BzrDir.open_from_transport(current_transport)
271
except errors.NotBranchError:
274
recurse, value = evaluate(bzrdir)
277
subdirs = list_current(current_transport)
278
except errors.NoSuchFile:
281
for subdir in sorted(subdirs, reverse=True):
282
pending.append(current_transport.clone(subdir))
285
def find_branches(transport):
286
"""Find all branches under a transport.
288
This will find all branches below the transport, including branches
289
inside other branches. Where possible, it will use
290
Repository.find_branches.
292
To list all the branches that use a particular Repository, see
293
Repository.find_branches
295
def evaluate(bzrdir):
297
repository = bzrdir.open_repository()
298
except errors.NoRepositoryPresent:
301
return False, (None, repository)
303
branch = bzrdir.open_branch()
304
except errors.NotBranchError:
305
return True, (None, None)
307
return True, (branch, None)
309
for branch, repo in BzrDir.find_bzrdirs(transport, evaluate=evaluate):
311
branches.extend(repo.find_branches())
312
if branch is not None:
313
branches.append(branch)
317
def destroy_repository(self):
318
"""Destroy the repository in this BzrDir"""
319
raise NotImplementedError(self.destroy_repository)
210
321
def create_branch(self):
211
322
"""Create a branch in this BzrDir.
213
The bzrdirs format will control what branch format is created.
324
The bzrdir's format will control what branch format is created.
214
325
For more control see BranchFormatXX.create(a_bzrdir).
216
327
raise NotImplementedError(self.create_branch)
329
def destroy_branch(self):
330
"""Destroy the branch in this BzrDir"""
331
raise NotImplementedError(self.destroy_branch)
219
def create_branch_and_repo(base, force_new_repo=False):
334
def create_branch_and_repo(base, force_new_repo=False, format=None):
220
335
"""Create a new BzrDir, Branch and Repository at the url 'base'.
222
This will use the current default BzrDirFormat, and use whatever
337
This will use the current default BzrDirFormat unless one is
338
specified, and use whatever
223
339
repository format that that uses via bzrdir.create_branch and
224
340
create_repository. If a shared repository is available that is used
266
414
:param force_new_repo: If True a new repository is always created.
267
415
:param force_new_tree: If True or False force creation of a tree or
268
416
prevent such creation respectively.
269
:param format: Override for the for the bzrdir format to create
417
:param format: Override for the bzrdir format to create.
418
:param possible_transports: An optional reusable transports list.
271
420
if force_new_tree:
272
421
# check for non local urls
273
t = get_transport(safe_unicode(base))
422
t = get_transport(base, possible_transports)
274
423
if not isinstance(t, LocalTransport):
275
424
raise errors.NotLocalUrl(base)
277
bzrdir = BzrDir.create(base)
279
bzrdir = format.initialize(base)
425
bzrdir = BzrDir.create(base, format, possible_transports)
280
426
repo = bzrdir._find_or_create_repository(force_new_repo)
281
427
result = bzrdir.create_branch()
282
if force_new_tree or (repo.make_working_trees() and
428
if force_new_tree or (repo.make_working_trees() and
283
429
force_new_tree is None):
285
431
bzrdir.create_workingtree()
286
432
except errors.NotLocalUrl:
291
def create_repository(base, shared=False):
437
@deprecated_function(zero_ninetyone)
438
def create_repository(base, shared=False, format=None):
292
439
"""Create a new BzrDir and Repository at the url 'base'.
294
This will use the current default BzrDirFormat, and use whatever
295
repository format that that uses for bzrdirformat.create_repository.
441
If no format is supplied, this will default to the current default
442
BzrDirFormat by default, and use whatever repository format that that
443
uses for bzrdirformat.create_repository.
297
;param shared: Create a shared repository rather than a standalone
445
:param shared: Create a shared repository rather than a standalone
299
447
The Repository object is returned.
301
449
This must be overridden as an instance method in child classes, where
302
450
it should take no parameters and construct whatever repository format
303
451
that child class desires.
453
This method is deprecated, please call create_repository on a bzrdir
305
bzrdir = BzrDir.create(base)
306
return bzrdir.create_repository()
456
bzrdir = BzrDir.create(base, format)
457
return bzrdir.create_repository(shared)
309
def create_standalone_workingtree(base):
460
def create_standalone_workingtree(base, format=None):
310
461
"""Create a new BzrDir, WorkingTree, Branch and Repository at 'base'.
312
463
'base' must be a local path or a file:// url.
314
This will use the current default BzrDirFormat, and use whatever
465
This will use the current default BzrDirFormat unless one is
466
specified, and use whatever
315
467
repository format that that uses for bzrdirformat.create_workingtree,
316
468
create_branch and create_repository.
318
The WorkingTree object is returned.
470
:param format: Override for the bzrdir format to create.
471
:return: The WorkingTree object.
320
t = get_transport(safe_unicode(base))
473
t = get_transport(base)
321
474
if not isinstance(t, LocalTransport):
322
475
raise errors.NotLocalUrl(base)
323
bzrdir = BzrDir.create_branch_and_repo(safe_unicode(base),
324
force_new_repo=True).bzrdir
476
bzrdir = BzrDir.create_branch_and_repo(base,
478
format=format).bzrdir
325
479
return bzrdir.create_workingtree()
327
def create_workingtree(self, revision_id=None):
481
def create_workingtree(self, revision_id=None, from_branch=None,
482
accelerator_tree=None, hardlink=False):
328
483
"""Create a working tree at this BzrDir.
330
revision_id: create it as of this revision id.
485
:param revision_id: create it as of this revision id.
486
:param from_branch: override bzrdir branch (for lightweight checkouts)
487
:param accelerator_tree: A tree which can be used for retrieving file
488
contents more quickly than the revision tree, i.e. a workingtree.
489
The revision tree will be used for cases where accelerator_tree's
490
content is different.
332
492
raise NotImplementedError(self.create_workingtree)
494
def retire_bzrdir(self, limit=10000):
495
"""Permanently disable the bzrdir.
497
This is done by renaming it to give the user some ability to recover
498
if there was a problem.
500
This will have horrible consequences if anyone has anything locked or
502
:param limit: number of times to retry
507
to_path = '.bzr.retired.%d' % i
508
self.root_transport.rename('.bzr', to_path)
509
note("renamed %s to %s"
510
% (self.root_transport.abspath('.bzr'), to_path))
512
except (errors.TransportError, IOError, errors.PathError):
519
def destroy_workingtree(self):
520
"""Destroy the working tree at this BzrDir.
522
Formats that do not support this may raise UnsupportedOperation.
524
raise NotImplementedError(self.destroy_workingtree)
526
def destroy_workingtree_metadata(self):
527
"""Destroy the control files for the working tree at this BzrDir.
529
The contents of working tree files are not affected.
530
Formats that do not support this may raise UnsupportedOperation.
532
raise NotImplementedError(self.destroy_workingtree_metadata)
534
def _find_containing(self, evaluate):
535
"""Find something in a containing control directory.
537
This method will scan containing control dirs, until it finds what
538
it is looking for, decides that it will never find it, or runs out
539
of containing control directories to check.
541
It is used to implement find_repository and
542
determine_repository_policy.
544
:param evaluate: A function returning (value, stop). If stop is True,
545
the value will be returned.
549
result, stop = evaluate(found_bzrdir)
552
next_transport = found_bzrdir.root_transport.clone('..')
553
if (found_bzrdir.root_transport.base == next_transport.base):
554
# top of the file system
556
# find the next containing bzrdir
558
found_bzrdir = BzrDir.open_containing_from_transport(
560
except errors.NotBranchError:
334
563
def find_repository(self):
335
"""Find the repository that should be used for a_bzrdir.
564
"""Find the repository that should be used.
337
566
This does not require a branch as we use it to find the repo for
338
567
new branches as well as to hook existing branches up to their
342
return self.open_repository()
343
except errors.NoRepositoryPresent:
345
next_transport = self.root_transport.clone('..')
347
# find the next containing bzrdir
349
found_bzrdir = BzrDir.open_containing_from_transport(
351
except errors.NotBranchError:
353
raise errors.NoRepositoryPresent(self)
570
def usable_repository(found_bzrdir):
354
571
# does it have a repository ?
356
573
repository = found_bzrdir.open_repository()
357
574
except errors.NoRepositoryPresent:
358
next_transport = found_bzrdir.root_transport.clone('..')
359
if (found_bzrdir.root_transport.base == next_transport.base):
360
# top of the file system
364
if ((found_bzrdir.root_transport.base ==
365
self.root_transport.base) or repository.is_shared()):
576
if found_bzrdir.root_transport.base == self.root_transport.base:
577
return repository, True
578
elif repository.is_shared():
579
return repository, True
368
raise errors.NoRepositoryPresent(self)
369
raise errors.NoRepositoryPresent(self)
583
found_repo = self._find_containing(usable_repository)
584
if found_repo is None:
585
raise errors.NoRepositoryPresent(self)
588
def get_branch_reference(self):
589
"""Return the referenced URL for the branch in this bzrdir.
591
:raises NotBranchError: If there is no Branch.
592
:return: The URL the branch in this bzrdir references if it is a
593
reference branch, or None for regular branches.
371
597
def get_branch_transport(self, branch_format):
372
598
"""Get the transport for use by branch format in this BzrDir.
505
771
url = a_transport.base
508
format = BzrDirFormat.find_format(a_transport)
509
BzrDir._check_supported(format, False)
510
return format.open(a_transport), urlutils.unescape(a_transport.relpath(url))
774
result = BzrDir.open_from_transport(a_transport)
775
return result, urlutils.unescape(a_transport.relpath(url))
511
776
except errors.NotBranchError, e:
512
## mutter('not a branch in: %r %s', a_transport.base, e)
514
new_t = a_transport.clone('..')
779
new_t = a_transport.clone('..')
780
except errors.InvalidURLJoin:
781
# reached the root, whatever that may be
782
raise errors.NotBranchError(path=url)
515
783
if new_t.base == a_transport.base:
516
784
# reached the root, whatever that may be
517
785
raise errors.NotBranchError(path=url)
518
786
a_transport = new_t
788
def _get_tree_branch(self):
789
"""Return the branch and tree, if any, for this bzrdir.
791
Return None for tree if not present or inaccessible.
792
Raise NotBranchError if no branch is present.
793
:return: (tree, branch)
796
tree = self.open_workingtree()
797
except (errors.NoWorkingTree, errors.NotLocalUrl):
799
branch = self.open_branch()
805
def open_tree_or_branch(klass, location):
806
"""Return the branch and working tree at a location.
808
If there is no tree at the location, tree will be None.
809
If there is no branch at the location, an exception will be
811
:return: (tree, branch)
813
bzrdir = klass.open(location)
814
return bzrdir._get_tree_branch()
817
def open_containing_tree_or_branch(klass, location):
818
"""Return the branch and working tree contained by a location.
820
Returns (tree, branch, relpath).
821
If there is no tree at containing the location, tree will be None.
822
If there is no branch containing the location, an exception will be
824
relpath is the portion of the path that is contained by the branch.
826
bzrdir, relpath = klass.open_containing(location)
827
tree, branch = bzrdir._get_tree_branch()
828
return tree, branch, relpath
520
830
def open_repository(self, _unsupported=False):
521
831
"""Open the repository object at this BzrDir if one is present.
523
This will not follow the Branch object pointer - its strictly a direct
833
This will not follow the Branch object pointer - it's strictly a direct
524
834
open facility. Most client code should use open_branch().repository to
525
835
get at a repository.
527
_unsupported is a private parameter, not part of the api.
837
:param _unsupported: a private parameter, not part of the api.
528
838
TODO: static convenience version of this?
530
840
raise NotImplementedError(self.open_repository)
532
def open_workingtree(self, _unsupported=False):
842
def open_workingtree(self, _unsupported=False,
843
recommend_upgrade=True, from_branch=None):
533
844
"""Open the workingtree object at this BzrDir if one is present.
535
TODO: static convenience version of this?
846
:param recommend_upgrade: Optional keyword parameter, when True (the
847
default), emit through the ui module a recommendation that the user
848
upgrade the working tree when the workingtree being opened is old
849
(but still fully supported).
850
:param from_branch: override bzrdir branch (for lightweight checkouts)
537
852
raise NotImplementedError(self.open_workingtree)
1333
1893
return RepositoryFormat.get_default_format()
1335
1895
def __set_repository_format(self, value):
1336
"""Allow changint the repository format for metadir formats."""
1896
"""Allow changing the repository format for metadir formats."""
1337
1897
self._repository_format = value
1339
1899
repository_format = property(__return_repository_format, __set_repository_format)
1901
def __get_workingtree_format(self):
1902
if self._workingtree_format is None:
1903
from bzrlib.workingtree import WorkingTreeFormat
1904
self._workingtree_format = WorkingTreeFormat.get_default_format()
1905
return self._workingtree_format
1907
def __set_workingtree_format(self, wt_format):
1908
self._workingtree_format = wt_format
1910
workingtree_format = property(__get_workingtree_format,
1911
__set_workingtree_format)
1914
# Register bzr control format
1915
BzrDirFormat.register_control_format(BzrDirFormat)
1917
# Register bzr formats
1342
1918
BzrDirFormat.register_format(BzrDirFormat4())
1343
1919
BzrDirFormat.register_format(BzrDirFormat5())
1344
1920
BzrDirFormat.register_format(BzrDirFormat6())
1345
1921
__default_format = BzrDirMetaFormat1()
1346
1922
BzrDirFormat.register_format(__default_format)
1347
BzrDirFormat.set_default_format(__default_format)
1350
class BzrDirTestProviderAdapter(object):
1351
"""A tool to generate a suite testing multiple bzrdir formats at once.
1353
This is done by copying the test once for each transport and injecting
1354
the transport_server, transport_readonly_server, and bzrdir_format
1355
classes into each copy. Each copy is also given a new id() to make it
1359
def __init__(self, transport_server, transport_readonly_server, formats):
1360
self._transport_server = transport_server
1361
self._transport_readonly_server = transport_readonly_server
1362
self._formats = formats
1364
def adapt(self, test):
1365
result = TestSuite()
1366
for format in self._formats:
1367
new_test = deepcopy(test)
1368
new_test.transport_server = self._transport_server
1369
new_test.transport_readonly_server = self._transport_readonly_server
1370
new_test.bzrdir_format = format
1371
def make_new_test_id():
1372
new_id = "%s(%s)" % (new_test.id(), format.__class__.__name__)
1373
return lambda: new_id
1374
new_test.id = make_new_test_id()
1375
result.addTest(new_test)
1379
class ScratchDir(BzrDir6):
1380
"""Special test class: a bzrdir that cleans up itself..
1382
>>> d = ScratchDir()
1383
>>> base = d.transport.base
1386
>>> b.transport.__del__()
1391
def __init__(self, files=[], dirs=[], transport=None):
1392
"""Make a test branch.
1394
This creates a temporary directory and runs init-tree in it.
1396
If any files are listed, they are created in the working copy.
1398
if transport is None:
1399
transport = bzrlib.transport.local.ScratchTransport()
1400
# local import for scope restriction
1401
BzrDirFormat6().initialize(transport.base)
1402
super(ScratchDir, self).__init__(transport, BzrDirFormat6())
1403
self.create_repository()
1404
self.create_branch()
1405
self.create_workingtree()
1407
super(ScratchDir, self).__init__(transport, BzrDirFormat6())
1409
# BzrBranch creates a clone to .bzr and then forgets about the
1410
# original transport. A ScratchTransport() deletes itself and
1411
# everything underneath it when it goes away, so we need to
1412
# grab a local copy to prevent that from happening
1413
self._transport = transport
1416
self._transport.mkdir(d)
1419
self._transport.put(f, 'content of %s' % f)
1423
>>> orig = ScratchDir(files=["file1", "file2"])
1424
>>> os.listdir(orig.base)
1425
[u'.bzr', u'file1', u'file2']
1426
>>> clone = orig.clone()
1427
>>> if os.name != 'nt':
1428
... os.path.samefile(orig.base, clone.base)
1430
... orig.base == clone.base
1433
>>> os.listdir(clone.base)
1434
[u'.bzr', u'file1', u'file2']
1436
from shutil import copytree
1437
from bzrlib.osutils import mkdtemp
1440
copytree(self.base, base, symlinks=True)
1442
transport=bzrlib.transport.local.ScratchTransport(base))
1923
BzrDirFormat._default_format = __default_format
1445
1926
class Converter(object):
1797
2294
# we hard code the formats here because we are converting into
1798
2295
# the meta format. The meta format upgrader can take this to a
1799
2296
# future format within each component.
1800
self.put_format('repository', bzrlib.repository.RepositoryFormat7())
2297
self.put_format('repository', RepositoryFormat7())
1801
2298
for entry in repository_names:
1802
2299
self.move_entry('repository', entry)
1804
2301
self.step('Upgrading branch ')
1805
2302
self.bzrdir.transport.mkdir('branch', mode=self.dir_mode)
1806
2303
self.make_lock('branch')
1807
self.put_format('branch', bzrlib.branch.BzrBranchFormat5())
2304
self.put_format('branch', BzrBranchFormat5())
1808
2305
branch_files = [('revision-history', True),
1809
2306
('branch-name', True),
1810
2307
('parent', False)]
1811
2308
for entry in branch_files:
1812
2309
self.move_entry('branch', entry)
1814
self.step('Upgrading working tree')
1815
self.bzrdir.transport.mkdir('checkout', mode=self.dir_mode)
1816
self.make_lock('checkout')
1817
self.put_format('checkout', bzrlib.workingtree.WorkingTreeFormat3())
1818
self.bzrdir.transport.delete_multi(self.garbage_inventories, self.pb)
1819
2311
checkout_files = [('pending-merges', True),
1820
2312
('inventory', True),
1821
2313
('stat-cache', False)]
1822
for entry in checkout_files:
1823
self.move_entry('checkout', entry)
1824
if last_revision is not None:
1825
self.bzrdir._control_files.put_utf8('checkout/last-revision',
1827
self.bzrdir._control_files.put_utf8('branch-format', BzrDirMetaFormat1().get_format_string())
2314
# If a mandatory checkout file is not present, the branch does not have
2315
# a functional checkout. Do not create a checkout in the converted
2317
for name, mandatory in checkout_files:
2318
if mandatory and name not in bzrcontents:
2319
has_checkout = False
2323
if not has_checkout:
2324
self.pb.note('No working tree.')
2325
# If some checkout files are there, we may as well get rid of them.
2326
for name, mandatory in checkout_files:
2327
if name in bzrcontents:
2328
self.bzrdir.transport.delete(name)
2330
from bzrlib.workingtree import WorkingTreeFormat3
2331
self.step('Upgrading working tree')
2332
self.bzrdir.transport.mkdir('checkout', mode=self.dir_mode)
2333
self.make_lock('checkout')
2335
'checkout', WorkingTreeFormat3())
2336
self.bzrdir.transport.delete_multi(
2337
self.garbage_inventories, self.pb)
2338
for entry in checkout_files:
2339
self.move_entry('checkout', entry)
2340
if last_revision is not None:
2341
self.bzrdir._control_files.put_utf8(
2342
'checkout/last-revision', last_revision)
2343
self.bzrdir._control_files.put_utf8(
2344
'branch-format', BzrDirMetaFormat1().get_format_string())
1828
2345
return BzrDir.open(self.bzrdir.root_transport.base)
1830
2347
def make_lock(self, name):
1831
2348
"""Make a lock for the new control dir name."""
1832
2349
self.step('Make %s lock' % name)
1833
ld = LockDir(self.bzrdir.transport,
1835
file_modebits=self.file_mode,
1836
dir_modebits=self.dir_mode)
2350
ld = lockdir.LockDir(self.bzrdir.transport,
2352
file_modebits=self.file_mode,
2353
dir_modebits=self.dir_mode)
1839
2356
def move_entry(self, new_dir, entry):
1878
2395
self.pb.note('starting repository conversion')
1879
2396
converter = CopyConverter(self.target_format.repository_format)
1880
2397
converter.convert(repo, pb)
2399
branch = self.bzrdir.open_branch()
2400
except errors.NotBranchError:
2403
# TODO: conversions of Branch and Tree should be done by
2404
# InterXFormat lookups
2405
# Avoid circular imports
2406
from bzrlib import branch as _mod_branch
2407
if (branch._format.__class__ is _mod_branch.BzrBranchFormat5 and
2408
self.target_format.get_branch_format().__class__ is
2409
_mod_branch.BzrBranchFormat6):
2410
branch_converter = _mod_branch.Converter5to6()
2411
branch_converter.convert(branch)
2413
tree = self.bzrdir.open_workingtree(recommend_upgrade=False)
2414
except (errors.NoWorkingTree, errors.NotLocalUrl):
2417
# TODO: conversions of Branch and Tree should be done by
2418
# InterXFormat lookups
2419
if (isinstance(tree, workingtree.WorkingTree3) and
2420
not isinstance(tree, workingtree_4.WorkingTree4) and
2421
isinstance(self.target_format.workingtree_format,
2422
workingtree_4.WorkingTreeFormat4)):
2423
workingtree_4.Converter3to4().convert(tree)
1881
2424
return to_convert
2427
# This is not in remote.py because it's small, and needs to be registered.
2428
# Putting it in remote.py creates a circular import problem.
2429
# we can make it a lazy object if the control formats is turned into something
2431
class RemoteBzrDirFormat(BzrDirMetaFormat1):
2432
"""Format representing bzrdirs accessed via a smart server"""
2434
def get_format_description(self):
2435
return 'bzr remote bzrdir'
2438
def probe_transport(klass, transport):
2439
"""Return a RemoteBzrDirFormat object if it looks possible."""
2441
medium = transport.get_smart_medium()
2442
except (NotImplementedError, AttributeError,
2443
errors.TransportNotPossible, errors.NoSmartMedium):
2444
# no smart server, so not a branch for this format type.
2445
raise errors.NotBranchError(path=transport.base)
2447
# Decline to open it if the server doesn't support our required
2448
# version (2) so that the VFS-based transport will do it.
2450
server_version = medium.protocol_version()
2451
except errors.SmartProtocolError:
2452
# Apparently there's no usable smart server there, even though
2453
# the medium supports the smart protocol.
2454
raise errors.NotBranchError(path=transport.base)
2455
if server_version != 2:
2456
raise errors.NotBranchError(path=transport.base)
2459
def initialize_on_transport(self, transport):
2461
# hand off the request to the smart server
2462
client_medium = transport.get_smart_medium()
2463
except errors.NoSmartMedium:
2464
# TODO: lookup the local format from a server hint.
2465
local_dir_format = BzrDirMetaFormat1()
2466
return local_dir_format.initialize_on_transport(transport)
2467
client = _SmartClient(client_medium, transport.base)
2468
path = client.remote_path_from_transport(transport)
2469
response = client.call('BzrDirFormat.initialize', path)
2470
assert response[0] in ('ok', ), 'unexpected response code %s' % (response,)
2471
return remote.RemoteBzrDir(transport)
2473
def _open(self, transport):
2474
return remote.RemoteBzrDir(transport)
2476
def __eq__(self, other):
2477
if not isinstance(other, RemoteBzrDirFormat):
2479
return self.get_format_description() == other.get_format_description()
2482
BzrDirFormat.register_control_server_format(RemoteBzrDirFormat)
2485
class BzrDirFormatInfo(object):
2487
def __init__(self, native, deprecated, hidden, experimental):
2488
self.deprecated = deprecated
2489
self.native = native
2490
self.hidden = hidden
2491
self.experimental = experimental
2494
class BzrDirFormatRegistry(registry.Registry):
2495
"""Registry of user-selectable BzrDir subformats.
2497
Differs from BzrDirFormat._control_formats in that it provides sub-formats,
2498
e.g. BzrDirMeta1 with weave repository. Also, it's more user-oriented.
2502
"""Create a BzrDirFormatRegistry."""
2503
self._aliases = set()
2504
super(BzrDirFormatRegistry, self).__init__()
2507
"""Return a set of the format names which are aliases."""
2508
return frozenset(self._aliases)
2510
def register_metadir(self, key,
2511
repository_format, help, native=True, deprecated=False,
2517
"""Register a metadir subformat.
2519
These all use a BzrDirMetaFormat1 bzrdir, but can be parameterized
2520
by the Repository format.
2522
:param repository_format: The fully-qualified repository format class
2524
:param branch_format: Fully-qualified branch format class name as
2526
:param tree_format: Fully-qualified tree format class name as
2529
# This should be expanded to support setting WorkingTree and Branch
2530
# formats, once BzrDirMetaFormat1 supports that.
2531
def _load(full_name):
2532
mod_name, factory_name = full_name.rsplit('.', 1)
2534
mod = __import__(mod_name, globals(), locals(),
2536
except ImportError, e:
2537
raise ImportError('failed to load %s: %s' % (full_name, e))
2539
factory = getattr(mod, factory_name)
2540
except AttributeError:
2541
raise AttributeError('no factory %s in module %r'
2546
bd = BzrDirMetaFormat1()
2547
if branch_format is not None:
2548
bd.set_branch_format(_load(branch_format))
2549
if tree_format is not None:
2550
bd.workingtree_format = _load(tree_format)
2551
if repository_format is not None:
2552
bd.repository_format = _load(repository_format)
2554
self.register(key, helper, help, native, deprecated, hidden,
2555
experimental, alias)
2557
def register(self, key, factory, help, native=True, deprecated=False,
2558
hidden=False, experimental=False, alias=False):
2559
"""Register a BzrDirFormat factory.
2561
The factory must be a callable that takes one parameter: the key.
2562
It must produce an instance of the BzrDirFormat when called.
2564
This function mainly exists to prevent the info object from being
2567
registry.Registry.register(self, key, factory, help,
2568
BzrDirFormatInfo(native, deprecated, hidden, experimental))
2570
self._aliases.add(key)
2572
def register_lazy(self, key, module_name, member_name, help, native=True,
2573
deprecated=False, hidden=False, experimental=False, alias=False):
2574
registry.Registry.register_lazy(self, key, module_name, member_name,
2575
help, BzrDirFormatInfo(native, deprecated, hidden, experimental))
2577
self._aliases.add(key)
2579
def set_default(self, key):
2580
"""Set the 'default' key to be a clone of the supplied key.
2582
This method must be called once and only once.
2584
registry.Registry.register(self, 'default', self.get(key),
2585
self.get_help(key), info=self.get_info(key))
2586
self._aliases.add('default')
2588
def set_default_repository(self, key):
2589
"""Set the FormatRegistry default and Repository default.
2591
This is a transitional method while Repository.set_default_format
2594
if 'default' in self:
2595
self.remove('default')
2596
self.set_default(key)
2597
format = self.get('default')()
2598
assert isinstance(format, BzrDirMetaFormat1)
2600
def make_bzrdir(self, key):
2601
return self.get(key)()
2603
def help_topic(self, topic):
2604
output = textwrap.dedent("""\
2605
These formats can be used for creating branches, working trees, and
2609
default_realkey = None
2610
default_help = self.get_help('default')
2612
for key in self.keys():
2613
if key == 'default':
2615
help = self.get_help(key)
2616
if help == default_help:
2617
default_realkey = key
2619
help_pairs.append((key, help))
2621
def wrapped(key, help, info):
2623
help = '(native) ' + help
2624
return ':%s:\n%s\n\n' % (key,
2625
textwrap.fill(help, initial_indent=' ',
2626
subsequent_indent=' '))
2627
if default_realkey is not None:
2628
output += wrapped(default_realkey, '(default) %s' % default_help,
2629
self.get_info('default'))
2630
deprecated_pairs = []
2631
experimental_pairs = []
2632
for key, help in help_pairs:
2633
info = self.get_info(key)
2636
elif info.deprecated:
2637
deprecated_pairs.append((key, help))
2638
elif info.experimental:
2639
experimental_pairs.append((key, help))
2641
output += wrapped(key, help, info)
2642
if len(experimental_pairs) > 0:
2643
output += "Experimental formats are shown below.\n\n"
2644
for key, help in experimental_pairs:
2645
info = self.get_info(key)
2646
output += wrapped(key, help, info)
2647
if len(deprecated_pairs) > 0:
2648
output += "Deprecated formats are shown below.\n\n"
2649
for key, help in deprecated_pairs:
2650
info = self.get_info(key)
2651
output += wrapped(key, help, info)
2656
class RepositoryAcquisitionPolicy(object):
2657
"""Abstract base class for repository acquisition policies.
2659
A repository acquisition policy decides how a BzrDir acquires a repository
2660
for a branch that is being created. The most basic policy decision is
2661
whether to create a new repository or use an existing one.
2664
def configure_branch(self, branch):
2665
"""Apply any configuration data from this policy to the branch.
2667
Default implementation does nothing.
2671
def acquire_repository(self, make_working_trees=None, shared=False):
2672
"""Acquire a repository for this bzrdir.
2674
Implementations may create a new repository or use a pre-exising
2676
:param make_working_trees: If creating a repository, set
2677
make_working_trees to this value (if non-None)
2678
:param shared: If creating a repository, make it shared if True
2679
:return: A repository
2681
raise NotImplemented(RepositoryAcquisitionPolicy.acquire_repository)
2684
class CreateRepository(RepositoryAcquisitionPolicy):
2685
"""A policy of creating a new repository"""
2687
def __init__(self, bzrdir):
2688
RepositoryAcquisitionPolicy.__init__(self)
2689
self._bzrdir = bzrdir
2691
def acquire_repository(self, make_working_trees=None, shared=False):
2692
"""Implementation of RepositoryAcquisitionPolicy.acquire_repository
2694
Creates the desired repository in the bzrdir we already have.
2696
repository = self._bzrdir.create_repository(shared=shared)
2697
if make_working_trees is not None:
2698
repository.set_make_working_trees(make_working_trees)
2702
class UseExistingRepository(RepositoryAcquisitionPolicy):
2703
"""A policy of reusing an existing repository"""
2705
def __init__(self, repository):
2706
RepositoryAcquisitionPolicy.__init__(self)
2707
self._repository = repository
2709
def acquire_repository(self, make_working_trees=None, shared=False):
2710
"""Implementation of RepositoryAcquisitionPolicy.acquire_repository
2712
Returns an existing repository to use
2714
return self._repository
2717
format_registry = BzrDirFormatRegistry()
2718
format_registry.register('weave', BzrDirFormat6,
2719
'Pre-0.8 format. Slower than knit and does not'
2720
' support checkouts or shared repositories.',
2722
format_registry.register_metadir('knit',
2723
'bzrlib.repofmt.knitrepo.RepositoryFormatKnit1',
2724
'Format using knits. Recommended for interoperation with bzr <= 0.14.',
2725
branch_format='bzrlib.branch.BzrBranchFormat5',
2726
tree_format='bzrlib.workingtree.WorkingTreeFormat3')
2727
format_registry.register_metadir('metaweave',
2728
'bzrlib.repofmt.weaverepo.RepositoryFormat7',
2729
'Transitional format in 0.8. Slower than knit.',
2730
branch_format='bzrlib.branch.BzrBranchFormat5',
2731
tree_format='bzrlib.workingtree.WorkingTreeFormat3',
2733
format_registry.register_metadir('dirstate',
2734
'bzrlib.repofmt.knitrepo.RepositoryFormatKnit1',
2735
help='New in 0.15: Fast local operations. Compatible with bzr 0.8 and '
2736
'above when accessed over the network.',
2737
branch_format='bzrlib.branch.BzrBranchFormat5',
2738
# this uses bzrlib.workingtree.WorkingTreeFormat4 because importing
2739
# directly from workingtree_4 triggers a circular import.
2740
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
2742
format_registry.register_metadir('dirstate-tags',
2743
'bzrlib.repofmt.knitrepo.RepositoryFormatKnit1',
2744
help='New in 0.15: Fast local operations and improved scaling for '
2745
'network operations. Additionally adds support for tags.'
2746
' Incompatible with bzr < 0.15.',
2747
branch_format='bzrlib.branch.BzrBranchFormat6',
2748
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
2750
format_registry.register_metadir('rich-root',
2751
'bzrlib.repofmt.knitrepo.RepositoryFormatKnit4',
2752
help='New in 1.0. Better handling of tree roots. Incompatible with'
2754
branch_format='bzrlib.branch.BzrBranchFormat6',
2755
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
2757
format_registry.register_metadir('dirstate-with-subtree',
2758
'bzrlib.repofmt.knitrepo.RepositoryFormatKnit3',
2759
help='New in 0.15: Fast local operations and improved scaling for '
2760
'network operations. Additionally adds support for versioning nested '
2761
'bzr branches. Incompatible with bzr < 0.15.',
2762
branch_format='bzrlib.branch.BzrBranchFormat6',
2763
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
2767
format_registry.register_metadir('pack-0.92',
2768
'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack1',
2769
help='New in 0.92: Pack-based format with data compatible with '
2770
'dirstate-tags format repositories. Interoperates with '
2771
'bzr repositories before 0.92 but cannot be read by bzr < 0.92. '
2772
'Previously called knitpack-experimental. '
2773
'For more information, see '
2774
'http://doc.bazaar-vcs.org/latest/developers/packrepo.html.',
2775
branch_format='bzrlib.branch.BzrBranchFormat6',
2776
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
2778
format_registry.register_metadir('pack-0.92-subtree',
2779
'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack3',
2780
help='New in 0.92: Pack-based format with data compatible with '
2781
'dirstate-with-subtree format repositories. Interoperates with '
2782
'bzr repositories before 0.92 but cannot be read by bzr < 0.92. '
2783
'Previously called knitpack-experimental. '
2784
'For more information, see '
2785
'http://doc.bazaar-vcs.org/latest/developers/packrepo.html.',
2786
branch_format='bzrlib.branch.BzrBranchFormat6',
2787
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
2791
format_registry.register_metadir('rich-root-pack',
2792
'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack4',
2793
help='New in 1.0: Pack-based format with data compatible with '
2794
'rich-root format repositories. Incompatible with'
2796
branch_format='bzrlib.branch.BzrBranchFormat6',
2797
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
2799
# The following two formats should always just be aliases.
2800
format_registry.register_metadir('development',
2801
'bzrlib.repofmt.pack_repo.RepositoryFormatPackDevelopment0',
2802
help='Current development format. Can convert data to and from pack-0.92 '
2803
'(and anything compatible with pack-0.92) format repositories. '
2804
'Repositories in this format can only be read by bzr.dev. '
2806
'http://doc.bazaar-vcs.org/latest/developers/development-repo.html '
2808
branch_format='bzrlib.branch.BzrBranchFormat6',
2809
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
2813
format_registry.register_metadir('development-subtree',
2814
'bzrlib.repofmt.pack_repo.RepositoryFormatPackDevelopment0Subtree',
2815
help='Current development format, subtree variant. Can convert data to and '
2816
'from pack-0.92 (and anything compatible with pack-0.92) format '
2817
'repositories. Repositories in this format can only be read by '
2818
'bzr.dev. Please read '
2819
'http://doc.bazaar-vcs.org/latest/developers/development-repo.html '
2821
branch_format='bzrlib.branch.BzrBranchFormat6',
2822
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
2826
# And the development formats which the will have aliased one of follow:
2827
format_registry.register_metadir('development0',
2828
'bzrlib.repofmt.pack_repo.RepositoryFormatPackDevelopment0',
2829
help='Trivial rename of pack-0.92 to provide a development format. '
2831
'http://doc.bazaar-vcs.org/latest/developers/development-repo.html '
2833
branch_format='bzrlib.branch.BzrBranchFormat6',
2834
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
2838
format_registry.register_metadir('development0-subtree',
2839
'bzrlib.repofmt.pack_repo.RepositoryFormatPackDevelopment0Subtree',
2840
help='Trivial rename of pack-0.92-subtree to provide a development format. '
2842
'http://doc.bazaar-vcs.org/latest/developers/development-repo.html '
2844
branch_format='bzrlib.branch.BzrBranchFormat6',
2845
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
2849
format_registry.set_default('pack-0.92')