Merge lp:~jelmer/bzr/lazy-bzrdir into lp:bzr

Proposed by Jelmer Vernooij
Status: Superseded
Proposed branch: lp:~jelmer/bzr/lazy-bzrdir
Merge into: lp:bzr
Diff against target: 1625 lines (+489/-429)
11 files modified
bzrlib/bzrdir.py (+36/-267)
bzrlib/controldir.py (+14/-12)
bzrlib/remote.py (+267/-32)
bzrlib/tests/blackbox/test_upgrade.py (+4/-2)
bzrlib/tests/per_controldir/test_controldir.py (+9/-11)
bzrlib/tests/test_bzrdir.py (+10/-73)
bzrlib/tests/test_controldir.py (+103/-0)
bzrlib/tests/test_foreign.py (+4/-3)
bzrlib/tests/test_import_tariff.py (+1/-0)
bzrlib/tests/test_remote.py (+30/-29)
doc/en/release-notes/bzr-2.4.txt (+11/-0)
To merge this branch: bzr merge lp:~jelmer/bzr/lazy-bzrdir
Reviewer Review Type Date Requested Status
Vincent Ladeuil Needs Fixing
Review via email: mp+52844@code.launchpad.net

This proposal has been superseded by a proposal from 2011-03-11.

Description of the change

Make it possible to lazily register BzrDir and ControlDir formats.

This is another prerequisite for the weave_fmt plugin branch. It also allows foreign formats to do more lazy loading - currently they always have to import their ControlDirFormat subclass at
startup time to register it.

Does the way in which this allows unregistration of lazy control dir formats look reasonable?
I realize using:

list.remove(_ObjectGetter(obj))

and relying on the __eq__ implementation in _ObjectGetter is a bit weird, but I can't think of a better alternative. Better ideas welcome :)

To post a comment you must log in.
Revision history for this message
John A Meinel (jameinel) wrote :

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On 03/10/2011 02:30 PM, Jelmer Vernooij wrote:
> Jelmer Vernooij has proposed merging lp:~jelmer/bzr/lazy-bzrdir into lp:bzr.
>
> Requested reviews:
> bzr-core (bzr-core)
>
> For more details, see:
> https://code.launchpad.net/~jelmer/bzr/lazy-bzrdir/+merge/52844
>
> Make it possible to lazily register BzrDir and ControlDir formats.
>
> This is another prerequisite for the weave_fmt plugin branch. It also allows foreign formats to do more lazy loading - currently they always have to import their ControlDirFormat subclass at
> startup time to register it.
>
> Does the way in which this allows unregistration of lazy control dir formats look reasonable?
> I realize using:
>
> list.remove(_ObjectGetter(obj))
>
> and relying on the __eq__ implementation in _ObjectGetter is a bit weird, but I can't think of a better alternative. Better ideas welcome :)

I don't think we want a separate unregister_lazy_format, because at some
point, the format won't be lazy anymore. I'd rather have the
registration take some sort of 'key' that it can then use.

I'm guessing the regular "register_format" actually uses some attribute
of the format to determine if it is what it wants. Why not pass that in
to the "register_lazy_format" so that:

1) unregistering is more straightforward
2) we could skip loading it entirely if it doesn't match the key, even
if we are probing and think it 'might' fit.

John
=:->

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.10 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iEYEARECAAYFAk141V8ACgkQJdeBCYSNAAPuaQCgyY8q8owLfo+QyDKrjZjm7diD
rqkAoJpbD9no3Ij7C2p483gVPWBVud1u
=cznf
-----END PGP SIGNATURE-----

Revision history for this message
Jelmer Vernooij (jelmer) wrote :

On Thu, 2011-03-10 at 13:55 +0000, John A Meinel wrote:
> On 03/10/2011 02:30 PM, Jelmer Vernooij wrote:
> > Jelmer Vernooij has proposed merging lp:~jelmer/bzr/lazy-bzrdir into lp:bzr.
> >
> > Requested reviews:
> > bzr-core (bzr-core)
> >
> > For more details, see:
> > https://code.launchpad.net/~jelmer/bzr/lazy-bzrdir/+merge/52844
> >
> > Make it possible to lazily register BzrDir and ControlDir formats.
> >
> > This is another prerequisite for the weave_fmt plugin branch. It also allows foreign formats to do more lazy loading - currently they always have to import their ControlDirFormat subclass at
> > startup time to register it.
> >
> > Does the way in which this allows unregistration of lazy control dir formats look reasonable?
> > I realize using:
> >
> > list.remove(_ObjectGetter(obj))
> >
> > and relying on the __eq__ implementation in _ObjectGetter is a bit weird, but I can't think of a better alternative. Better ideas welcome :)
>
> I don't think we want a separate unregister_lazy_format, because at some
> point, the format won't be lazy anymore. I'd rather have the
> registration take some sort of 'key' that it can then use.
>
> I'm guessing the regular "register_format" actually uses some attribute
> of the format to determine if it is what it wants. Why not pass that in
> to the "register_lazy_format" so that:
Thanks, that makes more sense indeed. I've updated the branch, will resubmit.

> 1) unregistering is more straightforward
> 2) we could skip loading it entirely if it doesn't match the key, even
> if we are probing and think it 'might' fit.
The regular register_format() also just works with ControlDirFormat
objects, not necessarily ones with a format string (hg, git, etc don't
have one).

That said, BzrDir.register_lazy_format() / BzrDir.register_format() can
just always pass in format.get_format_string() and foreign formats can
just specify an arbitrary string that's not used anywhere else.

Cheers,

Jelmer

Revision history for this message
Vincent Ladeuil (vila) wrote :

As discussed on IRC, this looks simpler and I like it better.

To summarize:

- add comments about using a set() for known_formats() and a couple of basic tests (using a set() also means we lose the registration order. I don't think there are cases where it should matter but it still good to test/document it explicitly,

- since you'll update bzr-{svn|hg|git}, I think more than 90% users of the previous API are covered, but there will still be users with installations where the old plugins will try (and fail) to use the old API in a newer bzr. They should at least get an meaningful error message telling them to upgrade.

With these tweaks in place, I'm ok for you to land it, but you may want to summarize the issues on the ml or get a second review.

review: Needs Fixing
Revision history for this message
Jelmer Vernooij (jelmer) wrote :

On Fri, 2011-03-11 at 07:35 +0000, Vincent Ladeuil wrote:
> The proposal to merge lp:~jelmer/bzr/lazy-bzrdir into lp:bzr has been updated.
>
> Status: Needs review => Approved
>
> For more details, see:
> https://code.launchpad.net/~jelmer/bzr/lazy-bzrdir/+merge/52844
I'll probably ask for another review. It turns out that the control dir
tests weren't being run against RemoteBzrDirFormat previously, and now
that they are there are a few test failures. I'm not entirely sure my
fixes are correct.

Cheers,

Jelmer

Revision history for this message
Vincent Ladeuil (vila) wrote :

> It turns out that the control dir tests weren't being run against RemoteBzrDirFormat previously, and now that they are there are a few test failures.

:-/

Marking as wip then.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'bzrlib/bzrdir.py'
2--- bzrlib/bzrdir.py 2011-03-08 17:40:26 +0000
3+++ bzrlib/bzrdir.py 2011-03-11 14:21:26 +0000
4@@ -59,7 +59,6 @@
5 xml5,
6 )
7 from bzrlib.repofmt import pack_repo
8-from bzrlib.smart.client import _SmartClient
9 from bzrlib.store.versioned import VersionedFileStore
10 from bzrlib.transactions import WriteTransaction
11 from bzrlib.transport import (
12@@ -80,6 +79,7 @@
13
14 from bzrlib import (
15 hooks,
16+ registry,
17 )
18 from bzrlib.symbol_versioning import (
19 deprecated_in,
20@@ -1473,16 +1473,18 @@
21 class BzrProber(controldir.Prober):
22 """Prober for formats that use a .bzr/ control directory."""
23
24- _formats = {}
25+ formats = registry.FormatRegistry(controldir.network_format_registry)
26 """The known .bzr formats."""
27
28 @classmethod
29+ @deprecated_method(deprecated_in((2, 4, 0)))
30 def register_bzrdir_format(klass, format):
31- klass._formats[format.get_format_string()] = format
32+ klass.formats.register(format.get_format_string(), format)
33
34 @classmethod
35+ @deprecated_method(deprecated_in((2, 4, 0)))
36 def unregister_bzrdir_format(klass, format):
37- del klass._formats[format.get_format_string()]
38+ klass.formats.remove(format.get_format_string())
39
40 @classmethod
41 def probe_transport(klass, transport):
42@@ -1492,10 +1494,17 @@
43 except errors.NoSuchFile:
44 raise errors.NotBranchError(path=transport.base)
45 try:
46- return klass._formats[format_string]
47+ return klass.formats.get(format_string)
48 except KeyError:
49 raise errors.UnknownFormatError(format=format_string, kind='bzrdir')
50
51+ @classmethod
52+ def known_formats(cls):
53+ result = set()
54+ for name, format in cls.formats.iteritems():
55+ result.add(format)
56+ return result
57+
58
59 controldir.ControlDirFormat.register_prober(BzrProber)
60
61@@ -1525,8 +1534,14 @@
62 raise errors.NotBranchError(path=transport.base)
63 if server_version != '2':
64 raise errors.NotBranchError(path=transport.base)
65+ from bzrlib.remote import RemoteBzrDirFormat
66 return RemoteBzrDirFormat()
67
68+ @classmethod
69+ def known_formats(cls):
70+ from bzrlib.remote import RemoteBzrDirFormat
71+ return set([RemoteBzrDirFormat()])
72+
73
74 class BzrDirFormat(controldir.ControlDirFormat):
75 """ControlDirFormat base class for .bzr/ directories.
76@@ -1545,7 +1560,8 @@
77 # _lock_class must be set in subclasses to the lock type, typ.
78 # TransportLock or LockDir
79
80- def get_format_string(self):
81+ @classmethod
82+ def get_format_string(cls):
83 """Return the ASCII format string that identifies this format."""
84 raise NotImplementedError(self.get_format_string)
85
86@@ -1563,6 +1579,7 @@
87 # metadir1
88 if type(self) != BzrDirMetaFormat1:
89 return self._initialize_on_transport_vfs(transport)
90+ from bzrlib.remote import RemoteBzrDirFormat
91 remote_format = RemoteBzrDirFormat()
92 self._supply_sub_formats_to(remote_format)
93 return remote_format.initialize_on_transport(transport)
94@@ -1606,6 +1623,7 @@
95 except errors.NoSmartMedium:
96 pass
97 else:
98+ from bzrlib.remote import RemoteBzrDirFormat
99 # TODO: lookup the local format from a server hint.
100 remote_dir_format = RemoteBzrDirFormat()
101 remote_dir_format._network_name = self.network_name()
102@@ -1726,13 +1744,6 @@
103 """
104 raise NotImplementedError(self._open)
105
106- @classmethod
107- def register_format(klass, format):
108- BzrProber.register_bzrdir_format(format)
109- # bzr native formats have a network name of their format string.
110- controldir.network_format_registry.register(format.get_format_string(), format.__class__)
111- controldir.ControlDirFormat.register_format(format)
112-
113 def _supply_sub_formats_to(self, other_format):
114 """Give other_format the same values for sub formats as this has.
115
116@@ -1745,12 +1756,6 @@
117 :return: None.
118 """
119
120- @classmethod
121- def unregister_format(klass, format):
122- BzrProber.unregister_bzrdir_format(format)
123- controldir.ControlDirFormat.unregister_format(format)
124- controldir.network_format_registry.remove(format.get_format_string())
125-
126
127 class BzrDirFormat4(BzrDirFormat):
128 """Bzr dir format 4.
129@@ -1769,7 +1774,8 @@
130
131 fixed_components = True
132
133- def get_format_string(self):
134+ @classmethod
135+ def get_format_string(cls):
136 """See BzrDirFormat.get_format_string()."""
137 return "Bazaar-NG branch, format 0.0.4\n"
138
139@@ -1849,7 +1855,8 @@
140
141 _lock_class = lockable_files.TransportLock
142
143- def get_format_string(self):
144+ @classmethod
145+ def get_format_string(cls):
146 """See BzrDirFormat.get_format_string()."""
147 return "Bazaar-NG branch, format 5\n"
148
149@@ -1910,7 +1917,8 @@
150
151 _lock_class = lockable_files.TransportLock
152
153- def get_format_string(self):
154+ @classmethod
155+ def get_format_string(cls):
156 """See BzrDirFormat.get_format_string()."""
157 return "Bazaar-NG branch, format 6\n"
158
159@@ -2102,7 +2110,8 @@
160 raise NotImplementedError(self.get_converter)
161 return ConvertMetaToMeta(format)
162
163- def get_format_string(self):
164+ @classmethod
165+ def get_format_string(cls):
166 """See BzrDirFormat.get_format_string()."""
167 return "Bazaar-NG meta directory, format 1\n"
168
169@@ -2170,11 +2179,11 @@
170
171
172 # Register bzr formats
173-BzrDirFormat.register_format(BzrDirFormat4())
174-BzrDirFormat.register_format(BzrDirFormat5())
175-BzrDirFormat.register_format(BzrDirFormat6())
176+BzrProber.formats.register(BzrDirFormat4.get_format_string(), BzrDirFormat4())
177+BzrProber.formats.register(BzrDirFormat5.get_format_string(), BzrDirFormat5())
178+BzrProber.formats.register(BzrDirFormat6.get_format_string(), BzrDirFormat6())
179 __default_format = BzrDirMetaFormat1()
180-BzrDirFormat.register_format(__default_format)
181+BzrProber.formats.register(__default_format.get_format_string(), __default_format)
182 controldir.ControlDirFormat._default_format = __default_format
183
184
185@@ -2695,246 +2704,6 @@
186 return to_convert
187
188
189-# This is not in remote.py because it's relatively small, and needs to be
190-# registered. Putting it in remote.py creates a circular import problem.
191-# we can make it a lazy object if the control formats is turned into something
192-# like a registry.
193-class RemoteBzrDirFormat(BzrDirMetaFormat1):
194- """Format representing bzrdirs accessed via a smart server"""
195-
196- supports_workingtrees = False
197-
198- def __init__(self):
199- BzrDirMetaFormat1.__init__(self)
200- # XXX: It's a bit ugly that the network name is here, because we'd
201- # like to believe that format objects are stateless or at least
202- # immutable, However, we do at least avoid mutating the name after
203- # it's returned. See <https://bugs.launchpad.net/bzr/+bug/504102>
204- self._network_name = None
205-
206- def __repr__(self):
207- return "%s(_network_name=%r)" % (self.__class__.__name__,
208- self._network_name)
209-
210- def get_format_description(self):
211- if self._network_name:
212- real_format = controldir.network_format_registry.get(self._network_name)
213- return 'Remote: ' + real_format.get_format_description()
214- return 'bzr remote bzrdir'
215-
216- def get_format_string(self):
217- raise NotImplementedError(self.get_format_string)
218-
219- def network_name(self):
220- if self._network_name:
221- return self._network_name
222- else:
223- raise AssertionError("No network name set.")
224-
225- def initialize_on_transport(self, transport):
226- try:
227- # hand off the request to the smart server
228- client_medium = transport.get_smart_medium()
229- except errors.NoSmartMedium:
230- # TODO: lookup the local format from a server hint.
231- local_dir_format = BzrDirMetaFormat1()
232- return local_dir_format.initialize_on_transport(transport)
233- client = _SmartClient(client_medium)
234- path = client.remote_path_from_transport(transport)
235- try:
236- response = client.call('BzrDirFormat.initialize', path)
237- except errors.ErrorFromSmartServer, err:
238- remote._translate_error(err, path=path)
239- if response[0] != 'ok':
240- raise errors.SmartProtocolError('unexpected response code %s' % (response,))
241- format = RemoteBzrDirFormat()
242- self._supply_sub_formats_to(format)
243- return remote.RemoteBzrDir(transport, format)
244-
245- def parse_NoneTrueFalse(self, arg):
246- if not arg:
247- return None
248- if arg == 'False':
249- return False
250- if arg == 'True':
251- return True
252- raise AssertionError("invalid arg %r" % arg)
253-
254- def _serialize_NoneTrueFalse(self, arg):
255- if arg is False:
256- return 'False'
257- if arg:
258- return 'True'
259- return ''
260-
261- def _serialize_NoneString(self, arg):
262- return arg or ''
263-
264- def initialize_on_transport_ex(self, transport, use_existing_dir=False,
265- create_prefix=False, force_new_repo=False, stacked_on=None,
266- stack_on_pwd=None, repo_format_name=None, make_working_trees=None,
267- shared_repo=False):
268- try:
269- # hand off the request to the smart server
270- client_medium = transport.get_smart_medium()
271- except errors.NoSmartMedium:
272- do_vfs = True
273- else:
274- # Decline to open it if the server doesn't support our required
275- # version (3) so that the VFS-based transport will do it.
276- if client_medium.should_probe():
277- try:
278- server_version = client_medium.protocol_version()
279- if server_version != '2':
280- do_vfs = True
281- else:
282- do_vfs = False
283- except errors.SmartProtocolError:
284- # Apparently there's no usable smart server there, even though
285- # the medium supports the smart protocol.
286- do_vfs = True
287- else:
288- do_vfs = False
289- if not do_vfs:
290- client = _SmartClient(client_medium)
291- path = client.remote_path_from_transport(transport)
292- if client_medium._is_remote_before((1, 16)):
293- do_vfs = True
294- if do_vfs:
295- # TODO: lookup the local format from a server hint.
296- local_dir_format = BzrDirMetaFormat1()
297- self._supply_sub_formats_to(local_dir_format)
298- return local_dir_format.initialize_on_transport_ex(transport,
299- use_existing_dir=use_existing_dir, create_prefix=create_prefix,
300- force_new_repo=force_new_repo, stacked_on=stacked_on,
301- stack_on_pwd=stack_on_pwd, repo_format_name=repo_format_name,
302- make_working_trees=make_working_trees, shared_repo=shared_repo,
303- vfs_only=True)
304- return self._initialize_on_transport_ex_rpc(client, path, transport,
305- use_existing_dir, create_prefix, force_new_repo, stacked_on,
306- stack_on_pwd, repo_format_name, make_working_trees, shared_repo)
307-
308- def _initialize_on_transport_ex_rpc(self, client, path, transport,
309- use_existing_dir, create_prefix, force_new_repo, stacked_on,
310- stack_on_pwd, repo_format_name, make_working_trees, shared_repo):
311- args = []
312- args.append(self._serialize_NoneTrueFalse(use_existing_dir))
313- args.append(self._serialize_NoneTrueFalse(create_prefix))
314- args.append(self._serialize_NoneTrueFalse(force_new_repo))
315- args.append(self._serialize_NoneString(stacked_on))
316- # stack_on_pwd is often/usually our transport
317- if stack_on_pwd:
318- try:
319- stack_on_pwd = transport.relpath(stack_on_pwd)
320- if not stack_on_pwd:
321- stack_on_pwd = '.'
322- except errors.PathNotChild:
323- pass
324- args.append(self._serialize_NoneString(stack_on_pwd))
325- args.append(self._serialize_NoneString(repo_format_name))
326- args.append(self._serialize_NoneTrueFalse(make_working_trees))
327- args.append(self._serialize_NoneTrueFalse(shared_repo))
328- request_network_name = self._network_name or \
329- BzrDirFormat.get_default_format().network_name()
330- try:
331- response = client.call('BzrDirFormat.initialize_ex_1.16',
332- request_network_name, path, *args)
333- except errors.UnknownSmartMethod:
334- client._medium._remember_remote_is_before((1,16))
335- local_dir_format = BzrDirMetaFormat1()
336- self._supply_sub_formats_to(local_dir_format)
337- return local_dir_format.initialize_on_transport_ex(transport,
338- use_existing_dir=use_existing_dir, create_prefix=create_prefix,
339- force_new_repo=force_new_repo, stacked_on=stacked_on,
340- stack_on_pwd=stack_on_pwd, repo_format_name=repo_format_name,
341- make_working_trees=make_working_trees, shared_repo=shared_repo,
342- vfs_only=True)
343- except errors.ErrorFromSmartServer, err:
344- remote._translate_error(err, path=path)
345- repo_path = response[0]
346- bzrdir_name = response[6]
347- require_stacking = response[7]
348- require_stacking = self.parse_NoneTrueFalse(require_stacking)
349- format = RemoteBzrDirFormat()
350- format._network_name = bzrdir_name
351- self._supply_sub_formats_to(format)
352- bzrdir = remote.RemoteBzrDir(transport, format, _client=client)
353- if repo_path:
354- repo_format = remote.response_tuple_to_repo_format(response[1:])
355- if repo_path == '.':
356- repo_path = ''
357- if repo_path:
358- repo_bzrdir_format = RemoteBzrDirFormat()
359- repo_bzrdir_format._network_name = response[5]
360- repo_bzr = remote.RemoteBzrDir(transport.clone(repo_path),
361- repo_bzrdir_format)
362- else:
363- repo_bzr = bzrdir
364- final_stack = response[8] or None
365- final_stack_pwd = response[9] or None
366- if final_stack_pwd:
367- final_stack_pwd = urlutils.join(
368- transport.base, final_stack_pwd)
369- remote_repo = remote.RemoteRepository(repo_bzr, repo_format)
370- if len(response) > 10:
371- # Updated server verb that locks remotely.
372- repo_lock_token = response[10] or None
373- remote_repo.lock_write(repo_lock_token, _skip_rpc=True)
374- if repo_lock_token:
375- remote_repo.dont_leave_lock_in_place()
376- else:
377- remote_repo.lock_write()
378- policy = UseExistingRepository(remote_repo, final_stack,
379- final_stack_pwd, require_stacking)
380- policy.acquire_repository()
381- else:
382- remote_repo = None
383- policy = None
384- bzrdir._format.set_branch_format(self.get_branch_format())
385- if require_stacking:
386- # The repo has already been created, but we need to make sure that
387- # we'll make a stackable branch.
388- bzrdir._format.require_stacking(_skip_repo=True)
389- return remote_repo, bzrdir, require_stacking, policy
390-
391- def _open(self, transport):
392- return remote.RemoteBzrDir(transport, self)
393-
394- def __eq__(self, other):
395- if not isinstance(other, RemoteBzrDirFormat):
396- return False
397- return self.get_format_description() == other.get_format_description()
398-
399- def __return_repository_format(self):
400- # Always return a RemoteRepositoryFormat object, but if a specific bzr
401- # repository format has been asked for, tell the RemoteRepositoryFormat
402- # that it should use that for init() etc.
403- result = remote.RemoteRepositoryFormat()
404- custom_format = getattr(self, '_repository_format', None)
405- if custom_format:
406- if isinstance(custom_format, remote.RemoteRepositoryFormat):
407- return custom_format
408- else:
409- # We will use the custom format to create repositories over the
410- # wire; expose its details like rich_root_data for code to
411- # query
412- result._custom_format = custom_format
413- return result
414-
415- def get_branch_format(self):
416- result = BzrDirMetaFormat1.get_branch_format(self)
417- if not isinstance(result, remote.RemoteBranchFormat):
418- new_result = remote.RemoteBranchFormat()
419- new_result._custom_format = result
420- # cache the result
421- self.set_branch_format(new_result)
422- result = new_result
423- return result
424-
425- repository_format = property(__return_repository_format,
426- BzrDirMetaFormat1._set_repository_format) #.im_func)
427-
428-
429 controldir.ControlDirFormat.register_server_prober(RemoteBzrProber)
430
431
432
433=== modified file 'bzrlib/controldir.py'
434--- bzrlib/controldir.py 2011-03-05 02:54:47 +0000
435+++ bzrlib/controldir.py 2011-03-11 14:21:26 +0000
436@@ -710,12 +710,6 @@
437 _default_format = None
438 """The default format used for new control directories."""
439
440- _formats = []
441- """The registered control formats - .bzr, ....
442-
443- This is a list of ControlDirFormat objects.
444- """
445-
446 _server_probers = []
447 """The registered server format probers, e.g. RemoteBzrProber.
448
449@@ -776,7 +770,8 @@
450 """Register a format that does not use '.bzr' for its control dir.
451
452 """
453- klass._formats.append(format)
454+ raise errors.BzrError("ControlDirFormat.register_format() has been "
455+ "removed in Bazaar 2.4. Please upgrade your plugins.")
456
457 @classmethod
458 def register_prober(klass, prober):
459@@ -808,14 +803,13 @@
460 return self.get_format_description().rstrip()
461
462 @classmethod
463- def unregister_format(klass, format):
464- klass._formats.remove(format)
465-
466- @classmethod
467 def known_formats(klass):
468 """Return all the known formats.
469 """
470- return set(klass._formats)
471+ result = set()
472+ for prober_kls in klass._probers + klass._server_probers:
473+ result.update(prober_kls.known_formats())
474+ return result
475
476 @classmethod
477 def find_format(klass, transport, _server_formats=True):
478@@ -929,6 +923,14 @@
479 """
480 raise NotImplementedError(self.probe_transport)
481
482+ @classmethod
483+ def known_formats(cls):
484+ """Return the control dir formats known by this prober.
485+
486+ :return: A set of known formats.
487+ """
488+ raise NotImplementedError(cls.known_formats)
489+
490
491 class ControlDirFormatInfo(object):
492
493
494=== modified file 'bzrlib/remote.py'
495--- bzrlib/remote.py 2011-03-08 20:37:43 +0000
496+++ bzrlib/remote.py 2011-03-11 14:21:26 +0000
497@@ -19,7 +19,7 @@
498 from bzrlib import (
499 bencode,
500 branch,
501- bzrdir,
502+ bzrdir as _mod_bzrdir,
503 config,
504 controldir,
505 debug,
506@@ -27,16 +27,13 @@
507 graph,
508 lock,
509 lockdir,
510- repository,
511 repository as _mod_repository,
512- revision,
513 revision as _mod_revision,
514 static_tuple,
515 symbol_versioning,
516 urlutils,
517 )
518 from bzrlib.branch import BranchReferenceFormat, BranchWriteLockResult
519-from bzrlib.bzrdir import BzrDir, RemoteBzrDirFormat
520 from bzrlib.decorators import needs_read_lock, needs_write_lock, only_raises
521 from bzrlib.errors import (
522 NoSuchRevision,
523@@ -44,7 +41,8 @@
524 )
525 from bzrlib.lockable_files import LockableFiles
526 from bzrlib.smart import client, vfs, repository as smart_repo
527-from bzrlib.revision import ensure_null, NULL_REVISION
528+from bzrlib.smart.client import _SmartClient
529+from bzrlib.revision import NULL_REVISION
530 from bzrlib.repository import RepositoryWriteLockResult
531 from bzrlib.trace import mutter, note, warning
532
533@@ -89,9 +87,246 @@
534 return format
535
536
537-# Note: RemoteBzrDirFormat is in bzrdir.py
538-
539-class RemoteBzrDir(BzrDir, _RpcHelper):
540+# Note that RemoteBzrDirProber lives in bzrlib.bzrdir so bzrlib.remote
541+# does not have to be imported unless a remote format is involved.
542+
543+class RemoteBzrDirFormat(_mod_bzrdir.BzrDirMetaFormat1):
544+ """Format representing bzrdirs accessed via a smart server"""
545+
546+ supports_workingtrees = False
547+
548+ def __init__(self):
549+ _mod_bzrdir.BzrDirMetaFormat1.__init__(self)
550+ # XXX: It's a bit ugly that the network name is here, because we'd
551+ # like to believe that format objects are stateless or at least
552+ # immutable, However, we do at least avoid mutating the name after
553+ # it's returned. See <https://bugs.launchpad.net/bzr/+bug/504102>
554+ self._network_name = None
555+
556+ def __repr__(self):
557+ return "%s(_network_name=%r)" % (self.__class__.__name__,
558+ self._network_name)
559+
560+ def get_format_description(self):
561+ if self._network_name:
562+ real_format = controldir.network_format_registry.get(self._network_name)
563+ return 'Remote: ' + real_format.get_format_description()
564+ return 'bzr remote bzrdir'
565+
566+ def get_format_string(self):
567+ raise NotImplementedError(self.get_format_string)
568+
569+ def network_name(self):
570+ if self._network_name:
571+ return self._network_name
572+ else:
573+ raise AssertionError("No network name set.")
574+
575+ def initialize_on_transport(self, transport):
576+ try:
577+ # hand off the request to the smart server
578+ client_medium = transport.get_smart_medium()
579+ except errors.NoSmartMedium:
580+ # TODO: lookup the local format from a server hint.
581+ local_dir_format = _mod_bzrdir.BzrDirMetaFormat1()
582+ return local_dir_format.initialize_on_transport(transport)
583+ client = _SmartClient(client_medium)
584+ path = client.remote_path_from_transport(transport)
585+ try:
586+ response = client.call('BzrDirFormat.initialize', path)
587+ except errors.ErrorFromSmartServer, err:
588+ _translate_error(err, path=path)
589+ if response[0] != 'ok':
590+ raise errors.SmartProtocolError('unexpected response code %s' % (response,))
591+ format = RemoteBzrDirFormat()
592+ self._supply_sub_formats_to(format)
593+ return RemoteBzrDir(transport, format)
594+
595+ def parse_NoneTrueFalse(self, arg):
596+ if not arg:
597+ return None
598+ if arg == 'False':
599+ return False
600+ if arg == 'True':
601+ return True
602+ raise AssertionError("invalid arg %r" % arg)
603+
604+ def _serialize_NoneTrueFalse(self, arg):
605+ if arg is False:
606+ return 'False'
607+ if arg:
608+ return 'True'
609+ return ''
610+
611+ def _serialize_NoneString(self, arg):
612+ return arg or ''
613+
614+ def initialize_on_transport_ex(self, transport, use_existing_dir=False,
615+ create_prefix=False, force_new_repo=False, stacked_on=None,
616+ stack_on_pwd=None, repo_format_name=None, make_working_trees=None,
617+ shared_repo=False):
618+ try:
619+ # hand off the request to the smart server
620+ client_medium = transport.get_smart_medium()
621+ except errors.NoSmartMedium:
622+ do_vfs = True
623+ else:
624+ # Decline to open it if the server doesn't support our required
625+ # version (3) so that the VFS-based transport will do it.
626+ if client_medium.should_probe():
627+ try:
628+ server_version = client_medium.protocol_version()
629+ if server_version != '2':
630+ do_vfs = True
631+ else:
632+ do_vfs = False
633+ except errors.SmartProtocolError:
634+ # Apparently there's no usable smart server there, even though
635+ # the medium supports the smart protocol.
636+ do_vfs = True
637+ else:
638+ do_vfs = False
639+ if not do_vfs:
640+ client = _SmartClient(client_medium)
641+ path = client.remote_path_from_transport(transport)
642+ if client_medium._is_remote_before((1, 16)):
643+ do_vfs = True
644+ if do_vfs:
645+ # TODO: lookup the local format from a server hint.
646+ local_dir_format = _mod_bzrdir.BzrDirMetaFormat1()
647+ self._supply_sub_formats_to(local_dir_format)
648+ return local_dir_format.initialize_on_transport_ex(transport,
649+ use_existing_dir=use_existing_dir, create_prefix=create_prefix,
650+ force_new_repo=force_new_repo, stacked_on=stacked_on,
651+ stack_on_pwd=stack_on_pwd, repo_format_name=repo_format_name,
652+ make_working_trees=make_working_trees, shared_repo=shared_repo,
653+ vfs_only=True)
654+ return self._initialize_on_transport_ex_rpc(client, path, transport,
655+ use_existing_dir, create_prefix, force_new_repo, stacked_on,
656+ stack_on_pwd, repo_format_name, make_working_trees, shared_repo)
657+
658+ def _initialize_on_transport_ex_rpc(self, client, path, transport,
659+ use_existing_dir, create_prefix, force_new_repo, stacked_on,
660+ stack_on_pwd, repo_format_name, make_working_trees, shared_repo):
661+ args = []
662+ args.append(self._serialize_NoneTrueFalse(use_existing_dir))
663+ args.append(self._serialize_NoneTrueFalse(create_prefix))
664+ args.append(self._serialize_NoneTrueFalse(force_new_repo))
665+ args.append(self._serialize_NoneString(stacked_on))
666+ # stack_on_pwd is often/usually our transport
667+ if stack_on_pwd:
668+ try:
669+ stack_on_pwd = transport.relpath(stack_on_pwd)
670+ if not stack_on_pwd:
671+ stack_on_pwd = '.'
672+ except errors.PathNotChild:
673+ pass
674+ args.append(self._serialize_NoneString(stack_on_pwd))
675+ args.append(self._serialize_NoneString(repo_format_name))
676+ args.append(self._serialize_NoneTrueFalse(make_working_trees))
677+ args.append(self._serialize_NoneTrueFalse(shared_repo))
678+ request_network_name = self._network_name or \
679+ _mod_bzrdir.BzrDirFormat.get_default_format().network_name()
680+ try:
681+ response = client.call('BzrDirFormat.initialize_ex_1.16',
682+ request_network_name, path, *args)
683+ except errors.UnknownSmartMethod:
684+ client._medium._remember_remote_is_before((1,16))
685+ local_dir_format = _mod_bzrdir.BzrDirMetaFormat1()
686+ self._supply_sub_formats_to(local_dir_format)
687+ return local_dir_format.initialize_on_transport_ex(transport,
688+ use_existing_dir=use_existing_dir, create_prefix=create_prefix,
689+ force_new_repo=force_new_repo, stacked_on=stacked_on,
690+ stack_on_pwd=stack_on_pwd, repo_format_name=repo_format_name,
691+ make_working_trees=make_working_trees, shared_repo=shared_repo,
692+ vfs_only=True)
693+ except errors.ErrorFromSmartServer, err:
694+ _translate_error(err, path=path)
695+ repo_path = response[0]
696+ bzrdir_name = response[6]
697+ require_stacking = response[7]
698+ require_stacking = self.parse_NoneTrueFalse(require_stacking)
699+ format = RemoteBzrDirFormat()
700+ format._network_name = bzrdir_name
701+ self._supply_sub_formats_to(format)
702+ bzrdir = RemoteBzrDir(transport, format, _client=client)
703+ if repo_path:
704+ repo_format = response_tuple_to_repo_format(response[1:])
705+ if repo_path == '.':
706+ repo_path = ''
707+ if repo_path:
708+ repo_bzrdir_format = RemoteBzrDirFormat()
709+ repo_bzrdir_format._network_name = response[5]
710+ repo_bzr = RemoteBzrDir(transport.clone(repo_path),
711+ repo_bzrdir_format)
712+ else:
713+ repo_bzr = bzrdir
714+ final_stack = response[8] or None
715+ final_stack_pwd = response[9] or None
716+ if final_stack_pwd:
717+ final_stack_pwd = urlutils.join(
718+ transport.base, final_stack_pwd)
719+ remote_repo = RemoteRepository(repo_bzr, repo_format)
720+ if len(response) > 10:
721+ # Updated server verb that locks remotely.
722+ repo_lock_token = response[10] or None
723+ remote_repo.lock_write(repo_lock_token, _skip_rpc=True)
724+ if repo_lock_token:
725+ remote_repo.dont_leave_lock_in_place()
726+ else:
727+ remote_repo.lock_write()
728+ policy = _mod_bzrdir.UseExistingRepository(remote_repo, final_stack,
729+ final_stack_pwd, require_stacking)
730+ policy.acquire_repository()
731+ else:
732+ remote_repo = None
733+ policy = None
734+ bzrdir._format.set_branch_format(self.get_branch_format())
735+ if require_stacking:
736+ # The repo has already been created, but we need to make sure that
737+ # we'll make a stackable branch.
738+ bzrdir._format.require_stacking(_skip_repo=True)
739+ return remote_repo, bzrdir, require_stacking, policy
740+
741+ def _open(self, transport):
742+ return RemoteBzrDir(transport, self)
743+
744+ def __eq__(self, other):
745+ if not isinstance(other, RemoteBzrDirFormat):
746+ return False
747+ return self.get_format_description() == other.get_format_description()
748+
749+ def __return_repository_format(self):
750+ # Always return a RemoteRepositoryFormat object, but if a specific bzr
751+ # repository format has been asked for, tell the RemoteRepositoryFormat
752+ # that it should use that for init() etc.
753+ result = RemoteRepositoryFormat()
754+ custom_format = getattr(self, '_repository_format', None)
755+ if custom_format:
756+ if isinstance(custom_format, RemoteRepositoryFormat):
757+ return custom_format
758+ else:
759+ # We will use the custom format to create repositories over the
760+ # wire; expose its details like rich_root_data for code to
761+ # query
762+ result._custom_format = custom_format
763+ return result
764+
765+ def get_branch_format(self):
766+ result = _mod_bzrdir.BzrDirMetaFormat1.get_branch_format(self)
767+ if not isinstance(result, RemoteBranchFormat):
768+ new_result = RemoteBranchFormat()
769+ new_result._custom_format = result
770+ # cache the result
771+ self.set_branch_format(new_result)
772+ result = new_result
773+ return result
774+
775+ repository_format = property(__return_repository_format,
776+ _mod_bzrdir.BzrDirMetaFormat1._set_repository_format) #.im_func)
777+
778+
779+class RemoteBzrDir(_mod_bzrdir.BzrDir, _RpcHelper):
780 """Control directory on a remote server, accessed via bzr:// or similar."""
781
782 def __init__(self, transport, format, _client=None, _force_probe=False):
783@@ -100,7 +335,7 @@
784 :param _client: Private parameter for testing. Disables probing and the
785 use of a real bzrdir.
786 """
787- BzrDir.__init__(self, transport, format)
788+ _mod_bzrdir.BzrDir.__init__(self, transport, format)
789 # this object holds a delegated bzrdir that uses file-level operations
790 # to talk to the other side
791 self._real_bzrdir = None
792@@ -166,7 +401,7 @@
793 import traceback
794 warning('VFS BzrDir access triggered\n%s',
795 ''.join(traceback.format_stack()))
796- self._real_bzrdir = BzrDir.open_from_transport(
797+ self._real_bzrdir = _mod_bzrdir.BzrDir.open_from_transport(
798 self.root_transport, _server_formats=False)
799 self._format._network_name = \
800 self._real_bzrdir._format.network_name()
801@@ -178,7 +413,7 @@
802 # Prevent aliasing problems in the next_open_branch_result cache.
803 # See create_branch for rationale.
804 self._next_open_branch_result = None
805- return BzrDir.break_lock(self)
806+ return _mod_bzrdir.BzrDir.break_lock(self)
807
808 def _vfs_cloning_metadir(self, require_stacking=False):
809 self._ensure_real()
810@@ -217,12 +452,12 @@
811 branch_ref, branch_name = branch_info
812 format = controldir.network_format_registry.get(control_name)
813 if repo_name:
814- format.repository_format = repository.network_format_registry.get(
815+ format.repository_format = _mod_repository.network_format_registry.get(
816 repo_name)
817 if branch_ref == 'ref':
818 # XXX: we need possible_transports here to avoid reopening the
819 # connection to the referenced location
820- ref_bzrdir = BzrDir.open(branch_name)
821+ ref_bzrdir = _mod_bzrdir.BzrDir.open(branch_name)
822 branch_format = ref_bzrdir.cloning_metadir().get_branch_format()
823 format.set_branch_format(branch_format)
824 elif branch_ref == 'branch':
825@@ -465,7 +700,7 @@
826 return RemoteBzrDirConfig(self)
827
828
829-class RemoteRepositoryFormat(repository.RepositoryFormat):
830+class RemoteRepositoryFormat(_mod_repository.RepositoryFormat):
831 """Format for repositories accessed over a _SmartClient.
832
833 Instances of this repository are represented by RemoteRepository
834@@ -490,7 +725,7 @@
835 supports_leaving_lock = True
836
837 def __init__(self):
838- repository.RepositoryFormat.__init__(self)
839+ _mod_repository.RepositoryFormat.__init__(self)
840 self._custom_format = None
841 self._network_name = None
842 self._creating_bzrdir = None
843@@ -587,7 +822,7 @@
844 network_name = self._network_name
845 else:
846 # Select the current bzrlib default and ask for that.
847- reference_bzrdir_format = bzrdir.format_registry.get('default')()
848+ reference_bzrdir_format = _mod_bzrdir.format_registry.get('default')()
849 reference_format = reference_bzrdir_format.repository_format
850 network_name = reference_format.network_name()
851 # 2) try direct creation via RPC
852@@ -619,7 +854,7 @@
853
854 def _ensure_real(self):
855 if self._custom_format is None:
856- self._custom_format = repository.network_format_registry.get(
857+ self._custom_format = _mod_repository.network_format_registry.get(
858 self._network_name)
859
860 @property
861@@ -721,7 +956,7 @@
862 # transport, but I'm not sure it's worth making this method
863 # optional -- mbp 2010-04-21
864 return self.bzrdir.get_repository_transport(None)
865-
866+
867 def __str__(self):
868 return "%s(%s)" % (self.__class__.__name__, self.base)
869
870@@ -861,7 +1096,7 @@
871 """Private method for using with old (< 1.2) servers to fallback."""
872 if revision_id is None:
873 revision_id = ''
874- elif revision.is_null(revision_id):
875+ elif _mod_revision.is_null(revision_id):
876 return {}
877
878 path = self.bzrdir._path_for_remote_call(self._client)
879@@ -948,7 +1183,7 @@
880 """See Repository.gather_stats()."""
881 path = self.bzrdir._path_for_remote_call(self._client)
882 # revid can be None to indicate no revisions, not just NULL_REVISION
883- if revid is None or revision.is_null(revid):
884+ if revid is None or _mod_revision.is_null(revid):
885 fmt_revid = ''
886 else:
887 fmt_revid = revid
888@@ -1375,7 +1610,7 @@
889 'revision_ids is mutually exclusive with revision_id')
890 if revision_id is not None:
891 revision_ids = [revision_id]
892- inter_repo = repository.InterRepository.get(other, self)
893+ inter_repo = _mod_repository.InterRepository.get(other, self)
894 return inter_repo.search_missing_revision_ids(
895 find_ghosts=find_ghosts, revision_ids=revision_ids,
896 if_present_ids=if_present_ids)
897@@ -1397,13 +1632,13 @@
898 # check that last_revision is in 'from' and then return a
899 # no-operation.
900 if (revision_id is not None and
901- not revision.is_null(revision_id)):
902+ not _mod_revision.is_null(revision_id)):
903 self.get_revision(revision_id)
904 return 0, []
905 # if there is no specific appropriate InterRepository, this will get
906 # the InterRepository base class, which raises an
907 # IncompatibleRepositories when asked to fetch.
908- inter = repository.InterRepository.get(source, self)
909+ inter = _mod_repository.InterRepository.get(source, self)
910 return inter.fetch(revision_id=revision_id,
911 find_ghosts=find_ghosts, fetch_spec=fetch_spec)
912
913@@ -1634,7 +1869,7 @@
914 tmpdir = osutils.mkdtemp()
915 try:
916 _extract_tar(tar, tmpdir)
917- tmp_bzrdir = BzrDir.open(tmpdir)
918+ tmp_bzrdir = _mod_bzrdir.BzrDir.open(tmpdir)
919 tmp_repo = tmp_bzrdir.open_repository()
920 tmp_repo.copy_content_into(destination, revision_id)
921 finally:
922@@ -1801,7 +2036,7 @@
923 raise errors.UnexpectedSmartServerResponse(response)
924
925
926-class RemoteStreamSink(repository.StreamSink):
927+class RemoteStreamSink(_mod_repository.StreamSink):
928
929 def _insert_real(self, stream, src_format, resume_tokens):
930 self.target_repo._ensure_real()
931@@ -1908,7 +2143,7 @@
932 self._last_substream and self._last_stream so that the stream can be
933 resumed by _resume_stream_with_vfs.
934 """
935-
936+
937 stream_iter = iter(stream)
938 for substream_kind, substream in stream_iter:
939 if substream_kind == 'inventory-deltas':
940@@ -1917,9 +2152,9 @@
941 return
942 else:
943 yield substream_kind, substream
944-
945-
946-class RemoteStreamSource(repository.StreamSource):
947+
948+
949+class RemoteStreamSource(_mod_repository.StreamSource):
950 """Stream data from a remote server."""
951
952 def get_stream(self, search):
953@@ -2132,7 +2367,7 @@
954 network_name = self._custom_format.network_name()
955 else:
956 # Select the current bzrlib default and ask for that.
957- reference_bzrdir_format = bzrdir.format_registry.get('default')()
958+ reference_bzrdir_format = _mod_bzrdir.format_registry.get('default')()
959 reference_format = reference_bzrdir_format.get_branch_format()
960 self._custom_format = reference_format
961 network_name = reference_format.network_name()
962@@ -2422,7 +2657,7 @@
963 self._is_stacked = False
964 else:
965 self._is_stacked = True
966-
967+
968 def _vfs_get_tags_bytes(self):
969 self._ensure_real()
970 return self._real_branch._get_tags_bytes()
971@@ -2763,7 +2998,7 @@
972 # XXX: These should be returned by the set_last_revision_info verb
973 old_revno, old_revid = self.last_revision_info()
974 self._run_pre_change_branch_tip_hooks(revno, revision_id)
975- revision_id = ensure_null(revision_id)
976+ revision_id = _mod_revision.ensure_null(revision_id)
977 try:
978 response = self._call('Branch.set_last_revision_info',
979 self._remote_path(), self._lock_token, self._repo_lock_token,
980
981=== modified file 'bzrlib/tests/blackbox/test_upgrade.py'
982--- bzrlib/tests/blackbox/test_upgrade.py 2011-03-04 15:29:08 +0000
983+++ bzrlib/tests/blackbox/test_upgrade.py 2011-03-11 14:21:26 +0000
984@@ -129,8 +129,10 @@
985
986 def test_upgrade_control_dir(self):
987 old_format = OldBzrDirFormat()
988- self.addCleanup(bzrdir.BzrDirFormat.unregister_format, old_format)
989- bzrdir.BzrDirFormat.register_format(old_format)
990+ self.addCleanup(bzrdir.BzrProber.formats.remove,
991+ old_format.get_format_string())
992+ bzrdir.BzrProber.formats.register(old_format.get_format_string(),
993+ old_format)
994 self.addCleanup(controldir.ControlDirFormat._set_default_format,
995 controldir.ControlDirFormat.get_default_format())
996
997
998=== modified file 'bzrlib/tests/per_controldir/test_controldir.py'
999--- bzrlib/tests/per_controldir/test_controldir.py 2011-03-08 00:53:45 +0000
1000+++ bzrlib/tests/per_controldir/test_controldir.py 2011-03-11 14:21:26 +0000
1001@@ -26,7 +26,6 @@
1002 errors,
1003 gpg,
1004 osutils,
1005- repository,
1006 transport,
1007 ui,
1008 urlutils,
1009@@ -46,6 +45,7 @@
1010 )
1011 from bzrlib.remote import (
1012 RemoteBzrDir,
1013+ RemoteBzrDirFormat,
1014 RemoteRepository,
1015 )
1016
1017@@ -906,6 +906,8 @@
1018 readonly_t = self.get_readonly_transport()
1019 made_control = self.bzrdir_format.initialize(t.base)
1020 self.failUnless(isinstance(made_control, controldir.ControlDir))
1021+ if isinstance(self.bzrdir_format, RemoteBzrDirFormat):
1022+ return
1023 self.assertEqual(self.bzrdir_format,
1024 controldir.ControlDirFormat.find_format(readonly_t))
1025 direct_opened_dir = self.bzrdir_format.open(readonly_t)
1026@@ -1068,15 +1070,11 @@
1027 self.assertIsInstance(control, controldir.ControlDir)
1028 opened = bzrdir.BzrDir.open(t.base)
1029 expected_format = self.bzrdir_format
1030- if isinstance(expected_format, bzrdir.RemoteBzrDirFormat):
1031- # Current RemoteBzrDirFormat's do not reliably get network_name
1032- # set, so we skip a number of tests for RemoteBzrDirFormat's.
1033- self.assertIsInstance(control, RemoteBzrDir)
1034- else:
1035- if need_meta and expected_format.fixed_components:
1036- # Pre-metadir formats change when we are making something that
1037- # needs a metaformat, because clone is used for push.
1038- expected_format = bzrdir.BzrDirMetaFormat1()
1039+ if need_meta and expected_format.fixed_components:
1040+ # Pre-metadir formats change when we are making something that
1041+ # needs a metaformat, because clone is used for push.
1042+ expected_format = bzrdir.BzrDirMetaFormat1()
1043+ if not isinstance(expected_format, RemoteBzrDirFormat):
1044 self.assertEqual(control._format.network_name(),
1045 expected_format.network_name())
1046 self.assertEqual(control._format.network_name(),
1047@@ -1093,7 +1091,7 @@
1048 # key in the registry gives back the same format. For remote obects
1049 # we check that the network_name of the RemoteBzrDirFormat we have
1050 # locally matches the actual format present on disk.
1051- if isinstance(format, bzrdir.RemoteBzrDirFormat):
1052+ if isinstance(format, RemoteBzrDirFormat):
1053 dir._ensure_real()
1054 real_dir = dir._real_bzrdir
1055 network_name = format.network_name()
1056
1057=== modified file 'bzrlib/tests/test_bzrdir.py'
1058--- bzrlib/tests/test_bzrdir.py 2011-02-24 12:08:37 +0000
1059+++ bzrlib/tests/test_bzrdir.py 2011-03-11 14:21:26 +0000
1060@@ -272,10 +272,14 @@
1061 def test_find_format(self):
1062 # is the right format object found for a branch?
1063 # create a branch with a few known format objects.
1064- bzrdir.BzrDirFormat.register_format(BzrDirFormatTest1())
1065- self.addCleanup(bzrdir.BzrDirFormat.unregister_format, BzrDirFormatTest1())
1066- bzrdir.BzrDirFormat.register_format(BzrDirFormatTest2())
1067- self.addCleanup(bzrdir.BzrDirFormat.unregister_format, BzrDirFormatTest2())
1068+ bzrdir.BzrProber.formats.register(BzrDirFormatTest1.get_format_string(),
1069+ BzrDirFormatTest1())
1070+ self.addCleanup(bzrdir.BzrProber.formats.remove,
1071+ BzrDirFormatTest1.get_format_string())
1072+ bzrdir.BzrProber.formats.register(BzrDirFormatTest2.get_format_string(),
1073+ BzrDirFormatTest2())
1074+ self.addCleanup(bzrdir.BzrProber.formats.remove,
1075+ BzrDirFormatTest2.get_format_string())
1076 t = self.get_transport()
1077 self.build_tree(["foo/", "bar/"], transport=t)
1078 def check_format(format, url):
1079@@ -305,7 +309,7 @@
1080 # make a bzrdir
1081 format.initialize(url)
1082 # register a format for it.
1083- bzrdir.BzrDirFormat.register_format(format)
1084+ bzrdir.BzrProber.formats.register(format.get_format_string(), format)
1085 # which bzrdir.Open will refuse (not supported)
1086 self.assertRaises(UnsupportedFormatError, bzrdir.BzrDir.open, url)
1087 # which bzrdir.open_containing will refuse (not supported)
1088@@ -314,7 +318,7 @@
1089 t = _mod_transport.get_transport(url)
1090 self.assertEqual(format.open(t), bzrdir.BzrDir.open_unsupported(url))
1091 # unregister the format
1092- bzrdir.BzrDirFormat.unregister_format(format)
1093+ bzrdir.BzrProber.formats.remove(format.get_format_string())
1094 # now open_downlevel should fail too.
1095 self.assertRaises(UnknownFormatError, bzrdir.BzrDir.open_unsupported, url)
1096
1097@@ -1071,73 +1075,6 @@
1098 bzrdir.BzrDirFormat.get_default_format()))
1099
1100
1101-class NotBzrDir(bzrlib.bzrdir.BzrDir):
1102- """A non .bzr based control directory."""
1103-
1104- def __init__(self, transport, format):
1105- self._format = format
1106- self.root_transport = transport
1107- self.transport = transport.clone('.not')
1108-
1109-
1110-class NotBzrDirFormat(bzrlib.bzrdir.BzrDirFormat):
1111- """A test class representing any non-.bzr based disk format."""
1112-
1113- def initialize_on_transport(self, transport):
1114- """Initialize a new .not dir in the base directory of a Transport."""
1115- transport.mkdir('.not')
1116- return self.open(transport)
1117-
1118- def open(self, transport):
1119- """Open this directory."""
1120- return NotBzrDir(transport, self)
1121-
1122- @classmethod
1123- def _known_formats(self):
1124- return set([NotBzrDirFormat()])
1125-
1126-
1127-class NotBzrDirProber(controldir.Prober):
1128-
1129- def probe_transport(self, transport):
1130- """Our format is present if the transport ends in '.not/'."""
1131- if transport.has('.not'):
1132- return NotBzrDirFormat()
1133-
1134-
1135-class TestNotBzrDir(TestCaseWithTransport):
1136- """Tests for using the bzrdir api with a non .bzr based disk format.
1137-
1138- If/when one of these is in the core, we can let the implementation tests
1139- verify this works.
1140- """
1141-
1142- def test_create_and_find_format(self):
1143- # create a .notbzr dir
1144- format = NotBzrDirFormat()
1145- dir = format.initialize(self.get_url())
1146- self.assertIsInstance(dir, NotBzrDir)
1147- # now probe for it.
1148- controldir.ControlDirFormat.register_prober(NotBzrDirProber)
1149- try:
1150- found = bzrlib.bzrdir.BzrDirFormat.find_format(self.get_transport())
1151- self.assertIsInstance(found, NotBzrDirFormat)
1152- finally:
1153- controldir.ControlDirFormat.unregister_prober(NotBzrDirProber)
1154-
1155- def test_included_in_known_formats(self):
1156- not_format = NotBzrDirFormat()
1157- bzrlib.controldir.ControlDirFormat.register_format(not_format)
1158- try:
1159- formats = bzrlib.bzrdir.BzrDirFormat.known_formats()
1160- for format in formats:
1161- if isinstance(format, NotBzrDirFormat):
1162- return
1163- self.fail("No NotBzrDirFormat in %s" % formats)
1164- finally:
1165- bzrlib.controldir.ControlDirFormat.unregister_format(not_format)
1166-
1167-
1168 class NonLocalTests(TestCaseWithTransport):
1169 """Tests for bzrdir static behaviour on non local paths."""
1170
1171
1172=== modified file 'bzrlib/tests/test_controldir.py'
1173--- bzrlib/tests/test_controldir.py 2011-02-24 16:23:16 +0000
1174+++ bzrlib/tests/test_controldir.py 2011-03-11 14:21:26 +0000
1175@@ -21,8 +21,13 @@
1176
1177 from bzrlib import (
1178 controldir,
1179+ errors,
1180 tests,
1181 )
1182+from bzrlib.tests.scenarios import load_tests_apply_scenarios
1183+
1184+
1185+load_tests = load_tests_apply_scenarios
1186
1187
1188 class SampleComponentFormat(controldir.ControlComponentFormat):
1189@@ -77,3 +82,101 @@
1190 formats = self.registry._get_all()
1191 self.assertEquals(1, len(formats))
1192 self.assertIsInstance(formats[0], SampleExtraComponentFormat)
1193+
1194+
1195+class TestControlDirFormatDeprecated(tests.TestCaseWithTransport):
1196+ """Tests for removed registration method in the ControlDirFormat facility."""
1197+
1198+ def test_register_format(self):
1199+ self.assertRaises(errors.BzrError,
1200+ controldir.ControlDirFormat.register_format, object())
1201+
1202+
1203+class TestProber(tests.TestCaseWithTransport):
1204+ """Per-prober tests."""
1205+
1206+ scenarios = [
1207+ (prober_cls.__name__, {'prober_cls': prober_cls})
1208+ for prober_cls in controldir.ControlDirFormat._probers]
1209+
1210+ def setUp(self):
1211+ super(TestProber, self).setUp()
1212+ self.prober = self.prober_cls()
1213+
1214+ def test_probe_transport_empty(self):
1215+ transport = self.get_transport(".")
1216+ self.assertRaises(errors.NotBranchError,
1217+ self.prober.probe_transport, transport)
1218+
1219+ def test_known_formats(self):
1220+ known_formats = self.prober_cls.known_formats()
1221+ self.assertIsInstance(known_formats, set)
1222+ for format in known_formats:
1223+ self.assertIsInstance(format, controldir.ControlDirFormat,
1224+ repr(format))
1225+
1226+
1227+class NotBzrDir(controldir.ControlDir):
1228+ """A non .bzr based control directory."""
1229+
1230+ def __init__(self, transport, format):
1231+ self._format = format
1232+ self.root_transport = transport
1233+ self.transport = transport.clone('.not')
1234+
1235+
1236+class NotBzrDirFormat(controldir.ControlDirFormat):
1237+ """A test class representing any non-.bzr based disk format."""
1238+
1239+ def initialize_on_transport(self, transport):
1240+ """Initialize a new .not dir in the base directory of a Transport."""
1241+ transport.mkdir('.not')
1242+ return self.open(transport)
1243+
1244+ def open(self, transport):
1245+ """Open this directory."""
1246+ return NotBzrDir(transport, self)
1247+
1248+
1249+class NotBzrDirProber(controldir.Prober):
1250+
1251+ def probe_transport(self, transport):
1252+ """Our format is present if the transport ends in '.not/'."""
1253+ if transport.has('.not'):
1254+ return NotBzrDirFormat()
1255+
1256+ @classmethod
1257+ def known_formats(cls):
1258+ return set([NotBzrDirFormat()])
1259+
1260+
1261+class TestNotBzrDir(tests.TestCaseWithTransport):
1262+ """Tests for using the controldir api with a non .bzr based disk format.
1263+
1264+ If/when one of these is in the core, we can let the implementation tests
1265+ verify this works.
1266+ """
1267+
1268+ def test_create_and_find_format(self):
1269+ # create a .notbzr dir
1270+ format = NotBzrDirFormat()
1271+ dir = format.initialize(self.get_url())
1272+ self.assertIsInstance(dir, NotBzrDir)
1273+ # now probe for it.
1274+ controldir.ControlDirFormat.register_prober(NotBzrDirProber)
1275+ try:
1276+ found = controldir.ControlDirFormat.find_format(self.get_transport())
1277+ self.assertIsInstance(found, NotBzrDirFormat)
1278+ finally:
1279+ controldir.ControlDirFormat.unregister_prober(NotBzrDirProber)
1280+
1281+ def test_included_in_known_formats(self):
1282+ controldir.ControlDirFormat.register_prober(NotBzrDirProber)
1283+ self.addCleanup(controldir.ControlDirFormat.unregister_prober, NotBzrDirProber)
1284+ formats = controldir.ControlDirFormat.known_formats()
1285+ self.assertIsInstance(formats, set)
1286+ for format in formats:
1287+ if isinstance(format, NotBzrDirFormat):
1288+ break
1289+ else:
1290+ self.fail("No NotBzrDirFormat in %s" % formats)
1291
1292=== modified file 'bzrlib/tests/test_foreign.py'
1293--- bzrlib/tests/test_foreign.py 2011-01-12 23:33:40 +0000
1294+++ bzrlib/tests/test_foreign.py 2011-03-11 14:21:26 +0000
1295@@ -262,9 +262,6 @@
1296
1297
1298 def register_dummy_foreign_for_test(testcase):
1299- controldir.ControlDirFormat.register_format(DummyForeignVcsDirFormat)
1300- testcase.addCleanup(controldir.ControlDirFormat.unregister_format,
1301- DummyForeignVcsDirFormat)
1302 controldir.ControlDirFormat.register_prober(DummyForeignProber)
1303 testcase.addCleanup(controldir.ControlDirFormat.unregister_prober,
1304 DummyForeignProber)
1305@@ -284,6 +281,10 @@
1306 raise errors.NotBranchError(path=transport.base)
1307 return DummyForeignVcsDirFormat()
1308
1309+ @classmethod
1310+ def known_formats(cls):
1311+ return set([DummyForeignVcsDirFormat()])
1312+
1313
1314 class ForeignVcsRegistryTests(tests.TestCase):
1315 """Tests for the ForeignVcsRegistry class."""
1316
1317=== modified file 'bzrlib/tests/test_import_tariff.py'
1318--- bzrlib/tests/test_import_tariff.py 2011-03-04 22:50:20 +0000
1319+++ bzrlib/tests/test_import_tariff.py 2011-03-11 14:21:26 +0000
1320@@ -110,6 +110,7 @@
1321 'bzrlib.remote',
1322 'bzrlib.sign_my_commits',
1323 'bzrlib.smart',
1324+ 'bzrlib.smart.client',
1325 'bzrlib.transform',
1326 'bzrlib.version_info_formats.format_rio',
1327 'bzrlib.workingtree_2',
1328
1329=== modified file 'bzrlib/tests/test_remote.py'
1330--- bzrlib/tests/test_remote.py 2011-03-03 07:16:12 +0000
1331+++ bzrlib/tests/test_remote.py 2011-03-11 14:21:26 +0000
1332@@ -52,6 +52,7 @@
1333 RemoteBranch,
1334 RemoteBranchFormat,
1335 RemoteBzrDir,
1336+ RemoteBzrDirFormat,
1337 RemoteRepository,
1338 RemoteRepositoryFormat,
1339 )
1340@@ -95,12 +96,12 @@
1341 self.addCleanup(self.transport.disconnect)
1342
1343 def test_create_remote_bzrdir(self):
1344- b = remote.RemoteBzrDir(self.transport, remote.RemoteBzrDirFormat())
1345+ b = remote.RemoteBzrDir(self.transport, RemoteBzrDirFormat())
1346 self.assertIsInstance(b, BzrDir)
1347
1348 def test_open_remote_branch(self):
1349 # open a standalone branch in the working directory
1350- b = remote.RemoteBzrDir(self.transport, remote.RemoteBzrDirFormat())
1351+ b = remote.RemoteBzrDir(self.transport, RemoteBzrDirFormat())
1352 branch = b.open_branch()
1353 self.assertIsInstance(branch, Branch)
1354
1355@@ -124,7 +125,7 @@
1356 fmt = BzrDirFormat.find_format(self.transport)
1357 self.assertTrue(bzrdir.RemoteBzrProber
1358 in controldir.ControlDirFormat._server_probers)
1359- self.assertIsInstance(fmt, remote.RemoteBzrDirFormat)
1360+ self.assertIsInstance(fmt, RemoteBzrDirFormat)
1361
1362 def test_open_detected_smart_format(self):
1363 fmt = BzrDirFormat.find_format(self.transport)
1364@@ -450,7 +451,7 @@
1365 client.add_expected_call(
1366 'BzrDir.open_branchV3', ('quack/',),
1367 'success', ('ref', self.get_url('referenced'))),
1368- a_bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
1369+ a_bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
1370 _client=client)
1371 result = a_bzrdir.cloning_metadir()
1372 # We should have got a control dir matching the referenced branch.
1373@@ -469,7 +470,7 @@
1374 client.add_expected_call(
1375 'BzrDir.cloning_metadir', ('quack/', 'False'),
1376 'success', (control_name, '', ('branch', ''))),
1377- a_bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
1378+ a_bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
1379 _client=client)
1380 result = a_bzrdir.cloning_metadir()
1381 # We should have got a reference control dir with default branch and
1382@@ -495,14 +496,14 @@
1383 client.add_expected_call(
1384 'BzrDir.open_2.1', ('quack/',), 'success', ('no',))
1385 self.assertRaises(errors.NotBranchError, RemoteBzrDir, transport,
1386- remote.RemoteBzrDirFormat(), _client=client, _force_probe=True)
1387+ RemoteBzrDirFormat(), _client=client, _force_probe=True)
1388 self.assertFinished(client)
1389
1390 def test_present_without_workingtree(self):
1391 client, transport = self.make_fake_client_and_transport()
1392 client.add_expected_call(
1393 'BzrDir.open_2.1', ('quack/',), 'success', ('yes', 'no'))
1394- bd = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
1395+ bd = RemoteBzrDir(transport, RemoteBzrDirFormat(),
1396 _client=client, _force_probe=True)
1397 self.assertIsInstance(bd, RemoteBzrDir)
1398 self.assertFalse(bd.has_workingtree())
1399@@ -513,7 +514,7 @@
1400 client, transport = self.make_fake_client_and_transport()
1401 client.add_expected_call(
1402 'BzrDir.open_2.1', ('quack/',), 'success', ('yes', 'yes'))
1403- bd = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
1404+ bd = RemoteBzrDir(transport, RemoteBzrDirFormat(),
1405 _client=client, _force_probe=True)
1406 self.assertIsInstance(bd, RemoteBzrDir)
1407 self.assertTrue(bd.has_workingtree())
1408@@ -526,7 +527,7 @@
1409 'BzrDir.open_2.1', ('quack/',), 'unknown', ('BzrDir.open_2.1',))
1410 client.add_expected_call(
1411 'BzrDir.open', ('quack/',), 'success', ('yes',))
1412- bd = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
1413+ bd = RemoteBzrDir(transport, RemoteBzrDirFormat(),
1414 _client=client, _force_probe=True)
1415 self.assertIsInstance(bd, RemoteBzrDir)
1416 self.assertFinished(client)
1417@@ -548,7 +549,7 @@
1418 'BzrDir.open_2.1', ('quack/',), 'unknown', ('BzrDir.open_2.1',))
1419 client.add_expected_call(
1420 'BzrDir.open', ('quack/',), 'success', ('yes',))
1421- bd = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
1422+ bd = RemoteBzrDir(transport, RemoteBzrDirFormat(),
1423 _client=client, _force_probe=True)
1424 self.assertIsInstance(bd, RemoteBzrDir)
1425 self.assertFinished(client)
1426@@ -585,7 +586,7 @@
1427 client.add_expected_call(
1428 'Branch.get_stacked_on_url', ('quack/',),
1429 'error', ('NotStacked',))
1430- bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
1431+ bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
1432 _client=client)
1433 result = bzrdir.open_branch()
1434 self.assertIsInstance(result, RemoteBranch)
1435@@ -598,7 +599,7 @@
1436 transport = transport.clone('quack')
1437 client = FakeClient(transport.base)
1438 client.add_error_response('nobranch')
1439- bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
1440+ bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
1441 _client=client)
1442 self.assertRaises(errors.NotBranchError, bzrdir.open_branch)
1443 self.assertEqual(
1444@@ -615,7 +616,7 @@
1445 transport = MemoryTransport()
1446 # no requests on the network - catches other api calls being made.
1447 client = FakeClient(transport.base)
1448- bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
1449+ bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
1450 _client=client)
1451 # patch the open_branch call to record that it was called.
1452 bzrdir.open_branch = open_branch
1453@@ -640,7 +641,7 @@
1454 client.add_expected_call(
1455 'Branch.get_stacked_on_url', ('~hello/',),
1456 'error', ('NotStacked',))
1457- bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
1458+ bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
1459 _client=client)
1460 result = bzrdir.open_branch()
1461 self.assertFinished(client)
1462@@ -663,7 +664,7 @@
1463 client.add_success_response(
1464 'ok', '', rich_response, subtree_response, external_lookup,
1465 network_name)
1466- bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
1467+ bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
1468 _client=client)
1469 result = bzrdir.open_repository()
1470 self.assertEqual(
1471@@ -715,7 +716,7 @@
1472 'BzrDir.create_branch', ('quack/', network_name),
1473 'success', ('ok', network_name, '', 'no', 'no', 'yes',
1474 reference_repo_name))
1475- a_bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
1476+ a_bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
1477 _client=client)
1478 branch = a_bzrdir.create_branch()
1479 # We should have got a remote branch
1480@@ -743,7 +744,7 @@
1481 'BzrDir.create_branch', ('extra/quack/', network_name),
1482 'success', ('ok', network_name, '', 'no', 'no', 'yes',
1483 reference_repo_name))
1484- a_bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
1485+ a_bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
1486 _client=client)
1487 branch = a_bzrdir.create_branch(repository=repo)
1488 # We should have got a remote branch
1489@@ -778,7 +779,7 @@
1490 'Bazaar repository format 2a (needs bzr 1.16 or later)\n',
1491 'False'),
1492 'success', ('ok', 'yes', 'yes', 'yes', network_name))
1493- a_bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
1494+ a_bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
1495 _client=client)
1496 repo = a_bzrdir.create_repository()
1497 # We should have got a remote repository
1498@@ -813,7 +814,7 @@
1499 client.add_success_response('stat', '0', '65535')
1500 remote_transport = RemoteTransport(server_url + 'quack/', medium=False,
1501 _client=client)
1502- bzrdir = RemoteBzrDir(remote_transport, remote.RemoteBzrDirFormat(),
1503+ bzrdir = RemoteBzrDir(remote_transport, RemoteBzrDirFormat(),
1504 _client=client)
1505 repo = bzrdir.open_repository()
1506 self.assertEqual(
1507@@ -846,7 +847,7 @@
1508 client.add_success_response('stat', '0', '65535')
1509 remote_transport = RemoteTransport(server_url + 'quack/', medium=False,
1510 _client=client)
1511- bzrdir = RemoteBzrDir(remote_transport, remote.RemoteBzrDirFormat(),
1512+ bzrdir = RemoteBzrDir(remote_transport, RemoteBzrDirFormat(),
1513 _client=client)
1514 repo = bzrdir.open_repository()
1515 self.assertEqual(
1516@@ -867,7 +868,7 @@
1517 transport = transport.clone('quack')
1518 client = FakeClient(transport.base)
1519 client.add_success_response('ok', '', 'no', 'no', 'no', network_name)
1520- bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
1521+ bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
1522 _client=client)
1523 repo = bzrdir.open_repository()
1524 self.assertEqual(
1525@@ -880,7 +881,7 @@
1526
1527 def test_success(self):
1528 """Simple test for typical successful call."""
1529- fmt = bzrdir.RemoteBzrDirFormat()
1530+ fmt = RemoteBzrDirFormat()
1531 default_format_name = BzrDirFormat.get_default_format().network_name()
1532 transport = self.get_transport()
1533 client = FakeClient(transport.base)
1534@@ -902,7 +903,7 @@
1535 """Error responses are translated, e.g. 'PermissionDenied' raises the
1536 corresponding error from the client.
1537 """
1538- fmt = bzrdir.RemoteBzrDirFormat()
1539+ fmt = RemoteBzrDirFormat()
1540 default_format_name = BzrDirFormat.get_default_format().network_name()
1541 transport = self.get_transport()
1542 client = FakeClient(transport.base)
1543@@ -926,7 +927,7 @@
1544 """Integration test for error translation."""
1545 transport = self.make_smart_server('foo')
1546 transport = transport.clone('no-such-path')
1547- fmt = bzrdir.RemoteBzrDirFormat()
1548+ fmt = RemoteBzrDirFormat()
1549 err = self.assertRaises(errors.NoSuchFile,
1550 fmt.initialize_on_transport_ex, transport, create_prefix=False)
1551
1552@@ -963,7 +964,7 @@
1553
1554 def make_remote_bzrdir(self, transport, client):
1555 """Make a RemotebzrDir using 'client' as the _client."""
1556- return RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
1557+ return RemoteBzrDir(transport, RemoteBzrDirFormat(),
1558 _client=client)
1559
1560
1561@@ -1296,7 +1297,7 @@
1562 client.add_expected_call(
1563 'Branch.get_stacked_on_url', ('stacked/',),
1564 'success', ('ok', vfs_url))
1565- bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
1566+ bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
1567 _client=client)
1568 repo_fmt = remote.RemoteRepositoryFormat()
1569 repo_fmt._custom_format = stacked_branch.repository._format
1570@@ -1329,7 +1330,7 @@
1571 # this will also do vfs access, but that goes direct to the transport
1572 # and isn't seen by the FakeClient.
1573 bzrdir = RemoteBzrDir(self.get_transport('stacked'),
1574- remote.RemoteBzrDirFormat(), _client=client)
1575+ RemoteBzrDirFormat(), _client=client)
1576 branch = bzrdir.open_branch()
1577 result = branch.get_stacked_on_url()
1578 self.assertEqual('../base', result)
1579@@ -1362,7 +1363,7 @@
1580 'Branch.get_stacked_on_url', ('stacked/',),
1581 'success', ('ok', '../base'))
1582 bzrdir = RemoteBzrDir(self.get_transport('stacked'),
1583- remote.RemoteBzrDirFormat(), _client=client)
1584+ RemoteBzrDirFormat(), _client=client)
1585 branch = bzrdir.open_branch()
1586 result = branch.get_stacked_on_url()
1587 self.assertEqual('../base', result)
1588@@ -1938,7 +1939,7 @@
1589 client = FakeClient(transport.base)
1590 transport = transport.clone(transport_path)
1591 # we do not want bzrdir to make any remote calls
1592- bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
1593+ bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
1594 _client=False)
1595 repo = RemoteRepository(bzrdir, None, _client=client)
1596 return repo, client
1597
1598=== modified file 'doc/en/release-notes/bzr-2.4.txt'
1599--- doc/en/release-notes/bzr-2.4.txt 2011-03-08 23:52:59 +0000
1600+++ doc/en/release-notes/bzr-2.4.txt 2011-03-11 14:21:26 +0000
1601@@ -161,6 +161,13 @@
1602 ``import_last_revision_info_and_tags`` method instead.
1603 (Andrew Bennetts)
1604
1605+* ``ControlDirFormat.register_format`` now takes an identifier argument
1606+ which can be used to unregister the format later. Control dir formats
1607+ can now be registered lazily using
1608+ ``ControlDirFormat.register_lazy_format``.
1609+ ``ControlDirFormat.unregister_format`` now takes a string rather than a
1610+ ``ControlDirFormat`` as its argument. (Jelmer Vernooij)
1611+
1612 * ``bzrlib.revionspec.dwim_revspecs`` is deprecated.
1613 Use ``bzrlib.revisionspec.RevisionSpec_dwim.append_possible_revspec`` and
1614 ``bzrlib.revisionspec.RevisionSpec_dwim.append_possible_lazy_revspec``
1615@@ -170,6 +177,10 @@
1616 indicates whether the components of the bzrdir can be upgraded
1617 independent of the ``BzrDir``. (Jelmer Vernooij)
1618
1619+* ``BzrProber.register_format`` and ``BzrProber.unregister_format`` are
1620+ now deprecated in favour of the ``BzrProber.formats`` format registry.
1621+ (Jelmer Vernooij)
1622+
1623 * ``ControlDir`` implementations no longer have to provide the ``get_branch_transport``,
1624 ``get_workingtree_transport`` and ``get_repository_transport`` methods.
1625 (Jelmer Vernooij, #730325)