/brz/remove-bazaar

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

« back to all changes in this revision

Viewing changes to bzrlib/controldir.py

  • Committer: Jelmer Vernooij
  • Date: 2011-03-22 12:10:34 UTC
  • mto: This revision was merged to the branch mainline in revision 5737.
  • Revision ID: jelmer@samba.org-20110322121034-70a7037sqrs2l2no
Rename check_status -> check_support_status.

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