~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/smart/bzrdir.py

  • Committer: Martin Pool
  • Date: 2009-03-03 01:45:32 UTC
  • mto: (4070.4.5 gnu-changelog)
  • mto: This revision was merged to the branch mainline in revision 4081.
  • Revision ID: mbp@sourcefrog.net-20090303014532-d223fxy97cb1og8f
Recommend setting timestamp in BranchBuilder

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
 
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 _boolean_to_yes_no(self, a_boolean):
 
57
        if a_boolean:
 
58
            return 'yes'
 
59
        else:
 
60
            return 'no'
 
61
 
 
62
    def _format_to_capabilities(self, repo_format):
 
63
        rich_root = self._boolean_to_yes_no(repo_format.rich_root_data)
 
64
        tree_ref = self._boolean_to_yes_no(
 
65
            repo_format.supports_tree_reference)
 
66
        external_lookup = self._boolean_to_yes_no(
 
67
            repo_format.supports_external_lookups)
 
68
        return rich_root, tree_ref, external_lookup
 
69
 
 
70
    def _repo_relpath(self, current_transport, repository):
 
71
        """Get the relative path for repository from current_transport."""
 
72
        # the relpath of the bzrdir in the found repository gives us the
 
73
        # path segments to pop-out.
 
74
        relpath = repository.bzrdir.root_transport.relpath(
 
75
            current_transport.base)
 
76
        if len(relpath):
 
77
            segments = ['..'] * len(relpath.split('/'))
 
78
        else:
 
79
            segments = []
 
80
        return '/'.join(segments)
 
81
 
 
82
 
 
83
class SmartServerRequestCreateBranch(SmartServerRequestBzrDir):
 
84
 
 
85
    def do(self, path, network_name):
 
86
        """Create a branch in the bzr dir at path.
 
87
 
 
88
        This operates precisely like 'bzrdir.create_branch'.
 
89
 
 
90
        If a bzrdir is not present, an exception is propogated
 
91
        rather than 'no branch' because these are different conditions (and
 
92
        this method should only be called after establishing that a bzr dir
 
93
        exists anyway).
 
94
 
 
95
        This is the initial version of this method introduced to the smart
 
96
        server for 1.13.
 
97
 
 
98
        :param path: The path to the bzrdir.
 
99
        :param network_name: The network name of the branch type to create.
 
100
        :return: (ok, network_name)
 
101
        """
 
102
        bzrdir = BzrDir.open_from_transport(
 
103
            self.transport_from_client_path(path))
 
104
        format = branch.network_format_registry.get(network_name)
 
105
        bzrdir.branch_format = format
 
106
        result = format.initialize(bzrdir)
 
107
        rich_root, tree_ref, external_lookup = self._format_to_capabilities(
 
108
            result.repository._format)
 
109
        branch_format = result._format.network_name()
 
110
        repo_format = result.repository._format.network_name()
 
111
        repo_path = self._repo_relpath(bzrdir.root_transport,
 
112
            result.repository)
 
113
        # branch format, repo relpath, rich_root, tree_ref, external_lookup,
 
114
        # repo_network_name
 
115
        return SuccessfulSmartServerResponse(('ok', branch_format, repo_path,
 
116
            rich_root, tree_ref, external_lookup, repo_format))
 
117
 
 
118
 
 
119
class SmartServerRequestCreateRepository(SmartServerRequestBzrDir):
 
120
 
 
121
    def do(self, path, network_name, shared):
 
122
        """Create a repository in the bzr dir at path.
 
123
 
 
124
        This operates precisely like 'bzrdir.create_repository'.
 
125
 
 
126
        If a bzrdir is not present, an exception is propogated
 
127
        rather than 'no branch' because these are different conditions (and
 
128
        this method should only be called after establishing that a bzr dir
 
129
        exists anyway).
 
130
 
 
131
        This is the initial version of this method introduced to the smart
 
132
        server for 1.13.
 
133
 
 
134
        :param path: The path to the bzrdir.
 
135
        :param network_name: The network name of the repository type to create.
 
136
        :param shared: The value to pass create_repository for the shared
 
137
            parameter.
 
138
        :return: (ok, rich_root, tree_ref, external_lookup, network_name)
 
139
        """
 
140
        bzrdir = BzrDir.open_from_transport(
 
141
            self.transport_from_client_path(path))
 
142
        shared = shared == 'True'
 
143
        format = repository.network_format_registry.get(network_name)
 
144
        bzrdir.repository_format = format
 
145
        result = format.initialize(bzrdir, shared=shared)
 
146
        rich_root, tree_ref, external_lookup = self._format_to_capabilities(
 
147
            result._format)
 
148
        return SuccessfulSmartServerResponse(('ok', rich_root, tree_ref,
 
149
            external_lookup, result._format.network_name()))
 
150
 
 
151
 
 
152
class SmartServerRequestFindRepository(SmartServerRequestBzrDir):
 
153
 
 
154
    def _find(self, path):
 
155
        """try to find a repository from path upwards
 
156
 
 
157
        This operates precisely like 'bzrdir.find_repository'.
 
158
 
 
159
        :return: (relpath, rich_root, tree_ref, external_lookup, network_name).
 
160
            All are strings, relpath is a / prefixed path, the next three are
 
161
            either 'yes' or 'no', and the last is a repository format network
 
162
            name.
 
163
        :raises errors.NoRepositoryPresent: When there is no repository
 
164
            present.
 
165
        """
 
166
        bzrdir = BzrDir.open_from_transport(
 
167
            self.transport_from_client_path(path))
 
168
        repository = bzrdir.find_repository()
 
169
        path = self._repo_relpath(bzrdir.root_transport, repository)
 
170
        rich_root, tree_ref, external_lookup = self._format_to_capabilities(
 
171
            repository._format)
 
172
        network_name = repository._format.network_name()
 
173
        return path, rich_root, tree_ref, external_lookup, network_name
 
174
 
 
175
 
 
176
class SmartServerRequestFindRepositoryV1(SmartServerRequestFindRepository):
 
177
 
 
178
    def do(self, path):
 
179
        """try to find a repository from path upwards
 
180
 
 
181
        This operates precisely like 'bzrdir.find_repository'.
 
182
 
 
183
        If a bzrdir is not present, an exception is propogated
 
184
        rather than 'no branch' because these are different conditions.
 
185
 
 
186
        This is the initial version of this method introduced with the smart
 
187
        server. Modern clients will try the V2 method that adds support for the
 
188
        supports_external_lookups attribute.
 
189
 
 
190
        :return: norepository or ok, relpath.
 
191
        """
 
192
        try:
 
193
            path, rich_root, tree_ref, external_lookup, name = self._find(path)
 
194
            return SuccessfulSmartServerResponse(('ok', path, rich_root, tree_ref))
 
195
        except errors.NoRepositoryPresent:
 
196
            return FailedSmartServerResponse(('norepository', ))
 
197
 
 
198
 
 
199
class SmartServerRequestFindRepositoryV2(SmartServerRequestFindRepository):
 
200
 
 
201
    def do(self, path):
 
202
        """try to find a repository from path upwards
 
203
 
 
204
        This operates precisely like 'bzrdir.find_repository'.
 
205
 
 
206
        If a bzrdir is not present, an exception is propogated
 
207
        rather than 'no branch' because these are different conditions.
 
208
 
 
209
        This is the second edition of this method introduced in bzr 1.3, which
 
210
        returns information about the supports_external_lookups format
 
211
        attribute too.
 
212
 
 
213
        :return: norepository or ok, relpath, rich_root, tree_ref,
 
214
            external_lookup.
 
215
        """
 
216
        try:
 
217
            path, rich_root, tree_ref, external_lookup, name = self._find(path)
 
218
            return SuccessfulSmartServerResponse(
 
219
                ('ok', path, rich_root, tree_ref, external_lookup))
 
220
        except errors.NoRepositoryPresent:
 
221
            return FailedSmartServerResponse(('norepository', ))
 
222
 
 
223
 
 
224
class SmartServerRequestFindRepositoryV3(SmartServerRequestFindRepository):
 
225
 
 
226
    def do(self, path):
 
227
        """try to find a repository from path upwards
 
228
 
 
229
        This operates precisely like 'bzrdir.find_repository'.
 
230
 
 
231
        If a bzrdir is not present, an exception is propogated
 
232
        rather than 'no branch' because these are different conditions.
 
233
 
 
234
        This is the third edition of this method introduced in bzr 1.13, which
 
235
        returns information about the network name of the repository format.
 
236
 
 
237
        :return: norepository or ok, relpath, rich_root, tree_ref,
 
238
            external_lookup, network_name.
 
239
        """
 
240
        try:
 
241
            path, rich_root, tree_ref, external_lookup, name = self._find(path)
 
242
            return SuccessfulSmartServerResponse(
 
243
                ('ok', path, rich_root, tree_ref, external_lookup, name))
 
244
        except errors.NoRepositoryPresent:
 
245
            return FailedSmartServerResponse(('norepository', ))
 
246
 
 
247
 
 
248
class SmartServerRequestInitializeBzrDir(SmartServerRequest):
 
249
 
 
250
    def do(self, path):
 
251
        """Initialize a bzrdir at path.
 
252
 
 
253
        The default format of the server is used.
 
254
        :return: SmartServerResponse(('ok', ))
 
255
        """
 
256
        target_transport = self.transport_from_client_path(path)
 
257
        BzrDirFormat.get_default_format().initialize_on_transport(target_transport)
 
258
        return SuccessfulSmartServerResponse(('ok', ))
 
259
 
 
260
 
 
261
class SmartServerRequestOpenBranch(SmartServerRequest):
 
262
 
 
263
    def do(self, path):
 
264
        """try to open a branch at path and return ok/nobranch.
 
265
 
 
266
        If a bzrdir is not present, an exception is propogated
 
267
        rather than 'no branch' because these are different conditions.
 
268
        """
 
269
        bzrdir = BzrDir.open_from_transport(
 
270
            self.transport_from_client_path(path))
 
271
        try:
 
272
            reference_url = bzrdir.get_branch_reference()
 
273
            if reference_url is None:
 
274
                return SuccessfulSmartServerResponse(('ok', ''))
 
275
            else:
 
276
                return SuccessfulSmartServerResponse(('ok', reference_url))
 
277
        except errors.NotBranchError:
 
278
            return FailedSmartServerResponse(('nobranch', ))