1
# Copyright (C) 2006 Canonical Ltd
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.
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.
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
17
"""Server-side bzrdir related request implmentations."""
20
from bzrlib import branch, errors, repository
21
from bzrlib.bzrdir import BzrDir, BzrDirFormat
22
from bzrlib.smart.request import (
23
FailedSmartServerResponse,
25
SuccessfulSmartServerResponse,
29
class SmartServerRequestOpenBzrDir(SmartServerRequest):
32
from bzrlib.bzrdir import BzrDirFormat
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
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.
43
default_format = BzrDirFormat.get_default_format()
44
real_bzrdir = default_format.open(t, _found=True)
46
real_bzrdir._format.probe_transport(t)
47
except (errors.NotBranchError, errors.UnknownFormatError):
51
return SuccessfulSmartServerResponse((answer,))
54
class SmartServerRequestBzrDir(SmartServerRequest):
56
def _boolean_to_yes_no(self, a_boolean):
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
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)
77
segments = ['..'] * len(relpath.split('/'))
80
return '/'.join(segments)
83
class SmartServerRequestCreateBranch(SmartServerRequestBzrDir):
85
def do(self, path, network_name):
86
"""Create a branch in the bzr dir at path.
88
This operates precisely like 'bzrdir.create_branch'.
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
95
This is the initial version of this method introduced to the smart
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)
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,
113
# branch format, repo relpath, rich_root, tree_ref, external_lookup,
115
return SuccessfulSmartServerResponse(('ok', branch_format, repo_path,
116
rich_root, tree_ref, external_lookup, repo_format))
119
class SmartServerRequestCreateRepository(SmartServerRequestBzrDir):
121
def do(self, path, network_name, shared):
122
"""Create a repository in the bzr dir at path.
124
This operates precisely like 'bzrdir.create_repository'.
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
131
This is the initial version of this method introduced to the smart
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
138
:return: (ok, rich_root, tree_ref, external_lookup, network_name)
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(
148
return SuccessfulSmartServerResponse(('ok', rich_root, tree_ref,
149
external_lookup, result._format.network_name()))
152
class SmartServerRequestFindRepository(SmartServerRequestBzrDir):
154
def _find(self, path):
155
"""try to find a repository from path upwards
157
This operates precisely like 'bzrdir.find_repository'.
159
:return: (relpath, rich_root, tree_ref, external_lookup) flags. All are
160
strings, relpath is a / prefixed path, and the other three are
161
either 'yes' or 'no'.
162
:raises errors.NoRepositoryPresent: When there is no repository
165
bzrdir = BzrDir.open_from_transport(
166
self.transport_from_client_path(path))
167
repository = bzrdir.find_repository()
168
path = self._repo_relpath(bzrdir.root_transport, repository)
169
rich_root, tree_ref, external_lookup = self._format_to_capabilities(
171
return path, rich_root, tree_ref, external_lookup
174
class SmartServerRequestFindRepositoryV1(SmartServerRequestFindRepository):
177
"""try to find a repository from path upwards
179
This operates precisely like 'bzrdir.find_repository'.
181
If a bzrdir is not present, an exception is propogated
182
rather than 'no branch' because these are different conditions.
184
This is the initial version of this method introduced with the smart
185
server. Modern clients will try the V2 method that adds support for the
186
supports_external_lookups attribute.
188
:return: norepository or ok, relpath.
191
path, rich_root, tree_ref, external_lookup = self._find(path)
192
return SuccessfulSmartServerResponse(('ok', path, rich_root, tree_ref))
193
except errors.NoRepositoryPresent:
194
return FailedSmartServerResponse(('norepository', ))
197
class SmartServerRequestFindRepositoryV2(SmartServerRequestFindRepository):
200
"""try to find a repository from path upwards
202
This operates precisely like 'bzrdir.find_repository'.
204
If a bzrdir is not present, an exception is propogated
205
rather than 'no branch' because these are different conditions.
207
This is the second edition of this method introduced in bzr 1.3, which
208
returns information about the supports_external_lookups format
211
:return: norepository or ok, relpath.
214
path, rich_root, tree_ref, external_lookup = self._find(path)
215
return SuccessfulSmartServerResponse(
216
('ok', path, rich_root, tree_ref, external_lookup))
217
except errors.NoRepositoryPresent:
218
return FailedSmartServerResponse(('norepository', ))
221
class SmartServerRequestInitializeBzrDir(SmartServerRequest):
224
"""Initialize a bzrdir at path.
226
The default format of the server is used.
227
:return: SmartServerResponse(('ok', ))
229
target_transport = self.transport_from_client_path(path)
230
BzrDirFormat.get_default_format().initialize_on_transport(target_transport)
231
return SuccessfulSmartServerResponse(('ok', ))
234
class SmartServerRequestOpenBranch(SmartServerRequest):
237
"""try to open a branch at path and return ok/nobranch.
239
If a bzrdir is not present, an exception is propogated
240
rather than 'no branch' because these are different conditions.
242
bzrdir = BzrDir.open_from_transport(
243
self.transport_from_client_path(path))
245
reference_url = bzrdir.get_branch_reference()
246
if reference_url is None:
247
return SuccessfulSmartServerResponse(('ok', ''))
249
return SuccessfulSmartServerResponse(('ok', reference_url))
250
except errors.NotBranchError:
251
return FailedSmartServerResponse(('nobranch', ))