~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/controldir.py

  • Committer: Jelmer Vernooij
  • Date: 2011-02-26 15:39:49 UTC
  • mto: (5691.1.1 bzr.dev)
  • mto: This revision was merged to the branch mainline in revision 5692.
  • Revision ID: jelmer@samba.org-20110226153949-o0fk909b30g7z570
Fix the use of "bzr tags" in branches with ghosts in their mainline /and/ tags on revisions not in the branch ancestry.

Show diffs side-by-side

added added

removed removed

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