~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/smart/bzrdir.py

  • Committer: Robert Collins
  • Date: 2009-03-03 03:27:51 UTC
  • mto: (4070.2.5 integration)
  • mto: This revision was merged to the branch mainline in revision 4075.
  • Revision ID: robertc@robertcollins.net-20090303032751-ubyfhezgjul6y5ic
Get BzrDir.cloning_metadir working.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Copyright (C) 2006 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
16
 
 
17
"""Server-side bzrdir related request implmentations."""
 
18
 
 
19
 
 
20
from bzrlib import branch, errors, repository
 
21
from bzrlib.bzrdir import BzrDir, BzrDirFormat, BzrDirMetaFormat1
 
22
from bzrlib.smart.request import (
 
23
    FailedSmartServerResponse,
 
24
    SmartServerRequest,
 
25
    SuccessfulSmartServerResponse,
 
26
    )
 
27
 
 
28
 
 
29
class SmartServerRequestOpenBzrDir(SmartServerRequest):
 
30
 
 
31
    def do(self, path):
 
32
        from bzrlib.bzrdir import BzrDirFormat
 
33
        try:
 
34
            t = self.transport_from_client_path(path)
 
35
        except errors.PathNotChild:
 
36
            # The client is trying to ask about a path that they have no access
 
37
            # to.
 
38
            # Ideally we'd return a FailedSmartServerResponse here rather than
 
39
            # a "successful" negative, but we want to be compatibile with
 
40
            # clients that don't anticipate errors from this method.
 
41
            answer = 'no'
 
42
        else:
 
43
            default_format = BzrDirFormat.get_default_format()
 
44
            real_bzrdir = default_format.open(t, _found=True)
 
45
            try:
 
46
                real_bzrdir._format.probe_transport(t)
 
47
            except (errors.NotBranchError, errors.UnknownFormatError):
 
48
                answer = 'no'
 
49
            else:
 
50
                answer = 'yes'
 
51
        return SuccessfulSmartServerResponse((answer,))
 
52
 
 
53
 
 
54
class SmartServerRequestBzrDir(SmartServerRequest):
 
55
 
 
56
    def do(self, path, *args):
 
57
        """Open a BzrDir at path, and return self.do_bzrdir_request(*args)."""
 
58
        self._bzrdir = BzrDir.open_from_transport(
 
59
            self.transport_from_client_path(path))
 
60
        return self.do_bzrdir_request(*args)
 
61
 
 
62
    def _boolean_to_yes_no(self, a_boolean):
 
63
        if a_boolean:
 
64
            return 'yes'
 
65
        else:
 
66
            return 'no'
 
67
 
 
68
    def _format_to_capabilities(self, repo_format):
 
69
        rich_root = self._boolean_to_yes_no(repo_format.rich_root_data)
 
70
        tree_ref = self._boolean_to_yes_no(
 
71
            repo_format.supports_tree_reference)
 
72
        external_lookup = self._boolean_to_yes_no(
 
73
            repo_format.supports_external_lookups)
 
74
        return rich_root, tree_ref, external_lookup
 
75
 
 
76
    def _repo_relpath(self, current_transport, repository):
 
77
        """Get the relative path for repository from current_transport."""
 
78
        # the relpath of the bzrdir in the found repository gives us the
 
79
        # path segments to pop-out.
 
80
        relpath = repository.bzrdir.root_transport.relpath(
 
81
            current_transport.base)
 
82
        if len(relpath):
 
83
            segments = ['..'] * len(relpath.split('/'))
 
84
        else:
 
85
            segments = []
 
86
        return '/'.join(segments)
 
87
 
 
88
 
 
89
class SmartServerBzrDirRequestCloningMetaDir(SmartServerRequestBzrDir):
 
90
 
 
91
    def do_bzrdir_request(self, require_stacking):
 
92
        """Get the format that should be used when cloning from this dir."""
 
93
        if require_stacking == "True":
 
94
            require_stacking = True
 
95
        else:
 
96
            require_stacking = False
 
97
        control_format = self._bzrdir.cloning_metadir(
 
98
            require_stacking=require_stacking)
 
99
        control_name = control_format.network_name()
 
100
        # XXX: Should be a method that tells us this, or delegated to the
 
101
        # format, or something.
 
102
        if isinstance(control_format, BzrDirMetaFormat1):
 
103
            branch_name = control_format.get_branch_format().network_name()
 
104
            repository_name = control_format.repository_format.network_name()
 
105
        else:
 
106
            # Only MetaDir has delegated formats today.
 
107
            branch_name = ''
 
108
            repository_name = ''
 
109
        return SuccessfulSmartServerResponse((control_name, repository_name,
 
110
            branch_name))
 
111
 
 
112
 
 
113
class SmartServerRequestCreateBranch(SmartServerRequestBzrDir):
 
114
 
 
115
    def do(self, path, network_name):
 
116
        """Create a branch in the bzr dir at path.
 
117
 
 
118
        This operates precisely like 'bzrdir.create_branch'.
 
119
 
 
120
        If a bzrdir is not present, an exception is propogated
 
121
        rather than 'no branch' because these are different conditions (and
 
122
        this method should only be called after establishing that a bzr dir
 
123
        exists anyway).
 
124
 
 
125
        This is the initial version of this method introduced to the smart
 
126
        server for 1.13.
 
127
 
 
128
        :param path: The path to the bzrdir.
 
129
        :param network_name: The network name of the branch type to create.
 
130
        :return: (ok, network_name)
 
131
        """
 
132
        bzrdir = BzrDir.open_from_transport(
 
133
            self.transport_from_client_path(path))
 
134
        format = branch.network_format_registry.get(network_name)
 
135
        bzrdir.branch_format = format
 
136
        result = format.initialize(bzrdir)
 
137
        rich_root, tree_ref, external_lookup = self._format_to_capabilities(
 
138
            result.repository._format)
 
139
        branch_format = result._format.network_name()
 
140
        repo_format = result.repository._format.network_name()
 
141
        repo_path = self._repo_relpath(bzrdir.root_transport,
 
142
            result.repository)
 
143
        # branch format, repo relpath, rich_root, tree_ref, external_lookup,
 
144
        # repo_network_name
 
145
        return SuccessfulSmartServerResponse(('ok', branch_format, repo_path,
 
146
            rich_root, tree_ref, external_lookup, repo_format))
 
147
 
 
148
 
 
149
class SmartServerRequestCreateRepository(SmartServerRequestBzrDir):
 
150
 
 
151
    def do(self, path, network_name, shared):
 
152
        """Create a repository in the bzr dir at path.
 
153
 
 
154
        This operates precisely like 'bzrdir.create_repository'.
 
155
 
 
156
        If a bzrdir is not present, an exception is propogated
 
157
        rather than 'no branch' because these are different conditions (and
 
158
        this method should only be called after establishing that a bzr dir
 
159
        exists anyway).
 
160
 
 
161
        This is the initial version of this method introduced to the smart
 
162
        server for 1.13.
 
163
 
 
164
        :param path: The path to the bzrdir.
 
165
        :param network_name: The network name of the repository type to create.
 
166
        :param shared: The value to pass create_repository for the shared
 
167
            parameter.
 
168
        :return: (ok, rich_root, tree_ref, external_lookup, network_name)
 
169
        """
 
170
        bzrdir = BzrDir.open_from_transport(
 
171
            self.transport_from_client_path(path))
 
172
        shared = shared == 'True'
 
173
        format = repository.network_format_registry.get(network_name)
 
174
        bzrdir.repository_format = format
 
175
        result = format.initialize(bzrdir, shared=shared)
 
176
        rich_root, tree_ref, external_lookup = self._format_to_capabilities(
 
177
            result._format)
 
178
        return SuccessfulSmartServerResponse(('ok', rich_root, tree_ref,
 
179
            external_lookup, result._format.network_name()))
 
180
 
 
181
 
 
182
class SmartServerRequestFindRepository(SmartServerRequestBzrDir):
 
183
 
 
184
    def _find(self, path):
 
185
        """try to find a repository from path upwards
 
186
 
 
187
        This operates precisely like 'bzrdir.find_repository'.
 
188
 
 
189
        :return: (relpath, rich_root, tree_ref, external_lookup, network_name).
 
190
            All are strings, relpath is a / prefixed path, the next three are
 
191
            either 'yes' or 'no', and the last is a repository format network
 
192
            name.
 
193
        :raises errors.NoRepositoryPresent: When there is no repository
 
194
            present.
 
195
        """
 
196
        bzrdir = BzrDir.open_from_transport(
 
197
            self.transport_from_client_path(path))
 
198
        repository = bzrdir.find_repository()
 
199
        path = self._repo_relpath(bzrdir.root_transport, repository)
 
200
        rich_root, tree_ref, external_lookup = self._format_to_capabilities(
 
201
            repository._format)
 
202
        network_name = repository._format.network_name()
 
203
        return path, rich_root, tree_ref, external_lookup, network_name
 
204
 
 
205
 
 
206
class SmartServerRequestFindRepositoryV1(SmartServerRequestFindRepository):
 
207
 
 
208
    def do(self, path):
 
209
        """try to find a repository from path upwards
 
210
 
 
211
        This operates precisely like 'bzrdir.find_repository'.
 
212
 
 
213
        If a bzrdir is not present, an exception is propogated
 
214
        rather than 'no branch' because these are different conditions.
 
215
 
 
216
        This is the initial version of this method introduced with the smart
 
217
        server. Modern clients will try the V2 method that adds support for the
 
218
        supports_external_lookups attribute.
 
219
 
 
220
        :return: norepository or ok, relpath.
 
221
        """
 
222
        try:
 
223
            path, rich_root, tree_ref, external_lookup, name = self._find(path)
 
224
            return SuccessfulSmartServerResponse(('ok', path, rich_root, tree_ref))
 
225
        except errors.NoRepositoryPresent:
 
226
            return FailedSmartServerResponse(('norepository', ))
 
227
 
 
228
 
 
229
class SmartServerRequestFindRepositoryV2(SmartServerRequestFindRepository):
 
230
 
 
231
    def do(self, path):
 
232
        """try to find a repository from path upwards
 
233
 
 
234
        This operates precisely like 'bzrdir.find_repository'.
 
235
 
 
236
        If a bzrdir is not present, an exception is propogated
 
237
        rather than 'no branch' because these are different conditions.
 
238
 
 
239
        This is the second edition of this method introduced in bzr 1.3, which
 
240
        returns information about the supports_external_lookups format
 
241
        attribute too.
 
242
 
 
243
        :return: norepository or ok, relpath, rich_root, tree_ref,
 
244
            external_lookup.
 
245
        """
 
246
        try:
 
247
            path, rich_root, tree_ref, external_lookup, name = self._find(path)
 
248
            return SuccessfulSmartServerResponse(
 
249
                ('ok', path, rich_root, tree_ref, external_lookup))
 
250
        except errors.NoRepositoryPresent:
 
251
            return FailedSmartServerResponse(('norepository', ))
 
252
 
 
253
 
 
254
class SmartServerRequestFindRepositoryV3(SmartServerRequestFindRepository):
 
255
 
 
256
    def do(self, path):
 
257
        """try to find a repository from path upwards
 
258
 
 
259
        This operates precisely like 'bzrdir.find_repository'.
 
260
 
 
261
        If a bzrdir is not present, an exception is propogated
 
262
        rather than 'no branch' because these are different conditions.
 
263
 
 
264
        This is the third edition of this method introduced in bzr 1.13, which
 
265
        returns information about the network name of the repository format.
 
266
 
 
267
        :return: norepository or ok, relpath, rich_root, tree_ref,
 
268
            external_lookup, network_name.
 
269
        """
 
270
        try:
 
271
            path, rich_root, tree_ref, external_lookup, name = self._find(path)
 
272
            return SuccessfulSmartServerResponse(
 
273
                ('ok', path, rich_root, tree_ref, external_lookup, name))
 
274
        except errors.NoRepositoryPresent:
 
275
            return FailedSmartServerResponse(('norepository', ))
 
276
 
 
277
 
 
278
class SmartServerRequestInitializeBzrDir(SmartServerRequest):
 
279
 
 
280
    def do(self, path):
 
281
        """Initialize a bzrdir at path.
 
282
 
 
283
        The default format of the server is used.
 
284
        :return: SmartServerResponse(('ok', ))
 
285
        """
 
286
        target_transport = self.transport_from_client_path(path)
 
287
        BzrDirFormat.get_default_format().initialize_on_transport(target_transport)
 
288
        return SuccessfulSmartServerResponse(('ok', ))
 
289
 
 
290
 
 
291
class SmartServerRequestOpenBranch(SmartServerRequest):
 
292
 
 
293
    def do(self, path):
 
294
        """try to open a branch at path and return ok/nobranch.
 
295
 
 
296
        If a bzrdir is not present, an exception is propogated
 
297
        rather than 'no branch' because these are different conditions.
 
298
        """
 
299
        bzrdir = BzrDir.open_from_transport(
 
300
            self.transport_from_client_path(path))
 
301
        try:
 
302
            reference_url = bzrdir.get_branch_reference()
 
303
            if reference_url is None:
 
304
                return SuccessfulSmartServerResponse(('ok', ''))
 
305
            else:
 
306
                return SuccessfulSmartServerResponse(('ok', reference_url))
 
307
        except errors.NotBranchError:
 
308
            return FailedSmartServerResponse(('nobranch', ))