~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/controldir.py

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2010-06-28 01:45:12 UTC
  • mfrom: (5320.1.1 statictuple-sizeof)
  • Revision ID: pqm@pqm.ubuntu.com-20100628014512-l4w7dmgpmt1pj5c4
(spiv) Implement __sizeof__ in StaticTuple. (Andrew Bennetts)

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