~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/controldir.py

  • Committer: Jelmer Vernooij
  • Date: 2011-11-08 19:09:55 UTC
  • mfrom: (6248 +trunk)
  • mto: This revision was merged to the branch mainline in revision 6249.
  • Revision ID: jelmer@samba.org-20111108190955-xspn5rb9kpgw78oy
mergeĀ lp:bzr

Show diffs side-by-side

added added

removed removed

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