~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/controldir.py

  • Committer: Patch Queue Manager
  • Date: 2012-02-25 15:28:53 UTC
  • mfrom: (6475.1.1 bzr.dev)
  • Revision ID: pqm@pqm.ubuntu.com-20120225152853-nz1w2gsfv7lc1yq4
(jelmer) Update documentation to mention command hooks landed in bzr 2.6
 rather than 2.5. (Brian de Alwis)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2010, 2011 Canonical Ltd
 
1
# Copyright (C) 2010, 2011, 2012 Canonical Ltd
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
22
22
 
23
23
"""
24
24
 
 
25
from __future__ import absolute_import
 
26
 
25
27
from bzrlib.lazy_import import lazy_import
26
28
lazy_import(globals(), """
27
29
import textwrap
106
108
        """Return a sequence of all branches local to this control directory.
107
109
 
108
110
        """
 
111
        return self.get_branches().values()
 
112
 
 
113
    def get_branches(self):
 
114
        """Get all branches in this control directory, as a dictionary.
 
115
        
 
116
        :return: Dictionary mapping branch names to instances.
 
117
        """
109
118
        try:
110
 
            return [self.open_branch()]
 
119
           return { "": self.open_branch() }
111
120
        except (errors.NotBranchError, errors.NoRepositoryPresent):
112
 
            return []
 
121
           return {}
113
122
 
114
123
    def is_control_filename(self, filename):
115
124
        """True if filename is the name of a path which is reserved for
154
163
        """Create a branch in this ControlDir.
155
164
 
156
165
        :param name: Name of the colocated branch to create, None for
157
 
            the default branch.
 
166
            the user selected branch or "" for the active branch.
158
167
        :param append_revisions_only: Whether this branch should only allow
159
168
            appending new revisions to its history.
160
169
 
166
175
    def destroy_branch(self, name=None):
167
176
        """Destroy a branch in this ControlDir.
168
177
 
169
 
        :param name: Name of the branch to destroy, None for the default 
170
 
            branch.
 
178
        :param name: Name of the branch to destroy, None for the 
 
179
            user selected branch or "" for the active branch.
 
180
        :raise NotBranchError: When the branch does not exist
171
181
        """
172
182
        raise NotImplementedError(self.destroy_branch)
173
183
 
221
231
            raise errors.NoColocatedBranchSupport(self)
222
232
        return None
223
233
 
 
234
    def set_branch_reference(self, target_branch, name=None):
 
235
        """Set the referenced URL for the branch in this controldir.
 
236
 
 
237
        :param name: Optional colocated branch name
 
238
        :param target_branch: Branch to reference
 
239
        :raises NoColocatedBranchSupport: If a branch name was specified
 
240
            but colocated branches are not supported.
 
241
        :return: The referencing branch
 
242
        """
 
243
        raise NotImplementedError(self.set_branch_reference)
 
244
 
224
245
    def open_branch(self, name=None, unsupported=False,
225
 
                    ignore_fallbacks=False):
 
246
                    ignore_fallbacks=False, possible_transports=None):
226
247
        """Open the branch object at this ControlDir if one is present.
227
248
 
228
 
        If unsupported is True, then no longer supported branch formats can
229
 
        still be opened.
230
 
 
231
 
        TODO: static convenience version of this?
 
249
        :param unsupported: if True, then no longer supported branch formats can
 
250
            still be opened.
 
251
        :param ignore_fallbacks: Whether to open fallback repositories
 
252
        :param possible_transports: Transports to use for opening e.g.
 
253
            fallback repositories.
232
254
        """
233
255
        raise NotImplementedError(self.open_branch)
234
256
 
240
262
        get at a repository.
241
263
 
242
264
        :param _unsupported: a private parameter, not part of the api.
243
 
 
244
 
        TODO: static convenience version of this?
245
265
        """
246
266
        raise NotImplementedError(self.open_repository)
247
267
 
254
274
        """
255
275
        raise NotImplementedError(self.find_repository)
256
276
 
257
 
    def open_workingtree(self, _unsupported=False,
 
277
    def open_workingtree(self, unsupported=False,
258
278
                         recommend_upgrade=True, from_branch=None):
259
279
        """Open the workingtree object at this ControlDir if one is present.
260
280
 
275
295
        branch and discards it, and that's somewhat expensive.)
276
296
        """
277
297
        try:
278
 
            self.open_branch(name)
 
298
            self.open_branch(name, ignore_fallbacks=True)
279
299
            return True
280
300
        except errors.NotBranchError:
281
301
            return False
283
303
    def _get_selected_branch(self):
284
304
        """Return the name of the branch selected by the user.
285
305
 
286
 
        :return: Name of the branch selected by the user, or None.
 
306
        :return: Name of the branch selected by the user, or "".
287
307
        """
288
308
        branch = self.root_transport.get_segment_parameters().get("branch")
289
 
        if branch is not None:
290
 
            branch = urlutils.unescape(branch)
291
 
        return branch
 
309
        if branch is None:
 
310
            branch = ""
 
311
        return urlutils.unescape(branch)
292
312
 
293
313
    def has_workingtree(self):
294
314
        """Tell if this controldir contains a working tree.
322
342
        raise NotImplementedError(self.cloning_metadir)
323
343
 
324
344
    def checkout_metadir(self):
325
 
        """Produce a metadir suitable for checkouts of this controldir."""
 
345
        """Produce a metadir suitable for checkouts of this controldir.
 
346
 
 
347
        :returns: A ControlDirFormat with all component formats
 
348
            either set appropriately or set to None if that component
 
349
            should not be created.
 
350
        """
326
351
        return self.cloning_metadir()
327
352
 
328
353
    def sprout(self, url, revision_id=None, force_new_repo=False,
381
406
            repository_to.fetch(source.repository, revision_id=revision_id)
382
407
            br_to = source.clone(self, revision_id=revision_id)
383
408
            if source.get_push_location() is None or remember:
 
409
                # FIXME: Should be done only if we succeed ? -- vila 2012-01-18
384
410
                source.set_push_location(br_to.base)
385
411
            push_result.stacked_on = None
386
412
            push_result.branch_push_result = None
392
418
        else:
393
419
            # We have successfully opened the branch, remember if necessary:
394
420
            if source.get_push_location() is None or remember:
 
421
                # FIXME: Should be done only if we succeed ? -- vila 2012-01-18
395
422
                source.set_push_location(br_to.base)
396
423
            try:
397
424
                tree_to = self.open_workingtree()
651
678
        return klass.open(base, _unsupported=True)
652
679
 
653
680
    @classmethod
654
 
    def open(klass, base, _unsupported=False, possible_transports=None):
 
681
    def open(klass, base, possible_transports=None, probers=None,
 
682
             _unsupported=False):
655
683
        """Open an existing controldir, rooted at 'base' (url).
656
684
 
657
685
        :param _unsupported: a private parameter to the ControlDir class.
658
686
        """
659
687
        t = _mod_transport.get_transport(base, possible_transports)
660
 
        return klass.open_from_transport(t, _unsupported=_unsupported)
 
688
        return klass.open_from_transport(t, probers=probers,
 
689
                _unsupported=_unsupported)
661
690
 
662
691
    @classmethod
663
692
    def open_from_transport(klass, transport, _unsupported=False,
664
 
                            _server_formats=True):
 
693
                            probers=None):
665
694
        """Open a controldir within a particular directory.
666
695
 
667
696
        :param transport: Transport containing the controldir.
673
702
        # the redirections.
674
703
        base = transport.base
675
704
        def find_format(transport):
676
 
            return transport, ControlDirFormat.find_format(
677
 
                transport, _server_formats=_server_formats)
 
705
            return transport, ControlDirFormat.find_format(transport,
 
706
                probers=probers)
678
707
 
679
708
        def redirected(transport, e, redirection_notice):
680
709
            redirected_transport = transport._redirected_to(e.source, e.target)
727
756
                return result, urlutils.unescape(a_transport.relpath(url))
728
757
            except errors.NotBranchError, e:
729
758
                pass
 
759
            except errors.PermissionDenied:
 
760
                pass
730
761
            try:
731
762
                new_t = a_transport.clone('..')
732
763
            except errors.InvalidURLJoin:
750
781
        return controldir._get_tree_branch()
751
782
 
752
783
    @classmethod
753
 
    def open_containing_tree_or_branch(klass, location):
 
784
    def open_containing_tree_or_branch(klass, location,
 
785
            possible_transports=None):
754
786
        """Return the branch and working tree contained by a location.
755
787
 
756
788
        Returns (tree, branch, relpath).
759
791
        raised
760
792
        relpath is the portion of the path that is contained by the branch.
761
793
        """
762
 
        controldir, relpath = klass.open_containing(location)
 
794
        controldir, relpath = klass.open_containing(location,
 
795
            possible_transports=possible_transports)
763
796
        tree, branch = controldir._get_tree_branch()
764
797
        return tree, branch, relpath
765
798
 
827
860
 
828
861
 
829
862
class ControlComponentFormat(object):
830
 
    """A component that can live inside of a .bzr meta directory."""
 
863
    """A component that can live inside of a control directory."""
831
864
 
832
865
    upgrade_recommended = False
833
866
 
834
 
    def get_format_string(self):
835
 
        """Return the format of this format, if usable in meta directories."""
836
 
        raise NotImplementedError(self.get_format_string)
837
 
 
838
867
    def get_format_description(self):
839
868
        """Return the short description for this format."""
840
869
        raise NotImplementedError(self.get_format_description)
867
896
            ui.ui_factory.recommend_upgrade(
868
897
                self.get_format_description(), basedir)
869
898
 
 
899
    @classmethod
 
900
    def get_format_string(cls):
 
901
        raise NotImplementedError(cls.get_format_string)
 
902
 
870
903
 
871
904
class ControlComponentFormatRegistry(registry.FormatRegistry):
872
905
    """A registry for control components (branch, workingtree, repository)."""
1095
1128
        return self.get_format_description().rstrip()
1096
1129
 
1097
1130
    @classmethod
 
1131
    def all_probers(klass):
 
1132
        return klass._server_probers + klass._probers
 
1133
 
 
1134
    @classmethod
1098
1135
    def known_formats(klass):
1099
1136
        """Return all the known formats.
1100
1137
        """
1101
1138
        result = set()
1102
 
        for prober_kls in klass._probers + klass._server_probers:
 
1139
        for prober_kls in klass.all_probers():
1103
1140
            result.update(prober_kls.known_formats())
1104
1141
        return result
1105
1142
 
1106
1143
    @classmethod
1107
 
    def find_format(klass, transport, _server_formats=True):
 
1144
    def find_format(klass, transport, probers=None):
1108
1145
        """Return the format present at transport."""
1109
 
        if _server_formats:
1110
 
            _probers = klass._server_probers + klass._probers
1111
 
        else:
1112
 
            _probers = klass._probers
1113
 
        for prober_kls in _probers:
 
1146
        if probers is None:
 
1147
            probers = klass.all_probers()
 
1148
        for prober_kls in probers:
1114
1149
            prober = prober_kls()
1115
1150
            try:
1116
1151
                return prober.probe_transport(transport)