31
31
def do(self, path):
32
32
from bzrlib.bzrdir import BzrDirFormat
33
t = self._backing_transport.clone(path)
34
default_format = BzrDirFormat.get_default_format()
35
real_bzrdir = default_format.open(t, _found=True)
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.
37
real_bzrdir._format.probe_transport(t)
38
except (errors.NotBranchError, errors.UnknownFormatError):
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
42
return SuccessfulSmartServerResponse((answer,))
54
class SmartServerRequestBzrDir(SmartServerRequest):
56
def do(self, path, *args):
57
"""Open a BzrDir at path, and return self.do_bzrdir_request(*args)."""
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)
65
def _boolean_to_yes_no(self, a_boolean):
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
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)
86
segments = ['..'] * len(relpath.split('/'))
89
return '/'.join(segments)
92
class SmartServerBzrDirRequestCloningMetaDir(SmartServerRequestBzrDir):
94
def do_bzrdir_request(self, require_stacking):
95
"""Get the format that should be used when cloning from this dir.
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
106
branch_ref = self._bzrdir.get_branch_reference()
107
except errors.NotBranchError:
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
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()
128
# Only MetaDir has delegated formats today.
129
branch_name = ('branch', '')
131
return SuccessfulSmartServerResponse((control_name, repository_name,
135
class SmartServerRequestCreateBranch(SmartServerRequestBzrDir):
137
def do(self, path, network_name):
138
"""Create a branch in the bzr dir at path.
140
This operates precisely like 'bzrdir.create_branch'.
45
class SmartServerRequestFindRepository(SmartServerRequest):
48
"""try to find a repository from path upwards
50
This operates precisely like 'bzrdir.find_repository'.
142
52
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
147
This is the initial version of this method introduced to the smart
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)
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,
165
# branch format, repo relpath, rich_root, tree_ref, external_lookup,
167
return SuccessfulSmartServerResponse(('ok', branch_format, repo_path,
168
rich_root, tree_ref, external_lookup, repo_format))
171
class SmartServerRequestCreateRepository(SmartServerRequestBzrDir):
173
def do(self, path, network_name, shared):
174
"""Create a repository in the bzr dir at path.
176
This operates precisely like 'bzrdir.create_repository'.
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
183
This is the initial version of this method introduced to the smart
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
190
:return: (ok, rich_root, tree_ref, external_lookup, network_name)
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(
200
return SuccessfulSmartServerResponse(('ok', rich_root, tree_ref,
201
external_lookup, result._format.network_name()))
204
class SmartServerRequestFindRepository(SmartServerRequestBzrDir):
206
def _find(self, path):
207
"""try to find a repository from path upwards
209
This operates precisely like 'bzrdir.find_repository'.
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
215
:raises errors.NoRepositoryPresent: When there is no repository
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(
224
network_name = repository._format.network_name()
225
return path, rich_root, tree_ref, external_lookup, network_name
228
class SmartServerRequestFindRepositoryV1(SmartServerRequestFindRepository):
231
"""try to find a repository from path upwards
233
This operates precisely like 'bzrdir.find_repository'.
235
If a bzrdir is not present, an exception is propagated
236
53
rather than 'no branch' because these are different conditions.
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.
242
55
:return: norepository or ok, relpath.
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', ))
251
class SmartServerRequestFindRepositoryV2(SmartServerRequestFindRepository):
254
"""try to find a repository from path upwards
256
This operates precisely like 'bzrdir.find_repository'.
258
If a bzrdir is not present, an exception is propagated
259
rather than 'no branch' because these are different conditions.
261
This is the second edition of this method introduced in bzr 1.3, which
262
returns information about the supports_external_lookups format
265
:return: norepository or ok, relpath, rich_root, tree_ref,
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', ))
276
class SmartServerRequestFindRepositoryV3(SmartServerRequestFindRepository):
279
"""try to find a repository from path upwards
281
This operates precisely like 'bzrdir.find_repository'.
283
If a bzrdir is not present, an exception is propogated
284
rather than 'no branch' because these are different conditions.
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.
289
:return: norepository or ok, relpath, rich_root, tree_ref,
290
external_lookup, network_name.
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))
57
bzrdir = BzrDir.open_from_transport(self._backing_transport.clone(path))
59
repository = bzrdir.find_repository()
60
# the relpath of the bzrdir in the found repository gives us the
61
# path segments to pop-out.
62
relpath = repository.bzrdir.root_transport.relpath(bzrdir.root_transport.base)
64
segments = ['..'] * len(relpath.split('/'))
67
if repository.supports_rich_root():
71
if repository._format.supports_tree_reference:
75
return SuccessfulSmartServerResponse(('ok', '/'.join(segments), rich_root, tree_ref))
296
76
except errors.NoRepositoryPresent:
297
77
return FailedSmartServerResponse(('norepository', ))