~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/controldir.py

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
 
 
25
 
from bzrlib.lazy_import import lazy_import
26
 
lazy_import(globals(), """
27
 
import textwrap
28
 
 
29
 
from bzrlib import (
30
 
    cleanup,
31
 
    errors,
32
 
    graph,
33
 
    revision as _mod_revision,
34
 
    urlutils,
35
 
    )
36
 
from bzrlib.push import (
37
 
    PushResult,
38
 
    )
39
 
from bzrlib.trace import (
40
 
    mutter,
41
 
    )
42
 
from bzrlib.transport import (
43
 
    get_transport,
44
 
    local,
45
 
    )
46
 
 
47
 
""")
48
 
 
49
 
from bzrlib import registry
50
 
 
51
 
 
52
 
class ControlComponent(object):
53
 
    """Abstract base class for control directory components.
54
 
 
55
 
    This provides interfaces that are common across controldirs,
56
 
    repositories, branches, and workingtree control directories.
57
 
 
58
 
    They all expose two urls and transports: the *user* URL is the
59
 
    one that stops above the control directory (eg .bzr) and that
60
 
    should normally be used in messages, and the *control* URL is
61
 
    under that in eg .bzr/checkout and is used to read the control
62
 
    files.
63
 
 
64
 
    This can be used as a mixin and is intended to fit with
65
 
    foreign formats.
66
 
    """
67
 
 
68
 
    @property
69
 
    def control_transport(self):
70
 
        raise NotImplementedError
71
 
 
72
 
    @property
73
 
    def control_url(self):
74
 
        return self.control_transport.base
75
 
 
76
 
    @property
77
 
    def user_transport(self):
78
 
        raise NotImplementedError
79
 
 
80
 
    @property
81
 
    def user_url(self):
82
 
        return self.user_transport.base
83
 
 
84
 
 
85
 
class ControlDir(ControlComponent):
86
 
    """A control directory.
87
 
 
88
 
    While this represents a generic control directory, there are a few
89
 
    features that are present in this interface that are currently only
90
 
    supported by one of its implementations, BzrDir.
91
 
 
92
 
    These features (bound branches, stacked branches) are currently only
93
 
    supported by Bazaar, but could be supported by other version control
94
 
    systems as well. Implementations are required to raise the appropriate
95
 
    exceptions when an operation is requested that is not supported.
96
 
 
97
 
    This also makes life easier for API users who can rely on the
98
 
    implementation always allowing a particular feature to be requested but
99
 
    raising an exception when it is not supported, rather than requiring the
100
 
    API users to check for magic attributes to see what features are supported.
101
 
    """
102
 
 
103
 
    def can_convert_format(self):
104
 
        """Return true if this controldir is one whose format we can convert
105
 
        from."""
106
 
        return True
107
 
 
108
 
    def list_branches(self):
109
 
        """Return a sequence of all branches local to this control directory.
110
 
 
111
 
        """
112
 
        try:
113
 
            return [self.open_branch()]
114
 
        except (errors.NotBranchError, errors.NoRepositoryPresent):
115
 
            return []
116
 
 
117
 
    def is_control_filename(self, filename):
118
 
        """True if filename is the name of a path which is reserved for
119
 
        controldirs.
120
 
 
121
 
        :param filename: A filename within the root transport of this
122
 
            controldir.
123
 
 
124
 
        This is true IF and ONLY IF the filename is part of the namespace reserved
125
 
        for bzr control dirs. Currently this is the '.bzr' directory in the root
126
 
        of the root_transport. it is expected that plugins will need to extend
127
 
        this in the future - for instance to make bzr talk with svn working
128
 
        trees.
129
 
        """
130
 
        raise NotImplementedError(self.is_control_filename)
131
 
 
132
 
    def needs_format_conversion(self, format=None):
133
 
        """Return true if this controldir needs convert_format run on it.
134
 
 
135
 
        For instance, if the repository format is out of date but the
136
 
        branch and working tree are not, this should return True.
137
 
 
138
 
        :param format: Optional parameter indicating a specific desired
139
 
                       format we plan to arrive at.
140
 
        """
141
 
        raise NotImplementedError(self.needs_format_conversion)
142
 
 
143
 
    def destroy_repository(self):
144
 
        """Destroy the repository in this ControlDir."""
145
 
        raise NotImplementedError(self.destroy_repository)
146
 
 
147
 
    def create_branch(self, name=None, repository=None):
148
 
        """Create a branch in this ControlDir.
149
 
 
150
 
        :param name: Name of the colocated branch to create, None for
151
 
            the default branch.
152
 
 
153
 
        The controldirs format will control what branch format is created.
154
 
        For more control see BranchFormatXX.create(a_controldir).
155
 
        """
156
 
        raise NotImplementedError(self.create_branch)
157
 
 
158
 
    def destroy_branch(self, name=None):
159
 
        """Destroy a branch in this ControlDir.
160
 
 
161
 
        :param name: Name of the branch to destroy, None for the default 
162
 
            branch.
163
 
        """
164
 
        raise NotImplementedError(self.destroy_branch)
165
 
 
166
 
    def create_workingtree(self, revision_id=None, from_branch=None,
167
 
        accelerator_tree=None, hardlink=False):
168
 
        """Create a working tree at this ControlDir.
169
 
 
170
 
        :param revision_id: create it as of this revision id.
171
 
        :param from_branch: override controldir branch 
172
 
            (for lightweight checkouts)
173
 
        :param accelerator_tree: A tree which can be used for retrieving file
174
 
            contents more quickly than the revision tree, i.e. a workingtree.
175
 
            The revision tree will be used for cases where accelerator_tree's
176
 
            content is different.
177
 
        """
178
 
        raise NotImplementedError(self.create_workingtree)
179
 
 
180
 
    def destroy_workingtree(self):
181
 
        """Destroy the working tree at this ControlDir.
182
 
 
183
 
        Formats that do not support this may raise UnsupportedOperation.
184
 
        """
185
 
        raise NotImplementedError(self.destroy_workingtree)
186
 
 
187
 
    def destroy_workingtree_metadata(self):
188
 
        """Destroy the control files for the working tree at this ControlDir.
189
 
 
190
 
        The contents of working tree files are not affected.
191
 
        Formats that do not support this may raise UnsupportedOperation.
192
 
        """
193
 
        raise NotImplementedError(self.destroy_workingtree_metadata)
194
 
 
195
 
    def get_branch_reference(self, name=None):
196
 
        """Return the referenced URL for the branch in this controldir.
197
 
 
198
 
        :param name: Optional colocated branch name
199
 
        :raises NotBranchError: If there is no Branch.
200
 
        :raises NoColocatedBranchSupport: If a branch name was specified
201
 
            but colocated branches are not supported.
202
 
        :return: The URL the branch in this controldir references if it is a
203
 
            reference branch, or None for regular branches.
204
 
        """
205
 
        if name is not None:
206
 
            raise errors.NoColocatedBranchSupport(self)
207
 
        return None
208
 
 
209
 
    def get_branch_transport(self, branch_format, name=None):
210
 
        """Get the transport for use by branch format in this ControlDir.
211
 
 
212
 
        Note that bzr dirs that do not support format strings will raise
213
 
        IncompatibleFormat if the branch format they are given has
214
 
        a format string, and vice versa.
215
 
 
216
 
        If branch_format is None, the transport is returned with no
217
 
        checking. If it is not None, then the returned transport is
218
 
        guaranteed to point to an existing directory ready for use.
219
 
        """
220
 
        raise NotImplementedError(self.get_branch_transport)
221
 
 
222
 
    def get_repository_transport(self, repository_format):
223
 
        """Get the transport for use by repository format in this ControlDir.
224
 
 
225
 
        Note that bzr dirs that do not support format strings will raise
226
 
        IncompatibleFormat if the repository format they are given has
227
 
        a format string, and vice versa.
228
 
 
229
 
        If repository_format is None, the transport is returned with no
230
 
        checking. If it is not None, then the returned transport is
231
 
        guaranteed to point to an existing directory ready for use.
232
 
        """
233
 
        raise NotImplementedError(self.get_repository_transport)
234
 
 
235
 
    def get_workingtree_transport(self, tree_format):
236
 
        """Get the transport for use by workingtree format in this ControlDir.
237
 
 
238
 
        Note that bzr dirs that do not support format strings will raise
239
 
        IncompatibleFormat if the workingtree format they are given has a
240
 
        format string, and vice versa.
241
 
 
242
 
        If workingtree_format is None, the transport is returned with no
243
 
        checking. If it is not None, then the returned transport is
244
 
        guaranteed to point to an existing directory ready for use.
245
 
        """
246
 
        raise NotImplementedError(self.get_workingtree_transport)
247
 
 
248
 
    def open_branch(self, name=None, unsupported=False,
249
 
                    ignore_fallbacks=False):
250
 
        """Open the branch object at this ControlDir if one is present.
251
 
 
252
 
        If unsupported is True, then no longer supported branch formats can
253
 
        still be opened.
254
 
 
255
 
        TODO: static convenience version of this?
256
 
        """
257
 
        raise NotImplementedError(self.open_branch)
258
 
 
259
 
    def open_repository(self, _unsupported=False):
260
 
        """Open the repository object at this ControlDir if one is present.
261
 
 
262
 
        This will not follow the Branch object pointer - it's strictly a direct
263
 
        open facility. Most client code should use open_branch().repository to
264
 
        get at a repository.
265
 
 
266
 
        :param _unsupported: a private parameter, not part of the api.
267
 
        TODO: static convenience version of this?
268
 
        """
269
 
        raise NotImplementedError(self.open_repository)
270
 
 
271
 
    def find_repository(self):
272
 
        """Find the repository that should be used.
273
 
 
274
 
        This does not require a branch as we use it to find the repo for
275
 
        new branches as well as to hook existing branches up to their
276
 
        repository.
277
 
        """
278
 
        raise NotImplementedError(self.find_repository)
279
 
 
280
 
    def open_workingtree(self, _unsupported=False,
281
 
                         recommend_upgrade=True, from_branch=None):
282
 
        """Open the workingtree object at this ControlDir if one is present.
283
 
 
284
 
        :param recommend_upgrade: Optional keyword parameter, when True (the
285
 
            default), emit through the ui module a recommendation that the user
286
 
            upgrade the working tree when the workingtree being opened is old
287
 
            (but still fully supported).
288
 
        :param from_branch: override controldir branch (for lightweight
289
 
            checkouts)
290
 
        """
291
 
        raise NotImplementedError(self.open_workingtree)
292
 
 
293
 
    def has_branch(self, name=None):
294
 
        """Tell if this controldir contains a branch.
295
 
 
296
 
        Note: if you're going to open the branch, you should just go ahead
297
 
        and try, and not ask permission first.  (This method just opens the
298
 
        branch and discards it, and that's somewhat expensive.)
299
 
        """
300
 
        try:
301
 
            self.open_branch(name)
302
 
            return True
303
 
        except errors.NotBranchError:
304
 
            return False
305
 
 
306
 
    def has_workingtree(self):
307
 
        """Tell if this controldir contains a working tree.
308
 
 
309
 
        This will still raise an exception if the controldir has a workingtree
310
 
        that is remote & inaccessible.
311
 
 
312
 
        Note: if you're going to open the working tree, you should just go ahead
313
 
        and try, and not ask permission first.  (This method just opens the
314
 
        workingtree and discards it, and that's somewhat expensive.)
315
 
        """
316
 
        try:
317
 
            self.open_workingtree(recommend_upgrade=False)
318
 
            return True
319
 
        except errors.NoWorkingTree:
320
 
            return False
321
 
 
322
 
    def cloning_metadir(self, require_stacking=False):
323
 
        """Produce a metadir suitable for cloning or sprouting with.
324
 
 
325
 
        These operations may produce workingtrees (yes, even though they're
326
 
        "cloning" something that doesn't have a tree), so a viable workingtree
327
 
        format must be selected.
328
 
 
329
 
        :require_stacking: If True, non-stackable formats will be upgraded
330
 
            to similar stackable formats.
331
 
        :returns: a ControlDirFormat with all component formats either set
332
 
            appropriately or set to None if that component should not be
333
 
            created.
334
 
        """
335
 
        raise NotImplementedError(self.cloning_metadir)
336
 
 
337
 
    def checkout_metadir(self):
338
 
        """Produce a metadir suitable for checkouts of this controldir."""
339
 
        return self.cloning_metadir()
340
 
 
341
 
    def sprout(self, url, revision_id=None, force_new_repo=False,
342
 
               recurse='down', possible_transports=None,
343
 
               accelerator_tree=None, hardlink=False, stacked=False,
344
 
               source_branch=None, create_tree_if_local=True):
345
 
        """Create a copy of this controldir prepared for use as a new line of
346
 
        development.
347
 
 
348
 
        If url's last component does not exist, it will be created.
349
 
 
350
 
        Attributes related to the identity of the source branch like
351
 
        branch nickname will be cleaned, a working tree is created
352
 
        whether one existed before or not; and a local branch is always
353
 
        created.
354
 
 
355
 
        if revision_id is not None, then the clone operation may tune
356
 
            itself to download less data.
357
 
        :param accelerator_tree: A tree which can be used for retrieving file
358
 
            contents more quickly than the revision tree, i.e. a workingtree.
359
 
            The revision tree will be used for cases where accelerator_tree's
360
 
            content is different.
361
 
        :param hardlink: If true, hard-link files from accelerator_tree,
362
 
            where possible.
363
 
        :param stacked: If true, create a stacked branch referring to the
364
 
            location of this control directory.
365
 
        :param create_tree_if_local: If true, a working-tree will be created
366
 
            when working locally.
367
 
        """
368
 
        operation = cleanup.OperationWithCleanups(self._sprout)
369
 
        return operation.run(url, revision_id=revision_id,
370
 
            force_new_repo=force_new_repo, recurse=recurse,
371
 
            possible_transports=possible_transports,
372
 
            accelerator_tree=accelerator_tree, hardlink=hardlink,
373
 
            stacked=stacked, source_branch=source_branch,
374
 
            create_tree_if_local=create_tree_if_local)
375
 
 
376
 
    def _sprout(self, op, url, revision_id=None, force_new_repo=False,
377
 
               recurse='down', possible_transports=None,
378
 
               accelerator_tree=None, hardlink=False, stacked=False,
379
 
               source_branch=None, create_tree_if_local=True):
380
 
        add_cleanup = op.add_cleanup
381
 
        target_transport = get_transport(url, possible_transports)
382
 
        target_transport.ensure_base()
383
 
        cloning_format = self.cloning_metadir(stacked)
384
 
        # Create/update the result branch
385
 
        result = cloning_format.initialize_on_transport(target_transport)
386
 
        # if a stacked branch wasn't requested, we don't create one
387
 
        # even if the origin was stacked
388
 
        stacked_branch_url = None
389
 
        if source_branch is not None:
390
 
            add_cleanup(source_branch.lock_read().unlock)
391
 
            if stacked:
392
 
                stacked_branch_url = self.root_transport.base
393
 
            source_repository = source_branch.repository
394
 
        else:
395
 
            try:
396
 
                source_branch = self.open_branch()
397
 
                source_repository = source_branch.repository
398
 
                if stacked:
399
 
                    stacked_branch_url = self.root_transport.base
400
 
            except errors.NotBranchError:
401
 
                source_branch = None
402
 
                try:
403
 
                    source_repository = self.open_repository()
404
 
                except errors.NoRepositoryPresent:
405
 
                    source_repository = None
406
 
                else:
407
 
                    add_cleanup(source_repository.lock_read().unlock)
408
 
            else:
409
 
                add_cleanup(source_branch.lock_read().unlock)
410
 
        repository_policy = result.determine_repository_policy(
411
 
            force_new_repo, stacked_branch_url, require_stacking=stacked)
412
 
        result_repo, is_new_repo = repository_policy.acquire_repository()
413
 
        add_cleanup(result_repo.lock_write().unlock)
414
 
        is_stacked = stacked or (len(result_repo._fallback_repositories) != 0)
415
 
        if is_new_repo and revision_id is not None and not is_stacked:
416
 
            fetch_spec = graph.PendingAncestryResult(
417
 
                [revision_id], source_repository)
418
 
        else:
419
 
            fetch_spec = None
420
 
        if source_repository is not None:
421
 
            # Fetch while stacked to prevent unstacked fetch from
422
 
            # Branch.sprout.
423
 
            if fetch_spec is None:
424
 
                result_repo.fetch(source_repository, revision_id=revision_id)
425
 
            else:
426
 
                result_repo.fetch(source_repository, fetch_spec=fetch_spec)
427
 
 
428
 
        if source_branch is None:
429
 
            # this is for sprouting a controldir without a branch; is that
430
 
            # actually useful?
431
 
            # Not especially, but it's part of the contract.
432
 
            result_branch = result.create_branch()
433
 
        else:
434
 
            result_branch = source_branch.sprout(result,
435
 
                revision_id=revision_id, repository_policy=repository_policy,
436
 
                repository=result_repo)
437
 
        mutter("created new branch %r" % (result_branch,))
438
 
 
439
 
        # Create/update the result working tree
440
 
        if (create_tree_if_local and
441
 
            isinstance(target_transport, local.LocalTransport) and
442
 
            (result_repo is None or result_repo.make_working_trees())):
443
 
            wt = result.create_workingtree(accelerator_tree=accelerator_tree,
444
 
                hardlink=hardlink, from_branch=result_branch)
445
 
            wt.lock_write()
446
 
            try:
447
 
                if wt.path2id('') is None:
448
 
                    try:
449
 
                        wt.set_root_id(self.open_workingtree.get_root_id())
450
 
                    except errors.NoWorkingTree:
451
 
                        pass
452
 
            finally:
453
 
                wt.unlock()
454
 
        else:
455
 
            wt = None
456
 
        if recurse == 'down':
457
 
            if wt is not None:
458
 
                basis = wt.basis_tree()
459
 
                basis.lock_read()
460
 
                subtrees = basis.iter_references()
461
 
            elif result_branch is not None:
462
 
                basis = result_branch.basis_tree()
463
 
                basis.lock_read()
464
 
                subtrees = basis.iter_references()
465
 
            elif source_branch is not None:
466
 
                basis = source_branch.basis_tree()
467
 
                basis.lock_read()
468
 
                subtrees = basis.iter_references()
469
 
            else:
470
 
                subtrees = []
471
 
                basis = None
472
 
            try:
473
 
                for path, file_id in subtrees:
474
 
                    target = urlutils.join(url, urlutils.escape(path))
475
 
                    sublocation = source_branch.reference_parent(file_id, path)
476
 
                    sublocation.bzrdir.sprout(target,
477
 
                        basis.get_reference_revision(file_id, path),
478
 
                        force_new_repo=force_new_repo, recurse=recurse,
479
 
                        stacked=stacked)
480
 
            finally:
481
 
                if basis is not None:
482
 
                    basis.unlock()
483
 
        return result
484
 
 
485
 
    def push_branch(self, source, revision_id=None, overwrite=False, 
486
 
        remember=False, create_prefix=False):
487
 
        """Push the source branch into this ControlDir."""
488
 
        br_to = None
489
 
        # If we can open a branch, use its direct repository, otherwise see
490
 
        # if there is a repository without a branch.
491
 
        try:
492
 
            br_to = self.open_branch()
493
 
        except errors.NotBranchError:
494
 
            # Didn't find a branch, can we find a repository?
495
 
            repository_to = self.find_repository()
496
 
        else:
497
 
            # Found a branch, so we must have found a repository
498
 
            repository_to = br_to.repository
499
 
 
500
 
        push_result = PushResult()
501
 
        push_result.source_branch = source
502
 
        if br_to is None:
503
 
            # We have a repository but no branch, copy the revisions, and then
504
 
            # create a branch.
505
 
            repository_to.fetch(source.repository, revision_id=revision_id)
506
 
            br_to = source.clone(self, revision_id=revision_id)
507
 
            if source.get_push_location() is None or remember:
508
 
                source.set_push_location(br_to.base)
509
 
            push_result.stacked_on = None
510
 
            push_result.branch_push_result = None
511
 
            push_result.old_revno = None
512
 
            push_result.old_revid = _mod_revision.NULL_REVISION
513
 
            push_result.target_branch = br_to
514
 
            push_result.master_branch = None
515
 
            push_result.workingtree_updated = False
516
 
        else:
517
 
            # We have successfully opened the branch, remember if necessary:
518
 
            if source.get_push_location() is None or remember:
519
 
                source.set_push_location(br_to.base)
520
 
            try:
521
 
                tree_to = self.open_workingtree()
522
 
            except errors.NotLocalUrl:
523
 
                push_result.branch_push_result = source.push(br_to, 
524
 
                    overwrite, stop_revision=revision_id)
525
 
                push_result.workingtree_updated = False
526
 
            except errors.NoWorkingTree:
527
 
                push_result.branch_push_result = source.push(br_to,
528
 
                    overwrite, stop_revision=revision_id)
529
 
                push_result.workingtree_updated = None # Not applicable
530
 
            else:
531
 
                tree_to.lock_write()
532
 
                try:
533
 
                    push_result.branch_push_result = source.push(
534
 
                        tree_to.branch, overwrite, stop_revision=revision_id)
535
 
                    tree_to.update()
536
 
                finally:
537
 
                    tree_to.unlock()
538
 
                push_result.workingtree_updated = True
539
 
            push_result.old_revno = push_result.branch_push_result.old_revno
540
 
            push_result.old_revid = push_result.branch_push_result.old_revid
541
 
            push_result.target_branch = \
542
 
                push_result.branch_push_result.target_branch
543
 
        return push_result
544
 
 
545
 
    def _get_tree_branch(self, name=None):
546
 
        """Return the branch and tree, if any, for this bzrdir.
547
 
 
548
 
        :param name: Name of colocated branch to open.
549
 
 
550
 
        Return None for tree if not present or inaccessible.
551
 
        Raise NotBranchError if no branch is present.
552
 
        :return: (tree, branch)
553
 
        """
554
 
        try:
555
 
            tree = self.open_workingtree()
556
 
        except (errors.NoWorkingTree, errors.NotLocalUrl):
557
 
            tree = None
558
 
            branch = self.open_branch(name=name)
559
 
        else:
560
 
            if name is not None:
561
 
                branch = self.open_branch(name=name)
562
 
            else:
563
 
                branch = tree.branch
564
 
        return tree, branch
565
 
 
566
 
    def get_config(self):
567
 
        """Get configuration for this ControlDir."""
568
 
        raise NotImplementedError(self.get_config)
569
 
 
570
 
    def check_conversion_target(self, target_format):
571
 
        """Check that a bzrdir as a whole can be converted to a new format."""
572
 
        raise NotImplementedError(self.check_conversion_target)
573
 
 
574
 
    def clone(self, url, revision_id=None, force_new_repo=False,
575
 
              preserve_stacking=False):
576
 
        """Clone this bzrdir and its contents to url verbatim.
577
 
 
578
 
        :param url: The url create the clone at.  If url's last component does
579
 
            not exist, it will be created.
580
 
        :param revision_id: The tip revision-id to use for any branch or
581
 
            working tree.  If not None, then the clone operation may tune
582
 
            itself to download less data.
583
 
        :param force_new_repo: Do not use a shared repository for the target
584
 
                               even if one is available.
585
 
        :param preserve_stacking: When cloning a stacked branch, stack the
586
 
            new branch on top of the other branch's stacked-on branch.
587
 
        """
588
 
        return self.clone_on_transport(get_transport(url),
589
 
                                       revision_id=revision_id,
590
 
                                       force_new_repo=force_new_repo,
591
 
                                       preserve_stacking=preserve_stacking)
592
 
 
593
 
    def clone_on_transport(self, transport, revision_id=None,
594
 
        force_new_repo=False, preserve_stacking=False, stacked_on=None,
595
 
        create_prefix=False, use_existing_dir=True):
596
 
        """Clone this bzrdir and its contents to transport verbatim.
597
 
 
598
 
        :param transport: The transport for the location to produce the clone
599
 
            at.  If the target directory does not exist, it will be created.
600
 
        :param revision_id: The tip revision-id to use for any branch or
601
 
            working tree.  If not None, then the clone operation may tune
602
 
            itself to download less data.
603
 
        :param force_new_repo: Do not use a shared repository for the target,
604
 
                               even if one is available.
605
 
        :param preserve_stacking: When cloning a stacked branch, stack the
606
 
            new branch on top of the other branch's stacked-on branch.
607
 
        :param create_prefix: Create any missing directories leading up to
608
 
            to_transport.
609
 
        :param use_existing_dir: Use an existing directory if one exists.
610
 
        """
611
 
        raise NotImplementedError(self.clone_on_transport)
612
 
 
613
 
 
614
 
class ControlDirFormat(object):
615
 
    """An encapsulation of the initialization and open routines for a format.
616
 
 
617
 
    Formats provide three things:
618
 
     * An initialization routine,
619
 
     * a format string,
620
 
     * an open routine.
621
 
 
622
 
    Formats are placed in a dict by their format string for reference
623
 
    during controldir opening. These should be subclasses of ControlDirFormat
624
 
    for consistency.
625
 
 
626
 
    Once a format is deprecated, just deprecate the initialize and open
627
 
    methods on the format class. Do not deprecate the object, as the
628
 
    object will be created every system load.
629
 
 
630
 
    :cvar colocated_branches: Whether this formats supports colocated branches.
631
 
    :cvar supports_workingtrees: This control directory can co-exist with a
632
 
        working tree.
633
 
    """
634
 
 
635
 
    _default_format = None
636
 
    """The default format used for new control directories."""
637
 
 
638
 
    _formats = []
639
 
    """The registered control formats - .bzr, ....
640
 
 
641
 
    This is a list of ControlDirFormat objects.
642
 
    """
643
 
 
644
 
    _server_probers = []
645
 
    """The registered server format probers, e.g. RemoteBzrProber.
646
 
 
647
 
    This is a list of Prober-derived classes.
648
 
    """
649
 
 
650
 
    _probers = []
651
 
    """The registered format probers, e.g. BzrProber.
652
 
 
653
 
    This is a list of Prober-derived classes.
654
 
    """
655
 
 
656
 
    colocated_branches = False
657
 
    """Whether co-located branches are supported for this control dir format.
658
 
    """
659
 
 
660
 
    supports_workingtrees = True
661
 
 
662
 
    def get_format_description(self):
663
 
        """Return the short description for this format."""
664
 
        raise NotImplementedError(self.get_format_description)
665
 
 
666
 
    def get_converter(self, format=None):
667
 
        """Return the converter to use to convert controldirs needing converts.
668
 
 
669
 
        This returns a bzrlib.controldir.Converter object.
670
 
 
671
 
        This should return the best upgrader to step this format towards the
672
 
        current default format. In the case of plugins we can/should provide
673
 
        some means for them to extend the range of returnable converters.
674
 
 
675
 
        :param format: Optional format to override the default format of the
676
 
                       library.
677
 
        """
678
 
        raise NotImplementedError(self.get_converter)
679
 
 
680
 
    def is_supported(self):
681
 
        """Is this format supported?
682
 
 
683
 
        Supported formats must be initializable and openable.
684
 
        Unsupported formats may not support initialization or committing or
685
 
        some other features depending on the reason for not being supported.
686
 
        """
687
 
        return True
688
 
 
689
 
    def same_model(self, target_format):
690
 
        return (self.repository_format.rich_root_data ==
691
 
            target_format.rich_root_data)
692
 
 
693
 
    @classmethod
694
 
    def register_format(klass, format):
695
 
        """Register a format that does not use '.bzr' for its control dir.
696
 
 
697
 
        """
698
 
        klass._formats.append(format)
699
 
 
700
 
    @classmethod
701
 
    def register_prober(klass, prober):
702
 
        """Register a prober that can look for a control dir.
703
 
 
704
 
        """
705
 
        klass._probers.append(prober)
706
 
 
707
 
    @classmethod
708
 
    def unregister_prober(klass, prober):
709
 
        """Unregister a prober.
710
 
 
711
 
        """
712
 
        klass._probers.remove(prober)
713
 
 
714
 
    @classmethod
715
 
    def register_server_prober(klass, prober):
716
 
        """Register a control format prober for client-server environments.
717
 
 
718
 
        These probers will be used before ones registered with
719
 
        register_prober.  This gives implementations that decide to the
720
 
        chance to grab it before anything looks at the contents of the format
721
 
        file.
722
 
        """
723
 
        klass._server_probers.append(prober)
724
 
 
725
 
    def __str__(self):
726
 
        # Trim the newline
727
 
        return self.get_format_description().rstrip()
728
 
 
729
 
    @classmethod
730
 
    def unregister_format(klass, format):
731
 
        klass._formats.remove(format)
732
 
 
733
 
    @classmethod
734
 
    def known_formats(klass):
735
 
        """Return all the known formats.
736
 
        """
737
 
        return set(klass._formats)
738
 
 
739
 
    @classmethod
740
 
    def find_format(klass, transport, _server_formats=True):
741
 
        """Return the format present at transport."""
742
 
        if _server_formats:
743
 
            _probers = klass._server_probers + klass._probers
744
 
        else:
745
 
            _probers = klass._probers
746
 
        for prober_kls in _probers:
747
 
            prober = prober_kls()
748
 
            try:
749
 
                return prober.probe_transport(transport)
750
 
            except errors.NotBranchError:
751
 
                # this format does not find a control dir here.
752
 
                pass
753
 
        raise errors.NotBranchError(path=transport.base)
754
 
 
755
 
    def initialize(self, url, possible_transports=None):
756
 
        """Create a control dir at this url and return an opened copy.
757
 
 
758
 
        While not deprecated, this method is very specific and its use will
759
 
        lead to many round trips to setup a working environment. See
760
 
        initialize_on_transport_ex for a [nearly] all-in-one method.
761
 
 
762
 
        Subclasses should typically override initialize_on_transport
763
 
        instead of this method.
764
 
        """
765
 
        return self.initialize_on_transport(get_transport(url,
766
 
                                                          possible_transports))
767
 
    def initialize_on_transport(self, transport):
768
 
        """Initialize a new controldir in the base directory of a Transport."""
769
 
        raise NotImplementedError(self.initialize_on_transport)
770
 
 
771
 
    def initialize_on_transport_ex(self, transport, use_existing_dir=False,
772
 
        create_prefix=False, force_new_repo=False, stacked_on=None,
773
 
        stack_on_pwd=None, repo_format_name=None, make_working_trees=None,
774
 
        shared_repo=False, vfs_only=False):
775
 
        """Create this format on transport.
776
 
 
777
 
        The directory to initialize will be created.
778
 
 
779
 
        :param force_new_repo: Do not use a shared repository for the target,
780
 
                               even if one is available.
781
 
        :param create_prefix: Create any missing directories leading up to
782
 
            to_transport.
783
 
        :param use_existing_dir: Use an existing directory if one exists.
784
 
        :param stacked_on: A url to stack any created branch on, None to follow
785
 
            any target stacking policy.
786
 
        :param stack_on_pwd: If stack_on is relative, the location it is
787
 
            relative to.
788
 
        :param repo_format_name: If non-None, a repository will be
789
 
            made-or-found. Should none be found, or if force_new_repo is True
790
 
            the repo_format_name is used to select the format of repository to
791
 
            create.
792
 
        :param make_working_trees: Control the setting of make_working_trees
793
 
            for a new shared repository when one is made. None to use whatever
794
 
            default the format has.
795
 
        :param shared_repo: Control whether made repositories are shared or
796
 
            not.
797
 
        :param vfs_only: If True do not attempt to use a smart server
798
 
        :return: repo, controldir, require_stacking, repository_policy. repo is
799
 
            None if none was created or found, controldir is always valid.
800
 
            require_stacking is the result of examining the stacked_on
801
 
            parameter and any stacking policy found for the target.
802
 
        """
803
 
        raise NotImplementedError(self.initialize_on_transport_ex)
804
 
 
805
 
    def network_name(self):
806
 
        """A simple byte string uniquely identifying this format for RPC calls.
807
 
 
808
 
        Bzr control formats use this disk format string to identify the format
809
 
        over the wire. Its possible that other control formats have more
810
 
        complex detection requirements, so we permit them to use any unique and
811
 
        immutable string they desire.
812
 
        """
813
 
        raise NotImplementedError(self.network_name)
814
 
 
815
 
    def open(self, transport, _found=False):
816
 
        """Return an instance of this format for the dir transport points at.
817
 
        """
818
 
        raise NotImplementedError(self.open)
819
 
 
820
 
    @classmethod
821
 
    def _set_default_format(klass, format):
822
 
        """Set default format (for testing behavior of defaults only)"""
823
 
        klass._default_format = format
824
 
 
825
 
    @classmethod
826
 
    def get_default_format(klass):
827
 
        """Return the current default format."""
828
 
        return klass._default_format
829
 
 
830
 
 
831
 
class Prober(object):
832
 
    """Abstract class that can be used to detect a particular kind of 
833
 
    control directory.
834
 
 
835
 
    At the moment this just contains a single method to probe a particular 
836
 
    transport, but it may be extended in the future to e.g. avoid 
837
 
    multiple levels of probing for Subversion repositories.
838
 
    """
839
 
 
840
 
    def probe_transport(self, transport):
841
 
        """Return the controldir style format present in a directory.
842
 
 
843
 
        :raise UnknownFormatError: If a control dir was found but is
844
 
            in an unknown format.
845
 
        :raise NotBranchError: If no control directory was found.
846
 
        :return: A ControlDirFormat instance.
847
 
        """
848
 
        raise NotImplementedError(self.probe_transport)
849
 
 
850
 
 
851
 
class ControlDirFormatInfo(object):
852
 
 
853
 
    def __init__(self, native, deprecated, hidden, experimental):
854
 
        self.deprecated = deprecated
855
 
        self.native = native
856
 
        self.hidden = hidden
857
 
        self.experimental = experimental
858
 
 
859
 
 
860
 
class ControlDirFormatRegistry(registry.Registry):
861
 
    """Registry of user-selectable ControlDir subformats.
862
 
 
863
 
    Differs from ControlDirFormat._formats in that it provides sub-formats,
864
 
    e.g. ControlDirMeta1 with weave repository.  Also, it's more user-oriented.
865
 
    """
866
 
 
867
 
    def __init__(self):
868
 
        """Create a ControlDirFormatRegistry."""
869
 
        self._aliases = set()
870
 
        self._registration_order = list()
871
 
        super(ControlDirFormatRegistry, self).__init__()
872
 
 
873
 
    def aliases(self):
874
 
        """Return a set of the format names which are aliases."""
875
 
        return frozenset(self._aliases)
876
 
 
877
 
    def register(self, key, factory, help, native=True, deprecated=False,
878
 
                 hidden=False, experimental=False, alias=False):
879
 
        """Register a ControlDirFormat factory.
880
 
 
881
 
        The factory must be a callable that takes one parameter: the key.
882
 
        It must produce an instance of the ControlDirFormat when called.
883
 
 
884
 
        This function mainly exists to prevent the info object from being
885
 
        supplied directly.
886
 
        """
887
 
        registry.Registry.register(self, key, factory, help,
888
 
            ControlDirFormatInfo(native, deprecated, hidden, experimental))
889
 
        if alias:
890
 
            self._aliases.add(key)
891
 
        self._registration_order.append(key)
892
 
 
893
 
    def register_lazy(self, key, module_name, member_name, help, native=True,
894
 
        deprecated=False, hidden=False, experimental=False, alias=False):
895
 
        registry.Registry.register_lazy(self, key, module_name, member_name,
896
 
            help, ControlDirFormatInfo(native, deprecated, hidden, experimental))
897
 
        if alias:
898
 
            self._aliases.add(key)
899
 
        self._registration_order.append(key)
900
 
 
901
 
    def set_default(self, key):
902
 
        """Set the 'default' key to be a clone of the supplied key.
903
 
 
904
 
        This method must be called once and only once.
905
 
        """
906
 
        registry.Registry.register(self, 'default', self.get(key),
907
 
            self.get_help(key), info=self.get_info(key))
908
 
        self._aliases.add('default')
909
 
 
910
 
    def set_default_repository(self, key):
911
 
        """Set the FormatRegistry default and Repository default.
912
 
 
913
 
        This is a transitional method while Repository.set_default_format
914
 
        is deprecated.
915
 
        """
916
 
        if 'default' in self:
917
 
            self.remove('default')
918
 
        self.set_default(key)
919
 
        format = self.get('default')()
920
 
 
921
 
    def make_bzrdir(self, key):
922
 
        return self.get(key)()
923
 
 
924
 
    def help_topic(self, topic):
925
 
        output = ""
926
 
        default_realkey = None
927
 
        default_help = self.get_help('default')
928
 
        help_pairs = []
929
 
        for key in self._registration_order:
930
 
            if key == 'default':
931
 
                continue
932
 
            help = self.get_help(key)
933
 
            if help == default_help:
934
 
                default_realkey = key
935
 
            else:
936
 
                help_pairs.append((key, help))
937
 
 
938
 
        def wrapped(key, help, info):
939
 
            if info.native:
940
 
                help = '(native) ' + help
941
 
            return ':%s:\n%s\n\n' % (key,
942
 
                textwrap.fill(help, initial_indent='    ',
943
 
                    subsequent_indent='    ',
944
 
                    break_long_words=False))
945
 
        if default_realkey is not None:
946
 
            output += wrapped(default_realkey, '(default) %s' % default_help,
947
 
                              self.get_info('default'))
948
 
        deprecated_pairs = []
949
 
        experimental_pairs = []
950
 
        for key, help in help_pairs:
951
 
            info = self.get_info(key)
952
 
            if info.hidden:
953
 
                continue
954
 
            elif info.deprecated:
955
 
                deprecated_pairs.append((key, help))
956
 
            elif info.experimental:
957
 
                experimental_pairs.append((key, help))
958
 
            else:
959
 
                output += wrapped(key, help, info)
960
 
        output += "\nSee :doc:`formats-help` for more about storage formats."
961
 
        other_output = ""
962
 
        if len(experimental_pairs) > 0:
963
 
            other_output += "Experimental formats are shown below.\n\n"
964
 
            for key, help in experimental_pairs:
965
 
                info = self.get_info(key)
966
 
                other_output += wrapped(key, help, info)
967
 
        else:
968
 
            other_output += \
969
 
                "No experimental formats are available.\n\n"
970
 
        if len(deprecated_pairs) > 0:
971
 
            other_output += "\nDeprecated formats are shown below.\n\n"
972
 
            for key, help in deprecated_pairs:
973
 
                info = self.get_info(key)
974
 
                other_output += wrapped(key, help, info)
975
 
        else:
976
 
            other_output += \
977
 
                "\nNo deprecated formats are available.\n\n"
978
 
        other_output += \
979
 
                "\nSee :doc:`formats-help` for more about storage formats."
980
 
 
981
 
        if topic == 'other-formats':
982
 
            return other_output
983
 
        else:
984
 
            return output
985
 
 
986
 
 
987
 
# Please register new formats after old formats so that formats
988
 
# appear in chronological order and format descriptions can build
989
 
# on previous ones.
990
 
format_registry = ControlDirFormatRegistry()
991
 
 
992
 
network_format_registry = registry.FormatRegistry()
993
 
"""Registry of formats indexed by their network name.
994
 
 
995
 
The network name for a ControlDirFormat is an identifier that can be used when
996
 
referring to formats with smart server operations. See
997
 
ControlDirFormat.network_name() for more detail.
998
 
"""