84
108
"""Return true if this bzrdir is one whose format we can convert from."""
111
def check_conversion_target(self, target_format):
112
target_repo_format = target_format.repository_format
113
source_repo_format = self._format.repository_format
114
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.
117
def _check_supported(format, allow_unsupported,
118
recommend_upgrade=True,
120
"""Give an error or warning on old formats.
122
:param format: may be any kind of format - workingtree, branch,
125
:param allow_unsupported: If true, allow opening
126
formats that are strongly deprecated, and which may
127
have limited functionality.
129
:param recommend_upgrade: If true (default), warn
130
the user through the ui object that they may wish
131
to upgrade the object.
133
# TODO: perhaps move this into a base Format class; it's not BzrDir
134
# specific. mbp 20070323
93
135
if not allow_unsupported and not format.is_supported():
94
136
# 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'])
137
raise errors.UnsupportedFormatError(format=format)
138
if recommend_upgrade \
139
and getattr(format, 'upgrade_recommended', False):
140
ui.ui_factory.recommend_upgrade(
141
format.get_format_description(),
101
def clone(self, url, revision_id=None, basis=None, force_new_repo=False):
144
def clone(self, url, revision_id=None, force_new_repo=False):
102
145
"""Clone this bzrdir and its contents to url verbatim.
104
147
If urls last component does not exist, it will be created.
147
198
except errors.NotBranchError:
150
self.open_workingtree().clone(result, basis=basis_tree)
201
self.open_workingtree().clone(result)
151
202
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
206
# TODO: This should be given a Transport, and should chdir up; otherwise
177
207
# this will open a new connection.
178
208
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:
209
t = get_transport(url)
187
212
# TODO: Should take a Transport
189
def create(cls, base):
214
def create(cls, base, format=None):
190
215
"""Create a new BzrDir at the url 'base'.
192
217
This will call the current default formats initialize with base
193
218
as the only parameter.
195
If you need a specific format, consider creating an instance
196
of that and calling initialize().
220
:param format: If supplied, the format of branch to create. If not
221
supplied, the default is used.
198
223
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))
224
raise AssertionError("BzrDir.create always creates the default"
225
" format, not one of %r" % cls)
226
t = get_transport(base)
229
format = BzrDirFormat.get_default_format()
230
return format.initialize(safe_unicode(base))
210
232
def create_branch(self):
211
233
"""Create a branch in this BzrDir.
455
526
_unsupported is a private parameter to the BzrDir class.
457
528
t = get_transport(base)
458
mutter("trying to open %r with transport %r", base, t)
459
format = BzrDirFormat.find_format(t)
529
return BzrDir.open_from_transport(t, _unsupported=_unsupported)
532
def open_from_transport(transport, _unsupported=False,
533
_server_formats=True):
534
"""Open a bzrdir within a particular directory.
536
:param transport: Transport containing the bzrdir.
537
:param _unsupported: private.
539
base = transport.base
541
def find_format(transport):
542
return transport, BzrDirFormat.find_format(
543
transport, _server_formats=_server_formats)
545
def redirected(transport, e, redirection_notice):
546
qualified_source = e.get_source_url()
547
relpath = transport.relpath(qualified_source)
548
if not e.target.endswith(relpath):
549
# Not redirected to a branch-format, not a branch
550
raise errors.NotBranchError(path=e.target)
551
target = e.target[:-len(relpath)]
552
note('%s is%s redirected to %s',
553
transport.base, e.permanently, target)
554
# Let's try with a new transport
555
qualified_target = e.get_target_url()[:-len(relpath)]
556
# FIXME: If 'transport' has a qualifier, this should
557
# be applied again to the new transport *iff* the
558
# schemes used are the same. It's a bit tricky to
559
# verify, so I'll punt for now
561
return get_transport(target)
564
transport, format = do_catching_redirections(find_format,
567
except errors.TooManyRedirections:
568
raise errors.NotBranchError(base)
460
570
BzrDir._check_supported(format, _unsupported)
461
return format.open(t, _found=True)
571
return format.open(transport, _found=True)
463
573
def open_branch(self, unsupported=False):
464
574
"""Open the branch object at this BzrDir if one is present.
553
689
workingtree and discards it, and that's somewhat expensive.)
556
self.open_workingtree()
692
self.open_workingtree(recommend_upgrade=False)
558
694
except errors.NoWorkingTree:
561
def sprout(self, url, revision_id=None, basis=None, force_new_repo=False):
697
def _cloning_metadir(self):
698
"""Produce a metadir suitable for cloning with"""
699
result_format = self._format.__class__()
702
branch = self.open_branch()
703
source_repository = branch.repository
704
except errors.NotBranchError:
706
source_repository = self.open_repository()
707
except errors.NoRepositoryPresent:
708
source_repository = None
710
# XXX TODO: This isinstance is here because we have not implemented
711
# the fix recommended in bug # 103195 - to delegate this choice the
713
repo_format = source_repository._format
714
if not isinstance(repo_format, remote.RemoteRepositoryFormat):
715
result_format.repository_format = repo_format
717
# TODO: Couldn't we just probe for the format in these cases,
718
# rather than opening the whole tree? It would be a little
719
# faster. mbp 20070401
720
tree = self.open_workingtree(recommend_upgrade=False)
721
except (errors.NoWorkingTree, errors.NotLocalUrl):
722
result_format.workingtree_format = None
724
result_format.workingtree_format = tree._format.__class__()
725
return result_format, source_repository
727
def cloning_metadir(self):
728
"""Produce a metadir suitable for cloning or sprouting with.
730
These operations may produce workingtrees (yes, even though they're
731
"cloning" something that doesn't have a tree, so a viable workingtree
732
format must be selected.
734
format, repository = self._cloning_metadir()
735
if format._workingtree_format is None:
736
if repository is None:
738
tree_format = repository._format._matchingbzrdir.workingtree_format
739
format.workingtree_format = tree_format.__class__()
742
def checkout_metadir(self):
743
return self.cloning_metadir()
745
def sprout(self, url, revision_id=None, force_new_repo=False,
562
747
"""Create a copy of this bzrdir prepared for use as a new line of
1277
1672
repository_format = property(__return_repository_format, __set_repository_format)
1674
def __get_workingtree_format(self):
1675
if self._workingtree_format is None:
1676
from bzrlib.workingtree import WorkingTreeFormat
1677
self._workingtree_format = WorkingTreeFormat.get_default_format()
1678
return self._workingtree_format
1680
def __set_workingtree_format(self, wt_format):
1681
self._workingtree_format = wt_format
1683
workingtree_format = property(__get_workingtree_format,
1684
__set_workingtree_format)
1687
# Register bzr control format
1688
BzrDirFormat.register_control_format(BzrDirFormat)
1690
# Register bzr formats
1280
1691
BzrDirFormat.register_format(BzrDirFormat4())
1281
1692
BzrDirFormat.register_format(BzrDirFormat5())
1282
1693
BzrDirFormat.register_format(BzrDirFormat6())
1283
1694
__default_format = BzrDirMetaFormat1()
1284
1695
BzrDirFormat.register_format(__default_format)
1285
BzrDirFormat.set_default_format(__default_format)
1288
class BzrDirTestProviderAdapter(object):
1289
"""A tool to generate a suite testing multiple bzrdir formats at once.
1291
This is done by copying the test once for each transport and injecting
1292
the transport_server, transport_readonly_server, and bzrdir_format
1293
classes into each copy. Each copy is also given a new id() to make it
1297
def __init__(self, transport_server, transport_readonly_server, formats):
1298
self._transport_server = transport_server
1299
self._transport_readonly_server = transport_readonly_server
1300
self._formats = formats
1302
def adapt(self, test):
1303
result = TestSuite()
1304
for format in self._formats:
1305
new_test = deepcopy(test)
1306
new_test.transport_server = self._transport_server
1307
new_test.transport_readonly_server = self._transport_readonly_server
1308
new_test.bzrdir_format = format
1309
def make_new_test_id():
1310
new_id = "%s(%s)" % (new_test.id(), format.__class__.__name__)
1311
return lambda: new_id
1312
new_test.id = make_new_test_id()
1313
result.addTest(new_test)
1317
class ScratchDir(BzrDir6):
1318
"""Special test class: a bzrdir that cleans up itself..
1320
>>> d = ScratchDir()
1321
>>> base = d.transport.base
1324
>>> b.transport.__del__()
1329
def __init__(self, files=[], dirs=[], transport=None):
1330
"""Make a test branch.
1332
This creates a temporary directory and runs init-tree in it.
1334
If any files are listed, they are created in the working copy.
1336
if transport is None:
1337
transport = bzrlib.transport.local.ScratchTransport()
1338
# local import for scope restriction
1339
BzrDirFormat6().initialize(transport.base)
1340
super(ScratchDir, self).__init__(transport, BzrDirFormat6())
1341
self.create_repository()
1342
self.create_branch()
1343
self.create_workingtree()
1345
super(ScratchDir, self).__init__(transport, BzrDirFormat6())
1347
# BzrBranch creates a clone to .bzr and then forgets about the
1348
# original transport. A ScratchTransport() deletes itself and
1349
# everything underneath it when it goes away, so we need to
1350
# grab a local copy to prevent that from happening
1351
self._transport = transport
1354
self._transport.mkdir(d)
1357
self._transport.put(f, 'content of %s' % f)
1361
>>> orig = ScratchDir(files=["file1", "file2"])
1362
>>> os.listdir(orig.base)
1363
[u'.bzr', u'file1', u'file2']
1364
>>> clone = orig.clone()
1365
>>> if os.name != 'nt':
1366
... os.path.samefile(orig.base, clone.base)
1368
... orig.base == clone.base
1371
>>> os.listdir(clone.base)
1372
[u'.bzr', u'file1', u'file2']
1374
from shutil import copytree
1375
from bzrlib.osutils import mkdtemp
1378
copytree(self.base, base, symlinks=True)
1380
transport=bzrlib.transport.local.ScratchTransport(base))
1696
BzrDirFormat._default_format = __default_format
1383
1699
class Converter(object):
1735
2054
# we hard code the formats here because we are converting into
1736
2055
# the meta format. The meta format upgrader can take this to a
1737
2056
# future format within each component.
1738
self.put_format('repository', bzrlib.repository.RepositoryFormat7())
2057
self.put_format('repository', RepositoryFormat7())
1739
2058
for entry in repository_names:
1740
2059
self.move_entry('repository', entry)
1742
2061
self.step('Upgrading branch ')
1743
2062
self.bzrdir.transport.mkdir('branch', mode=self.dir_mode)
1744
2063
self.make_lock('branch')
1745
self.put_format('branch', bzrlib.branch.BzrBranchFormat5())
2064
self.put_format('branch', BzrBranchFormat5())
1746
2065
branch_files = [('revision-history', True),
1747
2066
('branch-name', True),
1748
2067
('parent', False)]
1749
2068
for entry in branch_files:
1750
2069
self.move_entry('branch', entry)
1752
self.step('Upgrading working tree')
1753
self.bzrdir.transport.mkdir('checkout', mode=self.dir_mode)
1754
self.make_lock('checkout')
1755
self.put_format('checkout', bzrlib.workingtree.WorkingTreeFormat3())
1756
self.bzrdir.transport.delete_multi(self.garbage_inventories, self.pb)
1757
2071
checkout_files = [('pending-merges', True),
1758
2072
('inventory', True),
1759
2073
('stat-cache', False)]
1760
for entry in checkout_files:
1761
self.move_entry('checkout', entry)
1762
if last_revision is not None:
1763
self.bzrdir._control_files.put_utf8('checkout/last-revision',
1765
self.bzrdir._control_files.put_utf8('branch-format', BzrDirMetaFormat1().get_format_string())
2074
# If a mandatory checkout file is not present, the branch does not have
2075
# a functional checkout. Do not create a checkout in the converted
2077
for name, mandatory in checkout_files:
2078
if mandatory and name not in bzrcontents:
2079
has_checkout = False
2083
if not has_checkout:
2084
self.pb.note('No working tree.')
2085
# If some checkout files are there, we may as well get rid of them.
2086
for name, mandatory in checkout_files:
2087
if name in bzrcontents:
2088
self.bzrdir.transport.delete(name)
2090
from bzrlib.workingtree import WorkingTreeFormat3
2091
self.step('Upgrading working tree')
2092
self.bzrdir.transport.mkdir('checkout', mode=self.dir_mode)
2093
self.make_lock('checkout')
2095
'checkout', WorkingTreeFormat3())
2096
self.bzrdir.transport.delete_multi(
2097
self.garbage_inventories, self.pb)
2098
for entry in checkout_files:
2099
self.move_entry('checkout', entry)
2100
if last_revision is not None:
2101
self.bzrdir._control_files.put_utf8(
2102
'checkout/last-revision', last_revision)
2103
self.bzrdir._control_files.put_utf8(
2104
'branch-format', BzrDirMetaFormat1().get_format_string())
1766
2105
return BzrDir.open(self.bzrdir.root_transport.base)
1768
2107
def make_lock(self, name):
1769
2108
"""Make a lock for the new control dir name."""
1770
2109
self.step('Make %s lock' % name)
1771
ld = LockDir(self.bzrdir.transport,
1773
file_modebits=self.file_mode,
1774
dir_modebits=self.dir_mode)
2110
ld = lockdir.LockDir(self.bzrdir.transport,
2112
file_modebits=self.file_mode,
2113
dir_modebits=self.dir_mode)
1777
2116
def move_entry(self, new_dir, entry):
1816
2155
self.pb.note('starting repository conversion')
1817
2156
converter = CopyConverter(self.target_format.repository_format)
1818
2157
converter.convert(repo, pb)
2159
branch = self.bzrdir.open_branch()
2160
except errors.NotBranchError:
2163
# TODO: conversions of Branch and Tree should be done by
2164
# InterXFormat lookups
2165
# Avoid circular imports
2166
from bzrlib import branch as _mod_branch
2167
if (branch._format.__class__ is _mod_branch.BzrBranchFormat5 and
2168
self.target_format.get_branch_format().__class__ is
2169
_mod_branch.BzrBranchFormat6):
2170
branch_converter = _mod_branch.Converter5to6()
2171
branch_converter.convert(branch)
2173
tree = self.bzrdir.open_workingtree(recommend_upgrade=False)
2174
except (errors.NoWorkingTree, errors.NotLocalUrl):
2177
# TODO: conversions of Branch and Tree should be done by
2178
# InterXFormat lookups
2179
if (isinstance(tree, workingtree.WorkingTree3) and
2180
not isinstance(tree, workingtree_4.WorkingTree4) and
2181
isinstance(self.target_format.workingtree_format,
2182
workingtree_4.WorkingTreeFormat4)):
2183
workingtree_4.Converter3to4().convert(tree)
1819
2184
return to_convert
2187
# This is not in remote.py because it's small, and needs to be registered.
2188
# Putting it in remote.py creates a circular import problem.
2189
# we can make it a lazy object if the control formats is turned into something
2191
class RemoteBzrDirFormat(BzrDirMetaFormat1):
2192
"""Format representing bzrdirs accessed via a smart server"""
2194
def get_format_description(self):
2195
return 'bzr remote bzrdir'
2198
def probe_transport(klass, transport):
2199
"""Return a RemoteBzrDirFormat object if it looks possible."""
2201
client = transport.get_smart_client()
2202
except (NotImplementedError, AttributeError,
2203
errors.TransportNotPossible):
2204
# no smart server, so not a branch for this format type.
2205
raise errors.NotBranchError(path=transport.base)
2207
# Send a 'hello' request in protocol version one, and decline to
2208
# open it if the server doesn't support our required version (2) so
2209
# that the VFS-based transport will do it.
2210
request = client.get_request()
2211
smart_protocol = protocol.SmartClientRequestProtocolOne(request)
2212
server_version = smart_protocol.query_version()
2213
if server_version != 2:
2214
raise errors.NotBranchError(path=transport.base)
2217
def initialize_on_transport(self, transport):
2219
# hand off the request to the smart server
2220
medium = transport.get_smart_medium()
2221
except errors.NoSmartMedium:
2222
# TODO: lookup the local format from a server hint.
2223
local_dir_format = BzrDirMetaFormat1()
2224
return local_dir_format.initialize_on_transport(transport)
2225
client = _SmartClient(medium)
2226
path = client.remote_path_from_transport(transport)
2227
response = _SmartClient(medium).call('BzrDirFormat.initialize', path)
2228
assert response[0] in ('ok', ), 'unexpected response code %s' % (response,)
2229
return remote.RemoteBzrDir(transport)
2231
def _open(self, transport):
2232
return remote.RemoteBzrDir(transport)
2234
def __eq__(self, other):
2235
if not isinstance(other, RemoteBzrDirFormat):
2237
return self.get_format_description() == other.get_format_description()
2240
BzrDirFormat.register_control_server_format(RemoteBzrDirFormat)
2243
class BzrDirFormatInfo(object):
2245
def __init__(self, native, deprecated, hidden):
2246
self.deprecated = deprecated
2247
self.native = native
2248
self.hidden = hidden
2251
class BzrDirFormatRegistry(registry.Registry):
2252
"""Registry of user-selectable BzrDir subformats.
2254
Differs from BzrDirFormat._control_formats in that it provides sub-formats,
2255
e.g. BzrDirMeta1 with weave repository. Also, it's more user-oriented.
2258
def register_metadir(self, key,
2259
repository_format, help, native=True, deprecated=False,
2263
"""Register a metadir subformat.
2265
These all use a BzrDirMetaFormat1 bzrdir, but can be parameterized
2266
by the Repository format.
2268
:param repository_format: The fully-qualified repository format class
2270
:param branch_format: Fully-qualified branch format class name as
2272
:param tree_format: Fully-qualified tree format class name as
2275
# This should be expanded to support setting WorkingTree and Branch
2276
# formats, once BzrDirMetaFormat1 supports that.
2277
def _load(full_name):
2278
mod_name, factory_name = full_name.rsplit('.', 1)
2280
mod = __import__(mod_name, globals(), locals(),
2282
except ImportError, e:
2283
raise ImportError('failed to load %s: %s' % (full_name, e))
2285
factory = getattr(mod, factory_name)
2286
except AttributeError:
2287
raise AttributeError('no factory %s in module %r'
2292
bd = BzrDirMetaFormat1()
2293
if branch_format is not None:
2294
bd.set_branch_format(_load(branch_format))
2295
if tree_format is not None:
2296
bd.workingtree_format = _load(tree_format)
2297
if repository_format is not None:
2298
bd.repository_format = _load(repository_format)
2300
self.register(key, helper, help, native, deprecated, hidden)
2302
def register(self, key, factory, help, native=True, deprecated=False,
2304
"""Register a BzrDirFormat factory.
2306
The factory must be a callable that takes one parameter: the key.
2307
It must produce an instance of the BzrDirFormat when called.
2309
This function mainly exists to prevent the info object from being
2312
registry.Registry.register(self, key, factory, help,
2313
BzrDirFormatInfo(native, deprecated, hidden))
2315
def register_lazy(self, key, module_name, member_name, help, native=True,
2316
deprecated=False, hidden=False):
2317
registry.Registry.register_lazy(self, key, module_name, member_name,
2318
help, BzrDirFormatInfo(native, deprecated, hidden))
2320
def set_default(self, key):
2321
"""Set the 'default' key to be a clone of the supplied key.
2323
This method must be called once and only once.
2325
registry.Registry.register(self, 'default', self.get(key),
2326
self.get_help(key), info=self.get_info(key))
2328
def set_default_repository(self, key):
2329
"""Set the FormatRegistry default and Repository default.
2331
This is a transitional method while Repository.set_default_format
2334
if 'default' in self:
2335
self.remove('default')
2336
self.set_default(key)
2337
format = self.get('default')()
2338
assert isinstance(format, BzrDirMetaFormat1)
2340
def make_bzrdir(self, key):
2341
return self.get(key)()
2343
def help_topic(self, topic):
2344
output = textwrap.dedent("""\
2345
Bazaar directory formats
2346
------------------------
2348
These formats can be used for creating branches, working trees, and
2352
default_help = self.get_help('default')
2354
for key in self.keys():
2355
if key == 'default':
2357
help = self.get_help(key)
2358
if help == default_help:
2359
default_realkey = key
2361
help_pairs.append((key, help))
2363
def wrapped(key, help, info):
2365
help = '(native) ' + help
2366
return ' %s:\n%s\n\n' % (key,
2367
textwrap.fill(help, initial_indent=' ',
2368
subsequent_indent=' '))
2369
output += wrapped('%s/default' % default_realkey, default_help,
2370
self.get_info('default'))
2371
deprecated_pairs = []
2372
for key, help in help_pairs:
2373
info = self.get_info(key)
2376
elif info.deprecated:
2377
deprecated_pairs.append((key, help))
2379
output += wrapped(key, help, info)
2380
if len(deprecated_pairs) > 0:
2381
output += "Deprecated formats\n------------------\n\n"
2382
for key, help in deprecated_pairs:
2383
info = self.get_info(key)
2384
output += wrapped(key, help, info)
2389
format_registry = BzrDirFormatRegistry()
2390
format_registry.register('weave', BzrDirFormat6,
2391
'Pre-0.8 format. Slower than knit and does not'
2392
' support checkouts or shared repositories.',
2394
format_registry.register_metadir('knit',
2395
'bzrlib.repofmt.knitrepo.RepositoryFormatKnit1',
2396
'Format using knits. Recommended for interoperation with bzr <= 0.14.',
2397
branch_format='bzrlib.branch.BzrBranchFormat5',
2398
tree_format='bzrlib.workingtree.WorkingTreeFormat3')
2399
format_registry.register_metadir('metaweave',
2400
'bzrlib.repofmt.weaverepo.RepositoryFormat7',
2401
'Transitional format in 0.8. Slower than knit.',
2402
branch_format='bzrlib.branch.BzrBranchFormat5',
2403
tree_format='bzrlib.workingtree.WorkingTreeFormat3',
2405
format_registry.register_metadir('dirstate',
2406
'bzrlib.repofmt.knitrepo.RepositoryFormatKnit1',
2407
help='New in 0.15: Fast local operations. Compatible with bzr 0.8 and '
2408
'above when accessed over the network.',
2409
branch_format='bzrlib.branch.BzrBranchFormat5',
2410
# this uses bzrlib.workingtree.WorkingTreeFormat4 because importing
2411
# directly from workingtree_4 triggers a circular import.
2412
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
2414
format_registry.register_metadir('dirstate-tags',
2415
'bzrlib.repofmt.knitrepo.RepositoryFormatKnit1',
2416
help='New in 0.15: Fast local operations and improved scaling for '
2417
'network operations. Additionally adds support for tags.'
2418
' Incompatible with bzr < 0.15.',
2419
branch_format='bzrlib.branch.BzrBranchFormat6',
2420
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
2422
format_registry.register_metadir('dirstate-with-subtree',
2423
'bzrlib.repofmt.knitrepo.RepositoryFormatKnit3',
2424
help='New in 0.15: Fast local operations and improved scaling for '
2425
'network operations. Additionally adds support for versioning nested '
2426
'bzr branches. Incompatible with bzr < 0.15.',
2427
branch_format='bzrlib.branch.BzrBranchFormat6',
2428
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
2431
format_registry.set_default('dirstate')