/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/controldir.py

  • Committer: Jelmer Vernooij
  • Date: 2010-08-02 12:55:10 UTC
  • mto: This revision was merged to the branch mainline in revision 5389.
  • Revision ID: jelmer@samba.org-20100802125510-xc0a63b0i0c3fvob
Add dummy foreign prober.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Copyright (C) 2010 Canonical Ltd
 
2
#
 
3
# This program is free software; you can redistribute it and/or modify
 
4
# it under the terms of the GNU General Public License as published by
 
5
# the Free Software Foundation; either version 2 of the License, or
 
6
# (at your option) any later version.
 
7
#
 
8
# This program is distributed in the hope that it will be useful,
 
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
11
# GNU General Public License for more details.
 
12
#
 
13
# You should have received a copy of the GNU General Public License
 
14
# along with this program; if not, write to the Free Software
 
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 
16
 
 
17
"""ControlDir is the basic control directory class.
 
18
 
 
19
The ControlDir class is the base for the control directory used
 
20
by all bzr and foreign formats. For the ".bzr" implementation,
 
21
see bzrlib.bzrdir.BzrDir.
 
22
"""
 
23
 
 
24
from bzrlib.lazy_import import lazy_import
 
25
lazy_import(globals(), """
 
26
from bzrlib import (
 
27
    errors,
 
28
    graph,
 
29
    revision as _mod_revision,
 
30
    urlutils,
 
31
    )
 
32
from bzrlib.push import (
 
33
    PushResult,
 
34
    )
 
35
from bzrlib.trace import (
 
36
    mutter,
 
37
    )
 
38
from bzrlib.transport import (
 
39
    get_transport,
 
40
    local,
 
41
    )
 
42
 
 
43
""")
 
44
 
 
45
class ControlDir(object):
 
46
    """A control directory."""
 
47
 
 
48
    def can_convert_format(self):
 
49
        """Return true if this bzrdir is one whose format we can convert from."""
 
50
        return True
 
51
 
 
52
    def list_branches(self):
 
53
        """Return a sequence of all branches local to this control directory.
 
54
 
 
55
        """
 
56
        try:
 
57
            return [self.open_branch()]
 
58
        except (errors.NotBranchError, errors.NoRepositoryPresent):
 
59
            return []
 
60
 
 
61
    def is_control_filename(self, filename):
 
62
        """True if filename is the name of a path which is reserved for bzrdir's.
 
63
 
 
64
        :param filename: A filename within the root transport of this bzrdir.
 
65
 
 
66
        This is true IF and ONLY IF the filename is part of the namespace reserved
 
67
        for bzr control dirs. Currently this is the '.bzr' directory in the root
 
68
        of the root_transport. it is expected that plugins will need to extend
 
69
        this in the future - for instance to make bzr talk with svn working
 
70
        trees.
 
71
        """
 
72
        raise NotImplementedError(self.is_control_filename)
 
73
 
 
74
    def needs_format_conversion(self, format=None):
 
75
        """Return true if this bzrdir needs convert_format run on it.
 
76
 
 
77
        For instance, if the repository format is out of date but the
 
78
        branch and working tree are not, this should return True.
 
79
 
 
80
        :param format: Optional parameter indicating a specific desired
 
81
                       format we plan to arrive at.
 
82
        """
 
83
        raise NotImplementedError(self.needs_format_conversion)
 
84
 
 
85
    def destroy_repository(self):
 
86
        """Destroy the repository in this BzrDir"""
 
87
        raise NotImplementedError(self.destroy_repository)
 
88
 
 
89
    def create_branch(self, name=None):
 
90
        """Create a branch in this BzrDir.
 
91
 
 
92
        :param name: Name of the colocated branch to create, None for
 
93
            the default branch.
 
94
 
 
95
        The bzrdir's format will control what branch format is created.
 
96
        For more control see BranchFormatXX.create(a_bzrdir).
 
97
        """
 
98
        raise NotImplementedError(self.create_branch)
 
99
 
 
100
    def destroy_branch(self, name=None):
 
101
        """Destroy a branch in this BzrDir.
 
102
 
 
103
        :param name: Name of the branch to destroy, None for the default 
 
104
            branch.
 
105
        """
 
106
        raise NotImplementedError(self.destroy_branch)
 
107
 
 
108
    def create_workingtree(self, revision_id=None, from_branch=None,
 
109
        accelerator_tree=None, hardlink=False):
 
110
        """Create a working tree at this BzrDir.
 
111
 
 
112
        :param revision_id: create it as of this revision id.
 
113
        :param from_branch: override bzrdir branch (for lightweight checkouts)
 
114
        :param accelerator_tree: A tree which can be used for retrieving file
 
115
            contents more quickly than the revision tree, i.e. a workingtree.
 
116
            The revision tree will be used for cases where accelerator_tree's
 
117
            content is different.
 
118
        """
 
119
        raise NotImplementedError(self.create_workingtree)
 
120
 
 
121
    def destroy_workingtree(self):
 
122
        """Destroy the working tree at this BzrDir.
 
123
 
 
124
        Formats that do not support this may raise UnsupportedOperation.
 
125
        """
 
126
        raise NotImplementedError(self.destroy_workingtree)
 
127
 
 
128
    def destroy_workingtree_metadata(self):
 
129
        """Destroy the control files for the working tree at this BzrDir.
 
130
 
 
131
        The contents of working tree files are not affected.
 
132
        Formats that do not support this may raise UnsupportedOperation.
 
133
        """
 
134
        raise NotImplementedError(self.destroy_workingtree_metadata)
 
135
 
 
136
    def get_branch_reference(self, name=None):
 
137
        """Return the referenced URL for the branch in this bzrdir.
 
138
 
 
139
        :param name: Optional colocated branch name
 
140
        :raises NotBranchError: If there is no Branch.
 
141
        :raises NoColocatedBranchSupport: If a branch name was specified
 
142
            but colocated branches are not supported.
 
143
        :return: The URL the branch in this bzrdir references if it is a
 
144
            reference branch, or None for regular branches.
 
145
        """
 
146
        if name is not None:
 
147
            raise errors.NoColocatedBranchSupport(self)
 
148
        return None
 
149
 
 
150
    def get_branch_transport(self, branch_format, name=None):
 
151
        """Get the transport for use by branch format in this BzrDir.
 
152
 
 
153
        Note that bzr dirs that do not support format strings will raise
 
154
        IncompatibleFormat if the branch format they are given has
 
155
        a format string, and vice versa.
 
156
 
 
157
        If branch_format is None, the transport is returned with no
 
158
        checking. If it is not None, then the returned transport is
 
159
        guaranteed to point to an existing directory ready for use.
 
160
        """
 
161
        raise NotImplementedError(self.get_branch_transport)
 
162
 
 
163
    def get_repository_transport(self, repository_format):
 
164
        """Get the transport for use by repository format in this BzrDir.
 
165
 
 
166
        Note that bzr dirs that do not support format strings will raise
 
167
        IncompatibleFormat if the repository format they are given has
 
168
        a format string, and vice versa.
 
169
 
 
170
        If repository_format is None, the transport is returned with no
 
171
        checking. If it is not None, then the returned transport is
 
172
        guaranteed to point to an existing directory ready for use.
 
173
        """
 
174
        raise NotImplementedError(self.get_repository_transport)
 
175
 
 
176
    def get_workingtree_transport(self, tree_format):
 
177
        """Get the transport for use by workingtree format in this BzrDir.
 
178
 
 
179
        Note that bzr dirs that do not support format strings will raise
 
180
        IncompatibleFormat if the workingtree format they are given has a
 
181
        format string, and vice versa.
 
182
 
 
183
        If workingtree_format is None, the transport is returned with no
 
184
        checking. If it is not None, then the returned transport is
 
185
        guaranteed to point to an existing directory ready for use.
 
186
        """
 
187
        raise NotImplementedError(self.get_workingtree_transport)
 
188
 
 
189
    def open_branch(self, name=None, unsupported=False,
 
190
                    ignore_fallbacks=False):
 
191
        """Open the branch object at this BzrDir if one is present.
 
192
 
 
193
        If unsupported is True, then no longer supported branch formats can
 
194
        still be opened.
 
195
 
 
196
        TODO: static convenience version of this?
 
197
        """
 
198
        raise NotImplementedError(self.open_branch)
 
199
 
 
200
    def open_repository(self, _unsupported=False):
 
201
        """Open the repository object at this BzrDir if one is present.
 
202
 
 
203
        This will not follow the Branch object pointer - it's strictly a direct
 
204
        open facility. Most client code should use open_branch().repository to
 
205
        get at a repository.
 
206
 
 
207
        :param _unsupported: a private parameter, not part of the api.
 
208
        TODO: static convenience version of this?
 
209
        """
 
210
        raise NotImplementedError(self.open_repository)
 
211
 
 
212
    def find_repository(self):
 
213
        """Find the repository that should be used.
 
214
 
 
215
        This does not require a branch as we use it to find the repo for
 
216
        new branches as well as to hook existing branches up to their
 
217
        repository.
 
218
        """
 
219
        raise NotImplementedError(self.find_repository)
 
220
 
 
221
    def open_workingtree(self, _unsupported=False,
 
222
                         recommend_upgrade=True, from_branch=None):
 
223
        """Open the workingtree object at this BzrDir if one is present.
 
224
 
 
225
        :param recommend_upgrade: Optional keyword parameter, when True (the
 
226
            default), emit through the ui module a recommendation that the user
 
227
            upgrade the working tree when the workingtree being opened is old
 
228
            (but still fully supported).
 
229
        :param from_branch: override bzrdir branch (for lightweight checkouts)
 
230
        """
 
231
        raise NotImplementedError(self.open_workingtree)
 
232
 
 
233
    def has_branch(self, name=None):
 
234
        """Tell if this bzrdir contains a branch.
 
235
 
 
236
        Note: if you're going to open the branch, you should just go ahead
 
237
        and try, and not ask permission first.  (This method just opens the
 
238
        branch and discards it, and that's somewhat expensive.)
 
239
        """
 
240
        try:
 
241
            self.open_branch(name)
 
242
            return True
 
243
        except errors.NotBranchError:
 
244
            return False
 
245
 
 
246
    def has_workingtree(self):
 
247
        """Tell if this bzrdir contains a working tree.
 
248
 
 
249
        This will still raise an exception if the bzrdir has a workingtree that
 
250
        is remote & inaccessible.
 
251
 
 
252
        Note: if you're going to open the working tree, you should just go ahead
 
253
        and try, and not ask permission first.  (This method just opens the
 
254
        workingtree and discards it, and that's somewhat expensive.)
 
255
        """
 
256
        try:
 
257
            self.open_workingtree(recommend_upgrade=False)
 
258
            return True
 
259
        except errors.NoWorkingTree:
 
260
            return False
 
261
 
 
262
    def cloning_metadir(self, require_stacking=False):
 
263
        """Produce a metadir suitable for cloning or sprouting with.
 
264
 
 
265
        These operations may produce workingtrees (yes, even though they're
 
266
        "cloning" something that doesn't have a tree), so a viable workingtree
 
267
        format must be selected.
 
268
 
 
269
        :require_stacking: If True, non-stackable formats will be upgraded
 
270
            to similar stackable formats.
 
271
        :returns: a BzrDirFormat with all component formats either set
 
272
            appropriately or set to None if that component should not be
 
273
            created.
 
274
        """
 
275
        raise NotImplementedError(self.cloning_metadir)
 
276
 
 
277
    def checkout_metadir(self):
 
278
        """Produce a metadir suitable for checkouts of this controldir."""
 
279
        return self.cloning_metadir()
 
280
 
 
281
    def sprout(self, url, revision_id=None, force_new_repo=False,
 
282
               recurse='down', possible_transports=None,
 
283
               accelerator_tree=None, hardlink=False, stacked=False,
 
284
               source_branch=None, create_tree_if_local=True):
 
285
        """Create a copy of this bzrdir prepared for use as a new line of
 
286
        development.
 
287
 
 
288
        If url's last component does not exist, it will be created.
 
289
 
 
290
        Attributes related to the identity of the source branch like
 
291
        branch nickname will be cleaned, a working tree is created
 
292
        whether one existed before or not; and a local branch is always
 
293
        created.
 
294
 
 
295
        if revision_id is not None, then the clone operation may tune
 
296
            itself to download less data.
 
297
        :param accelerator_tree: A tree which can be used for retrieving file
 
298
            contents more quickly than the revision tree, i.e. a workingtree.
 
299
            The revision tree will be used for cases where accelerator_tree's
 
300
            content is different.
 
301
        :param hardlink: If true, hard-link files from accelerator_tree,
 
302
            where possible.
 
303
        :param stacked: If true, create a stacked branch referring to the
 
304
            location of this control directory.
 
305
        :param create_tree_if_local: If true, a working-tree will be created
 
306
            when working locally.
 
307
        """
 
308
        target_transport = get_transport(url, possible_transports)
 
309
        target_transport.ensure_base()
 
310
        cloning_format = self.cloning_metadir(stacked)
 
311
        # Create/update the result branch
 
312
        result = cloning_format.initialize_on_transport(target_transport)
 
313
        # if a stacked branch wasn't requested, we don't create one
 
314
        # even if the origin was stacked
 
315
        stacked_branch_url = None
 
316
        if source_branch is not None:
 
317
            if stacked:
 
318
                stacked_branch_url = self.root_transport.base
 
319
            source_repository = source_branch.repository
 
320
        else:
 
321
            try:
 
322
                source_branch = self.open_branch()
 
323
                source_repository = source_branch.repository
 
324
                if stacked:
 
325
                    stacked_branch_url = self.root_transport.base
 
326
            except errors.NotBranchError:
 
327
                source_branch = None
 
328
                try:
 
329
                    source_repository = self.open_repository()
 
330
                except errors.NoRepositoryPresent:
 
331
                    source_repository = None
 
332
        repository_policy = result.determine_repository_policy(
 
333
            force_new_repo, stacked_branch_url, require_stacking=stacked)
 
334
        result_repo, is_new_repo = repository_policy.acquire_repository()
 
335
        is_stacked = stacked or (len(result_repo._fallback_repositories) != 0)
 
336
        if is_new_repo and revision_id is not None and not is_stacked:
 
337
            fetch_spec = graph.PendingAncestryResult(
 
338
                [revision_id], source_repository)
 
339
        else:
 
340
            fetch_spec = None
 
341
        if source_repository is not None:
 
342
            # Fetch while stacked to prevent unstacked fetch from
 
343
            # Branch.sprout.
 
344
            if fetch_spec is None:
 
345
                result_repo.fetch(source_repository, revision_id=revision_id)
 
346
            else:
 
347
                result_repo.fetch(source_repository, fetch_spec=fetch_spec)
 
348
 
 
349
        if source_branch is None:
 
350
            # this is for sprouting a bzrdir without a branch; is that
 
351
            # actually useful?
 
352
            # Not especially, but it's part of the contract.
 
353
            result_branch = result.create_branch()
 
354
        else:
 
355
            result_branch = source_branch.sprout(result,
 
356
                revision_id=revision_id, repository_policy=repository_policy)
 
357
        mutter("created new branch %r" % (result_branch,))
 
358
 
 
359
        # Create/update the result working tree
 
360
        if (create_tree_if_local and
 
361
            isinstance(target_transport, local.LocalTransport) and
 
362
            (result_repo is None or result_repo.make_working_trees())):
 
363
            wt = result.create_workingtree(accelerator_tree=accelerator_tree,
 
364
                hardlink=hardlink)
 
365
            wt.lock_write()
 
366
            try:
 
367
                if wt.path2id('') is None:
 
368
                    try:
 
369
                        wt.set_root_id(self.open_workingtree.get_root_id())
 
370
                    except errors.NoWorkingTree:
 
371
                        pass
 
372
            finally:
 
373
                wt.unlock()
 
374
        else:
 
375
            wt = None
 
376
        if recurse == 'down':
 
377
            if wt is not None:
 
378
                basis = wt.basis_tree()
 
379
                basis.lock_read()
 
380
                subtrees = basis.iter_references()
 
381
            elif result_branch is not None:
 
382
                basis = result_branch.basis_tree()
 
383
                basis.lock_read()
 
384
                subtrees = basis.iter_references()
 
385
            elif source_branch is not None:
 
386
                basis = source_branch.basis_tree()
 
387
                basis.lock_read()
 
388
                subtrees = basis.iter_references()
 
389
            else:
 
390
                subtrees = []
 
391
                basis = None
 
392
            try:
 
393
                for path, file_id in subtrees:
 
394
                    target = urlutils.join(url, urlutils.escape(path))
 
395
                    sublocation = source_branch.reference_parent(file_id, path)
 
396
                    sublocation.bzrdir.sprout(target,
 
397
                        basis.get_reference_revision(file_id, path),
 
398
                        force_new_repo=force_new_repo, recurse=recurse,
 
399
                        stacked=stacked)
 
400
            finally:
 
401
                if basis is not None:
 
402
                    basis.unlock()
 
403
        return result
 
404
 
 
405
    def push_branch(self, source, revision_id=None, overwrite=False, 
 
406
        remember=False, create_prefix=False):
 
407
        """Push the source branch into this BzrDir."""
 
408
        br_to = None
 
409
        # If we can open a branch, use its direct repository, otherwise see
 
410
        # if there is a repository without a branch.
 
411
        try:
 
412
            br_to = self.open_branch()
 
413
        except errors.NotBranchError:
 
414
            # Didn't find a branch, can we find a repository?
 
415
            repository_to = self.find_repository()
 
416
        else:
 
417
            # Found a branch, so we must have found a repository
 
418
            repository_to = br_to.repository
 
419
 
 
420
        push_result = PushResult()
 
421
        push_result.source_branch = source
 
422
        if br_to is None:
 
423
            # We have a repository but no branch, copy the revisions, and then
 
424
            # create a branch.
 
425
            repository_to.fetch(source.repository, revision_id=revision_id)
 
426
            br_to = source.clone(self, revision_id=revision_id)
 
427
            if source.get_push_location() is None or remember:
 
428
                source.set_push_location(br_to.base)
 
429
            push_result.stacked_on = None
 
430
            push_result.branch_push_result = None
 
431
            push_result.old_revno = None
 
432
            push_result.old_revid = _mod_revision.NULL_REVISION
 
433
            push_result.target_branch = br_to
 
434
            push_result.master_branch = None
 
435
            push_result.workingtree_updated = False
 
436
        else:
 
437
            # We have successfully opened the branch, remember if necessary:
 
438
            if source.get_push_location() is None or remember:
 
439
                source.set_push_location(br_to.base)
 
440
            try:
 
441
                tree_to = self.open_workingtree()
 
442
            except errors.NotLocalUrl:
 
443
                push_result.branch_push_result = source.push(br_to, 
 
444
                    overwrite, stop_revision=revision_id)
 
445
                push_result.workingtree_updated = False
 
446
            except errors.NoWorkingTree:
 
447
                push_result.branch_push_result = source.push(br_to,
 
448
                    overwrite, stop_revision=revision_id)
 
449
                push_result.workingtree_updated = None # Not applicable
 
450
            else:
 
451
                tree_to.lock_write()
 
452
                try:
 
453
                    push_result.branch_push_result = source.push(
 
454
                        tree_to.branch, overwrite, stop_revision=revision_id)
 
455
                    tree_to.update()
 
456
                finally:
 
457
                    tree_to.unlock()
 
458
                push_result.workingtree_updated = True
 
459
            push_result.old_revno = push_result.branch_push_result.old_revno
 
460
            push_result.old_revid = push_result.branch_push_result.old_revid
 
461
            push_result.target_branch = \
 
462
                push_result.branch_push_result.target_branch
 
463
        return push_result
 
464
 
 
465
 
 
466
class ControlDirFormat(object):
 
467
    """An encapsulation of the initialization and open routines for a format.
 
468
 
 
469
    Formats provide three things:
 
470
     * An initialization routine,
 
471
     * a format string,
 
472
     * an open routine.
 
473
 
 
474
    Formats are placed in a dict by their format string for reference
 
475
    during bzrdir opening. These should be subclasses of BzrDirFormat
 
476
    for consistency.
 
477
 
 
478
    Once a format is deprecated, just deprecate the initialize and open
 
479
    methods on the format class. Do not deprecate the object, as the
 
480
    object will be created every system load.
 
481
 
 
482
    :cvar colocated_branches: Whether this formats supports colocated branches.
 
483
    """
 
484
 
 
485
    _default_format = None
 
486
    """The default format used for new control directories."""
 
487
 
 
488
    _formats = []
 
489
    """The registered control formats - .bzr, ....
 
490
 
 
491
    This is a list of ControlDirFormat objects.
 
492
    """
 
493
 
 
494
    _server_formats = []
 
495
    """The registered control server formats, e.g. RemoteBzrDirs.
 
496
 
 
497
    This is a list of ControlDirFormat objects.
 
498
    """
 
499
 
 
500
    colocated_branches = False
 
501
    """Whether co-located branches are supported for this control dir format.
 
502
    """
 
503
 
 
504
    def get_format_description(self):
 
505
        """Return the short description for this format."""
 
506
        raise NotImplementedError(self.get_format_description)
 
507
 
 
508
    def get_converter(self, format=None):
 
509
        """Return the converter to use to convert bzrdirs needing converts.
 
510
 
 
511
        This returns a bzrlib.bzrdir.Converter object.
 
512
 
 
513
        This should return the best upgrader to step this format towards the
 
514
        current default format. In the case of plugins we can/should provide
 
515
        some means for them to extend the range of returnable converters.
 
516
 
 
517
        :param format: Optional format to override the default format of the
 
518
                       library.
 
519
        """
 
520
        raise NotImplementedError(self.get_converter)
 
521
 
 
522
    def is_supported(self):
 
523
        """Is this format supported?
 
524
 
 
525
        Supported formats must be initializable and openable.
 
526
        Unsupported formats may not support initialization or committing or
 
527
        some other features depending on the reason for not being supported.
 
528
        """
 
529
        return True
 
530
 
 
531
    def same_model(self, target_format):
 
532
        return (self.repository_format.rich_root_data ==
 
533
            target_format.rich_root_data)
 
534
 
 
535
    @classmethod
 
536
    def register_format(klass, format):
 
537
        """Register a format that does not use '.bzr' for its control dir.
 
538
 
 
539
        TODO: This should be pulled up into a 'ControlDirFormat' base class
 
540
        which BzrDirFormat can inherit from, and renamed to register_format
 
541
        there. It has been done without that for now for simplicity of
 
542
        implementation.
 
543
        """
 
544
        klass._formats.append(format)
 
545
 
 
546
    @classmethod
 
547
    def register_server_format(klass, format):
 
548
        """Register a control format for client-server environments.
 
549
 
 
550
        These formats will be tried before ones registered with
 
551
        register_format.  This gives implementations that decide to the
 
552
        chance to grab it before anything looks at the contents of the format
 
553
        file.
 
554
        """
 
555
        klass._server_formats.append(format)
 
556
 
 
557
    def __str__(self):
 
558
        # Trim the newline
 
559
        return self.get_format_description().rstrip()
 
560
 
 
561
    @classmethod
 
562
    def unregister_format(klass, format):
 
563
        klass._formats.remove(format)
 
564
 
 
565
    @classmethod
 
566
    def known_formats(klass):
 
567
        """Return all the known formats.
 
568
        """
 
569
        return set(klass._formats)
 
570
 
 
571
    @classmethod
 
572
    def find_format(klass, transport, _server_formats=True):
 
573
        """Return the format present at transport."""
 
574
        if _server_formats:
 
575
            _probers = server_probers = probers
 
576
        else:
 
577
            _probers = probers
 
578
        for prober_kls in _probers:
 
579
            prober = prober_kls()
 
580
            try:
 
581
                return prober.probe_transport(transport)
 
582
            except errors.NotBranchError:
 
583
                # this format does not find a control dir here.
 
584
                pass
 
585
        raise errors.NotBranchError(path=transport.base)
 
586
 
 
587
    def initialize(self, url, possible_transports=None):
 
588
        """Create a control dir at this url and return an opened copy.
 
589
 
 
590
        While not deprecated, this method is very specific and its use will
 
591
        lead to many round trips to setup a working environment. See
 
592
        initialize_on_transport_ex for a [nearly] all-in-one method.
 
593
 
 
594
        Subclasses should typically override initialize_on_transport
 
595
        instead of this method.
 
596
        """
 
597
        return self.initialize_on_transport(get_transport(url,
 
598
                                                          possible_transports))
 
599
    def initialize_on_transport(self, transport):
 
600
        """Initialize a new bzrdir in the base directory of a Transport."""
 
601
        raise NotImplementedError(self.initialize_on_transport)
 
602
 
 
603
    def initialize_on_transport_ex(self, transport, use_existing_dir=False,
 
604
        create_prefix=False, force_new_repo=False, stacked_on=None,
 
605
        stack_on_pwd=None, repo_format_name=None, make_working_trees=None,
 
606
        shared_repo=False, vfs_only=False):
 
607
        """Create this format on transport.
 
608
 
 
609
        The directory to initialize will be created.
 
610
 
 
611
        :param force_new_repo: Do not use a shared repository for the target,
 
612
                               even if one is available.
 
613
        :param create_prefix: Create any missing directories leading up to
 
614
            to_transport.
 
615
        :param use_existing_dir: Use an existing directory if one exists.
 
616
        :param stacked_on: A url to stack any created branch on, None to follow
 
617
            any target stacking policy.
 
618
        :param stack_on_pwd: If stack_on is relative, the location it is
 
619
            relative to.
 
620
        :param repo_format_name: If non-None, a repository will be
 
621
            made-or-found. Should none be found, or if force_new_repo is True
 
622
            the repo_format_name is used to select the format of repository to
 
623
            create.
 
624
        :param make_working_trees: Control the setting of make_working_trees
 
625
            for a new shared repository when one is made. None to use whatever
 
626
            default the format has.
 
627
        :param shared_repo: Control whether made repositories are shared or
 
628
            not.
 
629
        :param vfs_only: If True do not attempt to use a smart server
 
630
        :return: repo, bzrdir, require_stacking, repository_policy. repo is
 
631
            None if none was created or found, bzrdir is always valid.
 
632
            require_stacking is the result of examining the stacked_on
 
633
            parameter and any stacking policy found for the target.
 
634
        """
 
635
        raise NotImplementedError(self.initialize_on_transport_ex)
 
636
 
 
637
    def network_name(self):
 
638
        """A simple byte string uniquely identifying this format for RPC calls.
 
639
 
 
640
        Bzr control formats use this disk format string to identify the format
 
641
        over the wire. Its possible that other control formats have more
 
642
        complex detection requirements, so we permit them to use any unique and
 
643
        immutable string they desire.
 
644
        """
 
645
        raise NotImplementedError(self.network_name)
 
646
 
 
647
    def open(self, transport, _found=False):
 
648
        """Return an instance of this format for the dir transport points at.
 
649
        """
 
650
        raise NotImplementedError(self.open)
 
651
 
 
652
    @classmethod
 
653
    def _set_default_format(klass, format):
 
654
        """Set default format (for testing behavior of defaults only)"""
 
655
        klass._default_format = format
 
656
 
 
657
    @classmethod
 
658
    def get_default_format(klass):
 
659
        """Return the current default format."""
 
660
        return klass._default_format
 
661
 
 
662
 
 
663
class Prober(object):
 
664
 
 
665
    def probe_transport(self, transport):
 
666
        """Return the controldir style format present in a directory."""
 
667
        raise NotImplementedError(self.probe_transport)
 
668
 
 
669
 
 
670
probers = []
 
671
server_probers = []