84
111
"""Return true if this bzrdir is one whose format we can convert from."""
114
def check_conversion_target(self, target_format):
115
target_repo_format = target_format.repository_format
116
source_repo_format = self._format.repository_format
117
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.
120
def _check_supported(format, allow_unsupported,
121
recommend_upgrade=True,
123
"""Give an error or warning on old formats.
125
:param format: may be any kind of format - workingtree, branch,
128
:param allow_unsupported: If true, allow opening
129
formats that are strongly deprecated, and which may
130
have limited functionality.
132
:param recommend_upgrade: If true (default), warn
133
the user through the ui object that they may wish
134
to upgrade the object.
136
# TODO: perhaps move this into a base Format class; it's not BzrDir
137
# specific. mbp 20070323
93
138
if not allow_unsupported and not format.is_supported():
94
139
# 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'])
140
raise errors.UnsupportedFormatError(format=format)
141
if recommend_upgrade \
142
and getattr(format, 'upgrade_recommended', False):
143
ui.ui_factory.recommend_upgrade(
144
format.get_format_description(),
101
def clone(self, url, revision_id=None, basis=None, force_new_repo=False):
147
def clone(self, url, revision_id=None, force_new_repo=False):
102
148
"""Clone this bzrdir and its contents to url verbatim.
104
150
If urls last component does not exist, it will be created.
462
524
_unsupported is a private parameter to the BzrDir class.
464
526
t = get_transport(base)
465
mutter("trying to open %r with transport %r", base, t)
466
format = BzrDirFormat.find_format(t)
527
return BzrDir.open_from_transport(t, _unsupported=_unsupported)
530
def open_from_transport(transport, _unsupported=False,
531
_server_formats=True):
532
"""Open a bzrdir within a particular directory.
534
:param transport: Transport containing the bzrdir.
535
:param _unsupported: private.
537
base = transport.base
539
def find_format(transport):
540
return transport, BzrDirFormat.find_format(
541
transport, _server_formats=_server_formats)
543
def redirected(transport, e, redirection_notice):
544
qualified_source = e.get_source_url()
545
relpath = transport.relpath(qualified_source)
546
if not e.target.endswith(relpath):
547
# Not redirected to a branch-format, not a branch
548
raise errors.NotBranchError(path=e.target)
549
target = e.target[:-len(relpath)]
550
note('%s is%s redirected to %s',
551
transport.base, e.permanently, target)
552
# Let's try with a new transport
553
qualified_target = e.get_target_url()[:-len(relpath)]
554
# FIXME: If 'transport' has a qualifier, this should
555
# be applied again to the new transport *iff* the
556
# schemes used are the same. It's a bit tricky to
557
# verify, so I'll punt for now
559
return get_transport(target)
562
transport, format = do_catching_redirections(find_format,
565
except errors.TooManyRedirections:
566
raise errors.NotBranchError(base)
467
568
BzrDir._check_supported(format, _unsupported)
468
return format.open(t, _found=True)
569
return format.open(transport, _found=True)
470
571
def open_branch(self, unsupported=False):
471
572
"""Open the branch object at this BzrDir if one is present.
560
687
workingtree and discards it, and that's somewhat expensive.)
563
self.open_workingtree()
690
self.open_workingtree(recommend_upgrade=False)
565
692
except errors.NoWorkingTree:
568
def sprout(self, url, revision_id=None, basis=None, force_new_repo=False):
695
def _cloning_metadir(self):
696
"""Produce a metadir suitable for cloning with"""
697
result_format = self._format.__class__()
700
branch = self.open_branch()
701
source_repository = branch.repository
702
except errors.NotBranchError:
704
source_repository = self.open_repository()
705
except errors.NoRepositoryPresent:
706
source_repository = None
708
# XXX TODO: This isinstance is here because we have not implemented
709
# the fix recommended in bug # 103195 - to delegate this choice the
711
repo_format = source_repository._format
712
if not isinstance(repo_format, remote.RemoteRepositoryFormat):
713
result_format.repository_format = repo_format
715
# TODO: Couldn't we just probe for the format in these cases,
716
# rather than opening the whole tree? It would be a little
717
# faster. mbp 20070401
718
tree = self.open_workingtree(recommend_upgrade=False)
719
except (errors.NoWorkingTree, errors.NotLocalUrl):
720
result_format.workingtree_format = None
722
result_format.workingtree_format = tree._format.__class__()
723
return result_format, source_repository
725
def cloning_metadir(self):
726
"""Produce a metadir suitable for cloning or sprouting with.
728
These operations may produce workingtrees (yes, even though they're
729
"cloning" something that doesn't have a tree, so a viable workingtree
730
format must be selected.
732
format, repository = self._cloning_metadir()
733
if format._workingtree_format is None:
734
if repository is None:
736
tree_format = repository._format._matchingbzrdir.workingtree_format
737
format.workingtree_format = tree_format.__class__()
740
def checkout_metadir(self):
741
return self.cloning_metadir()
743
def sprout(self, url, revision_id=None, force_new_repo=False,
569
745
"""Create a copy of this bzrdir prepared for use as a new line of
1797
2088
# we hard code the formats here because we are converting into
1798
2089
# the meta format. The meta format upgrader can take this to a
1799
2090
# future format within each component.
1800
self.put_format('repository', bzrlib.repository.RepositoryFormat7())
2091
self.put_format('repository', RepositoryFormat7())
1801
2092
for entry in repository_names:
1802
2093
self.move_entry('repository', entry)
1804
2095
self.step('Upgrading branch ')
1805
2096
self.bzrdir.transport.mkdir('branch', mode=self.dir_mode)
1806
2097
self.make_lock('branch')
1807
self.put_format('branch', bzrlib.branch.BzrBranchFormat5())
2098
self.put_format('branch', BzrBranchFormat5())
1808
2099
branch_files = [('revision-history', True),
1809
2100
('branch-name', True),
1810
2101
('parent', False)]
1811
2102
for entry in branch_files:
1812
2103
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
2105
checkout_files = [('pending-merges', True),
1820
2106
('inventory', True),
1821
2107
('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())
2108
# If a mandatory checkout file is not present, the branch does not have
2109
# a functional checkout. Do not create a checkout in the converted
2111
for name, mandatory in checkout_files:
2112
if mandatory and name not in bzrcontents:
2113
has_checkout = False
2117
if not has_checkout:
2118
self.pb.note('No working tree.')
2119
# If some checkout files are there, we may as well get rid of them.
2120
for name, mandatory in checkout_files:
2121
if name in bzrcontents:
2122
self.bzrdir.transport.delete(name)
2124
from bzrlib.workingtree import WorkingTreeFormat3
2125
self.step('Upgrading working tree')
2126
self.bzrdir.transport.mkdir('checkout', mode=self.dir_mode)
2127
self.make_lock('checkout')
2129
'checkout', WorkingTreeFormat3())
2130
self.bzrdir.transport.delete_multi(
2131
self.garbage_inventories, self.pb)
2132
for entry in checkout_files:
2133
self.move_entry('checkout', entry)
2134
if last_revision is not None:
2135
self.bzrdir._control_files.put_utf8(
2136
'checkout/last-revision', last_revision)
2137
self.bzrdir._control_files.put_utf8(
2138
'branch-format', BzrDirMetaFormat1().get_format_string())
1828
2139
return BzrDir.open(self.bzrdir.root_transport.base)
1830
2141
def make_lock(self, name):
1831
2142
"""Make a lock for the new control dir name."""
1832
2143
self.step('Make %s lock' % name)
1833
ld = LockDir(self.bzrdir.transport,
1835
file_modebits=self.file_mode,
1836
dir_modebits=self.dir_mode)
2144
ld = lockdir.LockDir(self.bzrdir.transport,
2146
file_modebits=self.file_mode,
2147
dir_modebits=self.dir_mode)
1839
2150
def move_entry(self, new_dir, entry):
1878
2189
self.pb.note('starting repository conversion')
1879
2190
converter = CopyConverter(self.target_format.repository_format)
1880
2191
converter.convert(repo, pb)
2193
branch = self.bzrdir.open_branch()
2194
except errors.NotBranchError:
2197
# TODO: conversions of Branch and Tree should be done by
2198
# InterXFormat lookups
2199
# Avoid circular imports
2200
from bzrlib import branch as _mod_branch
2201
if (branch._format.__class__ is _mod_branch.BzrBranchFormat5 and
2202
self.target_format.get_branch_format().__class__ is
2203
_mod_branch.BzrBranchFormat6):
2204
branch_converter = _mod_branch.Converter5to6()
2205
branch_converter.convert(branch)
2207
tree = self.bzrdir.open_workingtree(recommend_upgrade=False)
2208
except (errors.NoWorkingTree, errors.NotLocalUrl):
2211
# TODO: conversions of Branch and Tree should be done by
2212
# InterXFormat lookups
2213
if (isinstance(tree, workingtree.WorkingTree3) and
2214
not isinstance(tree, workingtree_4.WorkingTree4) and
2215
isinstance(self.target_format.workingtree_format,
2216
workingtree_4.WorkingTreeFormat4)):
2217
workingtree_4.Converter3to4().convert(tree)
1881
2218
return to_convert
2221
# This is not in remote.py because it's small, and needs to be registered.
2222
# Putting it in remote.py creates a circular import problem.
2223
# we can make it a lazy object if the control formats is turned into something
2225
class RemoteBzrDirFormat(BzrDirMetaFormat1):
2226
"""Format representing bzrdirs accessed via a smart server"""
2228
def get_format_description(self):
2229
return 'bzr remote bzrdir'
2232
def probe_transport(klass, transport):
2233
"""Return a RemoteBzrDirFormat object if it looks possible."""
2235
transport.get_smart_client()
2236
except (NotImplementedError, AttributeError,
2237
errors.TransportNotPossible):
2238
# no smart server, so not a branch for this format type.
2239
raise errors.NotBranchError(path=transport.base)
2243
def initialize_on_transport(self, transport):
2245
# hand off the request to the smart server
2246
medium = transport.get_smart_medium()
2247
except errors.NoSmartMedium:
2248
# TODO: lookup the local format from a server hint.
2249
local_dir_format = BzrDirMetaFormat1()
2250
return local_dir_format.initialize_on_transport(transport)
2251
client = _SmartClient(medium)
2252
path = client.remote_path_from_transport(transport)
2253
response = _SmartClient(medium).call('BzrDirFormat.initialize', path)
2254
assert response[0] in ('ok', ), 'unexpected response code %s' % (response,)
2255
return remote.RemoteBzrDir(transport)
2257
def _open(self, transport):
2258
return remote.RemoteBzrDir(transport)
2260
def __eq__(self, other):
2261
if not isinstance(other, RemoteBzrDirFormat):
2263
return self.get_format_description() == other.get_format_description()
2266
BzrDirFormat.register_control_server_format(RemoteBzrDirFormat)
2269
class BzrDirFormatInfo(object):
2271
def __init__(self, native, deprecated, hidden):
2272
self.deprecated = deprecated
2273
self.native = native
2274
self.hidden = hidden
2277
class BzrDirFormatRegistry(registry.Registry):
2278
"""Registry of user-selectable BzrDir subformats.
2280
Differs from BzrDirFormat._control_formats in that it provides sub-formats,
2281
e.g. BzrDirMeta1 with weave repository. Also, it's more user-oriented.
2284
def register_metadir(self, key,
2285
repository_format, help, native=True, deprecated=False,
2289
"""Register a metadir subformat.
2291
These all use a BzrDirMetaFormat1 bzrdir, but can be parameterized
2292
by the Repository format.
2294
:param repository_format: The fully-qualified repository format class
2296
:param branch_format: Fully-qualified branch format class name as
2298
:param tree_format: Fully-qualified tree format class name as
2301
# This should be expanded to support setting WorkingTree and Branch
2302
# formats, once BzrDirMetaFormat1 supports that.
2303
def _load(full_name):
2304
mod_name, factory_name = full_name.rsplit('.', 1)
2306
mod = __import__(mod_name, globals(), locals(),
2308
except ImportError, e:
2309
raise ImportError('failed to load %s: %s' % (full_name, e))
2311
factory = getattr(mod, factory_name)
2312
except AttributeError:
2313
raise AttributeError('no factory %s in module %r'
2318
bd = BzrDirMetaFormat1()
2319
if branch_format is not None:
2320
bd.set_branch_format(_load(branch_format))
2321
if tree_format is not None:
2322
bd.workingtree_format = _load(tree_format)
2323
if repository_format is not None:
2324
bd.repository_format = _load(repository_format)
2326
self.register(key, helper, help, native, deprecated, hidden)
2328
def register(self, key, factory, help, native=True, deprecated=False,
2330
"""Register a BzrDirFormat factory.
2332
The factory must be a callable that takes one parameter: the key.
2333
It must produce an instance of the BzrDirFormat when called.
2335
This function mainly exists to prevent the info object from being
2338
registry.Registry.register(self, key, factory, help,
2339
BzrDirFormatInfo(native, deprecated, hidden))
2341
def register_lazy(self, key, module_name, member_name, help, native=True,
2342
deprecated=False, hidden=False):
2343
registry.Registry.register_lazy(self, key, module_name, member_name,
2344
help, BzrDirFormatInfo(native, deprecated, hidden))
2346
def set_default(self, key):
2347
"""Set the 'default' key to be a clone of the supplied key.
2349
This method must be called once and only once.
2351
registry.Registry.register(self, 'default', self.get(key),
2352
self.get_help(key), info=self.get_info(key))
2354
def set_default_repository(self, key):
2355
"""Set the FormatRegistry default and Repository default.
2357
This is a transitional method while Repository.set_default_format
2360
if 'default' in self:
2361
self.remove('default')
2362
self.set_default(key)
2363
format = self.get('default')()
2364
assert isinstance(format, BzrDirMetaFormat1)
2366
def make_bzrdir(self, key):
2367
return self.get(key)()
2369
def help_topic(self, topic):
2370
output = textwrap.dedent("""\
2371
Bazaar directory formats
2372
------------------------
2374
These formats can be used for creating branches, working trees, and
2378
default_help = self.get_help('default')
2380
for key in self.keys():
2381
if key == 'default':
2383
help = self.get_help(key)
2384
if help == default_help:
2385
default_realkey = key
2387
help_pairs.append((key, help))
2389
def wrapped(key, help, info):
2391
help = '(native) ' + help
2392
return ' %s:\n%s\n\n' % (key,
2393
textwrap.fill(help, initial_indent=' ',
2394
subsequent_indent=' '))
2395
output += wrapped('%s/default' % default_realkey, default_help,
2396
self.get_info('default'))
2397
deprecated_pairs = []
2398
for key, help in help_pairs:
2399
info = self.get_info(key)
2402
elif info.deprecated:
2403
deprecated_pairs.append((key, help))
2405
output += wrapped(key, help, info)
2406
if len(deprecated_pairs) > 0:
2407
output += "Deprecated formats\n------------------\n\n"
2408
for key, help in deprecated_pairs:
2409
info = self.get_info(key)
2410
output += wrapped(key, help, info)
2415
format_registry = BzrDirFormatRegistry()
2416
format_registry.register('weave', BzrDirFormat6,
2417
'Pre-0.8 format. Slower than knit and does not'
2418
' support checkouts or shared repositories.',
2420
format_registry.register_metadir('knit',
2421
'bzrlib.repofmt.knitrepo.RepositoryFormatKnit1',
2422
'Format using knits. Recommended for interoperation with bzr <= 0.14.',
2423
branch_format='bzrlib.branch.BzrBranchFormat5',
2424
tree_format='bzrlib.workingtree.WorkingTreeFormat3')
2425
format_registry.register_metadir('metaweave',
2426
'bzrlib.repofmt.weaverepo.RepositoryFormat7',
2427
'Transitional format in 0.8. Slower than knit.',
2428
branch_format='bzrlib.branch.BzrBranchFormat5',
2429
tree_format='bzrlib.workingtree.WorkingTreeFormat3',
2431
format_registry.register_metadir('dirstate',
2432
'bzrlib.repofmt.knitrepo.RepositoryFormatKnit1',
2433
help='New in 0.15: Fast local operations. Compatible with bzr 0.8 and '
2434
'above when accessed over the network.',
2435
branch_format='bzrlib.branch.BzrBranchFormat5',
2436
# this uses bzrlib.workingtree.WorkingTreeFormat4 because importing
2437
# directly from workingtree_4 triggers a circular import.
2438
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
2440
format_registry.register_metadir('dirstate-tags',
2441
'bzrlib.repofmt.knitrepo.RepositoryFormatKnit1',
2442
help='New in 0.15: Fast local operations and improved scaling for '
2443
'network operations. Additionally adds support for tags.'
2444
' Incompatible with bzr < 0.15.',
2445
branch_format='bzrlib.branch.BzrBranchFormat6',
2446
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
2448
format_registry.register_metadir('dirstate-with-subtree',
2449
'bzrlib.repofmt.knitrepo.RepositoryFormatKnit3',
2450
help='New in 0.15: Fast local operations and improved scaling for '
2451
'network operations. Additionally adds support for versioning nested '
2452
'bzr branches. Incompatible with bzr < 0.15.',
2453
branch_format='bzrlib.branch.BzrBranchFormat6',
2454
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
2457
format_registry.set_default('dirstate')