~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/smart/bzrdir.py

  • Committer: Martin Pool
  • Date: 2005-05-17 07:51:51 UTC
  • Revision ID: mbp@sourcefrog.net-20050517075151-b64853a6a38a6225
- export bzrlib.find_branch

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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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
 
        try:
59
 
            self._bzrdir = BzrDir.open_from_transport(
60
 
                self.transport_from_client_path(path))
61
 
        except errors.NotBranchError:
62
 
            return FailedSmartServerResponse(('nobranch', ))
63
 
        return self.do_bzrdir_request(*args)
64
 
 
65
 
    def _boolean_to_yes_no(self, a_boolean):
66
 
        if a_boolean:
67
 
            return 'yes'
68
 
        else:
69
 
            return 'no'
70
 
 
71
 
    def _format_to_capabilities(self, repo_format):
72
 
        rich_root = self._boolean_to_yes_no(repo_format.rich_root_data)
73
 
        tree_ref = self._boolean_to_yes_no(
74
 
            repo_format.supports_tree_reference)
75
 
        external_lookup = self._boolean_to_yes_no(
76
 
            repo_format.supports_external_lookups)
77
 
        return rich_root, tree_ref, external_lookup
78
 
 
79
 
    def _repo_relpath(self, current_transport, repository):
80
 
        """Get the relative path for repository from current_transport."""
81
 
        # the relpath of the bzrdir in the found repository gives us the
82
 
        # path segments to pop-out.
83
 
        relpath = repository.bzrdir.root_transport.relpath(
84
 
            current_transport.base)
85
 
        if len(relpath):
86
 
            segments = ['..'] * len(relpath.split('/'))
87
 
        else:
88
 
            segments = []
89
 
        return '/'.join(segments)
90
 
 
91
 
 
92
 
class SmartServerBzrDirRequestCloningMetaDir(SmartServerRequestBzrDir):
93
 
 
94
 
    def do_bzrdir_request(self, require_stacking):
95
 
        """Get the format that should be used when cloning from this dir.
96
 
 
97
 
        New in 1.13.
98
 
        
99
 
        :return: on success, a 3-tuple of network names for (control,
100
 
            repository, branch) directories, where '' signifies "not present".
101
 
            If this BzrDir contains a branch reference then this will fail with
102
 
            BranchReference; clients should resolve branch references before
103
 
            calling this RPC.
104
 
        """
105
 
        try:
106
 
            branch_ref = self._bzrdir.get_branch_reference()
107
 
        except errors.NotBranchError:
108
 
            branch_ref = None
109
 
        if branch_ref is not None:
110
 
            # The server shouldn't try to resolve references, and it quite
111
 
            # possibly can't reach them anyway.  The client needs to resolve
112
 
            # the branch reference to determine the cloning_metadir.
113
 
            return FailedSmartServerResponse(('BranchReference',))
114
 
        if require_stacking == "True":
115
 
            require_stacking = True
116
 
        else:
117
 
            require_stacking = False
118
 
        control_format = self._bzrdir.cloning_metadir(
119
 
            require_stacking=require_stacking)
120
 
        control_name = control_format.network_name()
121
 
        # XXX: There should be a method that tells us that the format does/does
122
 
        # not have subformats.
123
 
        if isinstance(control_format, BzrDirMetaFormat1):
124
 
            branch_name = ('branch',
125
 
                control_format.get_branch_format().network_name())
126
 
            repository_name = control_format.repository_format.network_name()
127
 
        else:
128
 
            # Only MetaDir has delegated formats today.
129
 
            branch_name = ('branch', '')
130
 
            repository_name = ''
131
 
        return SuccessfulSmartServerResponse((control_name, repository_name,
132
 
            branch_name))
133
 
 
134
 
 
135
 
class SmartServerRequestCreateBranch(SmartServerRequestBzrDir):
136
 
 
137
 
    def do(self, path, network_name):
138
 
        """Create a branch in the bzr dir at path.
139
 
 
140
 
        This operates precisely like 'bzrdir.create_branch'.
141
 
 
142
 
        If a bzrdir is not present, an exception is propogated
143
 
        rather than 'no branch' because these are different conditions (and
144
 
        this method should only be called after establishing that a bzr dir
145
 
        exists anyway).
146
 
 
147
 
        This is the initial version of this method introduced to the smart
148
 
        server for 1.13.
149
 
 
150
 
        :param path: The path to the bzrdir.
151
 
        :param network_name: The network name of the branch type to create.
152
 
        :return: (ok, network_name)
153
 
        """
154
 
        bzrdir = BzrDir.open_from_transport(
155
 
            self.transport_from_client_path(path))
156
 
        format = branch.network_format_registry.get(network_name)
157
 
        bzrdir.branch_format = format
158
 
        result = format.initialize(bzrdir)
159
 
        rich_root, tree_ref, external_lookup = self._format_to_capabilities(
160
 
            result.repository._format)
161
 
        branch_format = result._format.network_name()
162
 
        repo_format = result.repository._format.network_name()
163
 
        repo_path = self._repo_relpath(bzrdir.root_transport,
164
 
            result.repository)
165
 
        # branch format, repo relpath, rich_root, tree_ref, external_lookup,
166
 
        # repo_network_name
167
 
        return SuccessfulSmartServerResponse(('ok', branch_format, repo_path,
168
 
            rich_root, tree_ref, external_lookup, repo_format))
169
 
 
170
 
 
171
 
class SmartServerRequestCreateRepository(SmartServerRequestBzrDir):
172
 
 
173
 
    def do(self, path, network_name, shared):
174
 
        """Create a repository in the bzr dir at path.
175
 
 
176
 
        This operates precisely like 'bzrdir.create_repository'.
177
 
 
178
 
        If a bzrdir is not present, an exception is propagated
179
 
        rather than 'no branch' because these are different conditions (and
180
 
        this method should only be called after establishing that a bzr dir
181
 
        exists anyway).
182
 
 
183
 
        This is the initial version of this method introduced to the smart
184
 
        server for 1.13.
185
 
 
186
 
        :param path: The path to the bzrdir.
187
 
        :param network_name: The network name of the repository type to create.
188
 
        :param shared: The value to pass create_repository for the shared
189
 
            parameter.
190
 
        :return: (ok, rich_root, tree_ref, external_lookup, network_name)
191
 
        """
192
 
        bzrdir = BzrDir.open_from_transport(
193
 
            self.transport_from_client_path(path))
194
 
        shared = shared == 'True'
195
 
        format = repository.network_format_registry.get(network_name)
196
 
        bzrdir.repository_format = format
197
 
        result = format.initialize(bzrdir, shared=shared)
198
 
        rich_root, tree_ref, external_lookup = self._format_to_capabilities(
199
 
            result._format)
200
 
        return SuccessfulSmartServerResponse(('ok', rich_root, tree_ref,
201
 
            external_lookup, result._format.network_name()))
202
 
 
203
 
 
204
 
class SmartServerRequestFindRepository(SmartServerRequestBzrDir):
205
 
 
206
 
    def _find(self, path):
207
 
        """try to find a repository from path upwards
208
 
 
209
 
        This operates precisely like 'bzrdir.find_repository'.
210
 
 
211
 
        :return: (relpath, rich_root, tree_ref, external_lookup, network_name).
212
 
            All are strings, relpath is a / prefixed path, the next three are
213
 
            either 'yes' or 'no', and the last is a repository format network
214
 
            name.
215
 
        :raises errors.NoRepositoryPresent: When there is no repository
216
 
            present.
217
 
        """
218
 
        bzrdir = BzrDir.open_from_transport(
219
 
            self.transport_from_client_path(path))
220
 
        repository = bzrdir.find_repository()
221
 
        path = self._repo_relpath(bzrdir.root_transport, repository)
222
 
        rich_root, tree_ref, external_lookup = self._format_to_capabilities(
223
 
            repository._format)
224
 
        network_name = repository._format.network_name()
225
 
        return path, rich_root, tree_ref, external_lookup, network_name
226
 
 
227
 
 
228
 
class SmartServerRequestFindRepositoryV1(SmartServerRequestFindRepository):
229
 
 
230
 
    def do(self, path):
231
 
        """try to find a repository from path upwards
232
 
 
233
 
        This operates precisely like 'bzrdir.find_repository'.
234
 
 
235
 
        If a bzrdir is not present, an exception is propagated
236
 
        rather than 'no branch' because these are different conditions.
237
 
 
238
 
        This is the initial version of this method introduced with the smart
239
 
        server. Modern clients will try the V2 method that adds support for the
240
 
        supports_external_lookups attribute.
241
 
 
242
 
        :return: norepository or ok, relpath.
243
 
        """
244
 
        try:
245
 
            path, rich_root, tree_ref, external_lookup, name = self._find(path)
246
 
            return SuccessfulSmartServerResponse(('ok', path, rich_root, tree_ref))
247
 
        except errors.NoRepositoryPresent:
248
 
            return FailedSmartServerResponse(('norepository', ))
249
 
 
250
 
 
251
 
class SmartServerRequestFindRepositoryV2(SmartServerRequestFindRepository):
252
 
 
253
 
    def do(self, path):
254
 
        """try to find a repository from path upwards
255
 
 
256
 
        This operates precisely like 'bzrdir.find_repository'.
257
 
 
258
 
        If a bzrdir is not present, an exception is propagated
259
 
        rather than 'no branch' because these are different conditions.
260
 
 
261
 
        This is the second edition of this method introduced in bzr 1.3, which
262
 
        returns information about the supports_external_lookups format
263
 
        attribute too.
264
 
 
265
 
        :return: norepository or ok, relpath, rich_root, tree_ref,
266
 
            external_lookup.
267
 
        """
268
 
        try:
269
 
            path, rich_root, tree_ref, external_lookup, name = self._find(path)
270
 
            return SuccessfulSmartServerResponse(
271
 
                ('ok', path, rich_root, tree_ref, external_lookup))
272
 
        except errors.NoRepositoryPresent:
273
 
            return FailedSmartServerResponse(('norepository', ))
274
 
 
275
 
 
276
 
class SmartServerRequestFindRepositoryV3(SmartServerRequestFindRepository):
277
 
 
278
 
    def do(self, path):
279
 
        """try to find a repository from path upwards
280
 
 
281
 
        This operates precisely like 'bzrdir.find_repository'.
282
 
 
283
 
        If a bzrdir is not present, an exception is propogated
284
 
        rather than 'no branch' because these are different conditions.
285
 
 
286
 
        This is the third edition of this method introduced in bzr 1.13, which
287
 
        returns information about the network name of the repository format.
288
 
 
289
 
        :return: norepository or ok, relpath, rich_root, tree_ref,
290
 
            external_lookup, network_name.
291
 
        """
292
 
        try:
293
 
            path, rich_root, tree_ref, external_lookup, name = self._find(path)
294
 
            return SuccessfulSmartServerResponse(
295
 
                ('ok', path, rich_root, tree_ref, external_lookup, name))
296
 
        except errors.NoRepositoryPresent:
297
 
            return FailedSmartServerResponse(('norepository', ))
298
 
 
299
 
 
300
 
class SmartServerRequestInitializeBzrDir(SmartServerRequest):
301
 
 
302
 
    def do(self, path):
303
 
        """Initialize a bzrdir at path.
304
 
 
305
 
        The default format of the server is used.
306
 
        :return: SmartServerResponse(('ok', ))
307
 
        """
308
 
        target_transport = self.transport_from_client_path(path)
309
 
        BzrDirFormat.get_default_format().initialize_on_transport(target_transport)
310
 
        return SuccessfulSmartServerResponse(('ok', ))
311
 
 
312
 
 
313
 
class SmartServerRequestOpenBranch(SmartServerRequestBzrDir):
314
 
 
315
 
    def do_bzrdir_request(self):
316
 
        """open a branch at path and return the branch reference or branch."""
317
 
        try:
318
 
            reference_url = self._bzrdir.get_branch_reference()
319
 
            if reference_url is None:
320
 
                return SuccessfulSmartServerResponse(('ok', ''))
321
 
            else:
322
 
                return SuccessfulSmartServerResponse(('ok', reference_url))
323
 
        except errors.NotBranchError:
324
 
            return FailedSmartServerResponse(('nobranch', ))
325
 
 
326
 
 
327
 
class SmartServerRequestOpenBranchV2(SmartServerRequestBzrDir):
328
 
 
329
 
    def do_bzrdir_request(self):
330
 
        """open a branch at path and return the reference or format."""
331
 
        try:
332
 
            reference_url = self._bzrdir.get_branch_reference()
333
 
            if reference_url is None:
334
 
                br = self._bzrdir.open_branch(ignore_fallbacks=True)
335
 
                format = br._format.network_name()
336
 
                return SuccessfulSmartServerResponse(('branch', format))
337
 
            else:
338
 
                return SuccessfulSmartServerResponse(('ref', reference_url))
339
 
        except errors.NotBranchError:
340
 
            return FailedSmartServerResponse(('nobranch', ))