37
29
class SmartServerRequestOpenBzrDir(SmartServerRequest):
39
31
def do(self, path):
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)
41
t = self.transport_from_client_path(path)
42
except errors.PathNotChild:
43
# The client is trying to ask about a path that they have no access
45
# Ideally we'd return a FailedSmartServerResponse here rather than
46
# a "successful" negative, but we want to be compatibile with
47
# clients that don't anticipate errors from this method.
37
real_bzrdir._format.probe_transport(t)
38
except (errors.NotBranchError, errors.UnknownFormatError):
50
bzr_prober = BzrProber()
52
bzr_prober.probe_transport(t)
53
except (errors.NotBranchError, errors.UnknownFormatError):
57
42
return SuccessfulSmartServerResponse((answer,))
60
class SmartServerRequestOpenBzrDir_2_1(SmartServerRequest):
63
"""Is there a BzrDir present, and if so does it have a working tree?
68
t = self.transport_from_client_path(path)
69
except errors.PathNotChild:
70
# The client is trying to ask about a path that they have no access
72
return SuccessfulSmartServerResponse(('no',))
74
bd = BzrDir.open_from_transport(t)
75
except errors.NotBranchError:
79
if bd.has_workingtree():
83
return SuccessfulSmartServerResponse(answer)
86
class SmartServerRequestBzrDir(SmartServerRequest):
88
def do(self, path, *args):
89
"""Open a BzrDir at path, and return `self.do_bzrdir_request(*args)`."""
91
self._bzrdir = BzrDir.open_from_transport(
92
self.transport_from_client_path(path))
93
except errors.NotBranchError, e:
94
return FailedSmartServerResponse(('nobranch',))
95
return self.do_bzrdir_request(*args)
45
class SmartServerRequestFindRepository(SmartServerRequest):
97
47
def _boolean_to_yes_no(self, a_boolean):
103
def _format_to_capabilities(self, repo_format):
104
rich_root = self._boolean_to_yes_no(repo_format.rich_root_data)
105
tree_ref = self._boolean_to_yes_no(
106
repo_format.supports_tree_reference)
107
external_lookup = self._boolean_to_yes_no(
108
repo_format.supports_external_lookups)
109
return rich_root, tree_ref, external_lookup
111
def _repo_relpath(self, current_transport, repository):
112
"""Get the relative path for repository from current_transport."""
113
# the relpath of the bzrdir in the found repository gives us the
53
def _find(self, path):
54
"""try to find a repository from path upwards
56
This operates precisely like 'bzrdir.find_repository'.
58
:return: (relpath, rich_root, tree_ref, external_lookup) flags. All are
59
strings, relpath is a / prefixed path, and the other three are
61
:raises errors.NoRepositoryPresent: When there is no repository
64
bzrdir = BzrDir.open_from_transport(self._backing_transport.clone(path))
65
repository = bzrdir.find_repository()
66
# the relpath of the bzrdir in the found repository gives us the
114
67
# path segments to pop-out.
115
relpath = repository.user_transport.relpath(
116
current_transport.base)
68
relpath = repository.bzrdir.root_transport.relpath(bzrdir.root_transport.base)
118
70
segments = ['..'] * len(relpath.split('/'))
121
return '/'.join(segments)
124
class SmartServerBzrDirRequestCloningMetaDir(SmartServerRequestBzrDir):
126
def do_bzrdir_request(self, require_stacking):
127
"""Get the format that should be used when cloning from this dir.
131
:return: on success, a 3-tuple of network names for (control,
132
repository, branch) directories, where '' signifies "not present".
133
If this BzrDir contains a branch reference then this will fail with
134
BranchReference; clients should resolve branch references before
138
branch_ref = self._bzrdir.get_branch_reference()
139
except errors.NotBranchError:
141
if branch_ref is not None:
142
# The server shouldn't try to resolve references, and it quite
143
# possibly can't reach them anyway. The client needs to resolve
144
# the branch reference to determine the cloning_metadir.
145
return FailedSmartServerResponse(('BranchReference',))
146
if require_stacking == "True":
147
require_stacking = True
149
require_stacking = False
150
control_format = self._bzrdir.cloning_metadir(
151
require_stacking=require_stacking)
152
control_name = control_format.network_name()
153
if not control_format.fixed_components:
154
branch_name = ('branch',
155
control_format.get_branch_format().network_name())
156
repository_name = control_format.repository_format.network_name()
158
# Only MetaDir has delegated formats today.
159
branch_name = ('branch', '')
161
return SuccessfulSmartServerResponse((control_name, repository_name,
165
class SmartServerRequestCreateBranch(SmartServerRequestBzrDir):
167
def do(self, path, network_name):
168
"""Create a branch in the bzr dir at path.
170
This operates precisely like 'bzrdir.create_branch'.
172
If a bzrdir is not present, an exception is propogated
173
rather than 'no branch' because these are different conditions (and
174
this method should only be called after establishing that a bzr dir
177
This is the initial version of this method introduced to the smart
180
:param path: The path to the bzrdir.
181
:param network_name: The network name of the branch type to create.
182
:return: ('ok', branch_format, repo_path, rich_root, tree_ref,
183
external_lookup, repo_format)
185
bzrdir = BzrDir.open_from_transport(
186
self.transport_from_client_path(path))
187
format = branch.network_format_registry.get(network_name)
188
bzrdir.branch_format = format
189
result = format.initialize(bzrdir)
190
rich_root, tree_ref, external_lookup = self._format_to_capabilities(
191
result.repository._format)
192
branch_format = result._format.network_name()
193
repo_format = result.repository._format.network_name()
194
repo_path = self._repo_relpath(bzrdir.root_transport,
196
# branch format, repo relpath, rich_root, tree_ref, external_lookup,
198
return SuccessfulSmartServerResponse(('ok', branch_format, repo_path,
199
rich_root, tree_ref, external_lookup, repo_format))
202
class SmartServerRequestCreateRepository(SmartServerRequestBzrDir):
204
def do(self, path, network_name, shared):
205
"""Create a repository in the bzr dir at path.
207
This operates precisely like 'bzrdir.create_repository'.
209
If a bzrdir is not present, an exception is propagated
210
rather than 'no branch' because these are different conditions (and
211
this method should only be called after establishing that a bzr dir
214
This is the initial version of this method introduced to the smart
217
:param path: The path to the bzrdir.
218
:param network_name: The network name of the repository type to create.
219
:param shared: The value to pass create_repository for the shared
221
:return: (ok, rich_root, tree_ref, external_lookup, network_name)
223
bzrdir = BzrDir.open_from_transport(
224
self.transport_from_client_path(path))
225
shared = shared == 'True'
226
format = repository.network_format_registry.get(network_name)
227
bzrdir.repository_format = format
228
result = format.initialize(bzrdir, shared=shared)
229
rich_root, tree_ref, external_lookup = self._format_to_capabilities(
231
return SuccessfulSmartServerResponse(('ok', rich_root, tree_ref,
232
external_lookup, result._format.network_name()))
235
class SmartServerRequestFindRepository(SmartServerRequestBzrDir):
237
def _find(self, path):
238
"""try to find a repository from path upwards
240
This operates precisely like 'bzrdir.find_repository'.
242
:return: (relpath, rich_root, tree_ref, external_lookup, network_name).
243
All are strings, relpath is a / prefixed path, the next three are
244
either 'yes' or 'no', and the last is a repository format network
246
:raises errors.NoRepositoryPresent: When there is no repository
249
bzrdir = BzrDir.open_from_transport(
250
self.transport_from_client_path(path))
251
repository = bzrdir.find_repository()
252
path = self._repo_relpath(bzrdir.root_transport, repository)
253
rich_root, tree_ref, external_lookup = self._format_to_capabilities(
255
network_name = repository._format.network_name()
256
return path, rich_root, tree_ref, external_lookup, network_name
73
rich_root = self._boolean_to_yes_no(repository.supports_rich_root())
74
tree_ref = self._boolean_to_yes_no(
75
repository._format.supports_tree_reference)
76
external_lookup = self._boolean_to_yes_no(
77
repository._format.supports_external_lookups)
78
return '/'.join(segments), rich_root, tree_ref, external_lookup
259
81
class SmartServerRequestFindRepositoryV1(SmartServerRequestFindRepository):
261
83
def do(self, path):
262
84
"""try to find a repository from path upwards
264
86
This operates precisely like 'bzrdir.find_repository'.
266
If a bzrdir is not present, an exception is propagated
88
If a bzrdir is not present, an exception is propogated
267
89
rather than 'no branch' because these are different conditions.
269
91
This is the initial version of this method introduced with the smart
284
106
def do(self, path):
285
107
"""try to find a repository from path upwards
287
109
This operates precisely like 'bzrdir.find_repository'.
289
If a bzrdir is not present, an exception is propagated
111
If a bzrdir is not present, an exception is propogated
290
112
rather than 'no branch' because these are different conditions.
292
114
This is the second edition of this method introduced in bzr 1.3, which
293
115
returns information about the supports_external_lookups format
296
:return: norepository or ok, relpath, rich_root, tree_ref,
118
:return: norepository or ok, relpath.
300
path, rich_root, tree_ref, external_lookup, name = self._find(path)
121
path, rich_root, tree_ref, external_lookup = self._find(path)
301
122
return SuccessfulSmartServerResponse(
302
123
('ok', path, rich_root, tree_ref, external_lookup))
303
124
except errors.NoRepositoryPresent:
304
125
return FailedSmartServerResponse(('norepository', ))
307
class SmartServerRequestFindRepositoryV3(SmartServerRequestFindRepository):
310
"""try to find a repository from path upwards
312
This operates precisely like 'bzrdir.find_repository'.
314
If a bzrdir is not present, an exception is propogated
315
rather than 'no branch' because these are different conditions.
317
This is the third edition of this method introduced in bzr 1.13, which
318
returns information about the network name of the repository format.
320
:return: norepository or ok, relpath, rich_root, tree_ref,
321
external_lookup, network_name.
324
path, rich_root, tree_ref, external_lookup, name = self._find(path)
325
return SuccessfulSmartServerResponse(
326
('ok', path, rich_root, tree_ref, external_lookup, name))
327
except errors.NoRepositoryPresent:
328
return FailedSmartServerResponse(('norepository', ))
331
class SmartServerBzrDirRequestConfigFile(SmartServerRequestBzrDir):
333
def do_bzrdir_request(self):
334
"""Get the configuration bytes for a config file in bzrdir.
336
The body is not utf8 decoded - it is the literal bytestream from disk.
338
config = self._bzrdir._get_config()
342
content = config._get_config_file().read()
343
return SuccessfulSmartServerResponse((), content)
346
128
class SmartServerRequestInitializeBzrDir(SmartServerRequest):
348
130
def do(self, path):
351
133
The default format of the server is used.
352
134
:return: SmartServerResponse(('ok', ))
354
target_transport = self.transport_from_client_path(path)
136
target_transport = self._backing_transport.clone(path)
355
137
BzrDirFormat.get_default_format().initialize_on_transport(target_transport)
356
138
return SuccessfulSmartServerResponse(('ok', ))
359
class SmartServerRequestBzrDirInitializeEx(SmartServerRequestBzrDir):
361
def parse_NoneTrueFalse(self, arg):
368
raise AssertionError("invalid arg %r" % arg)
370
def parse_NoneString(self, arg):
373
def _serialize_NoneTrueFalse(self, arg):
380
def do(self, bzrdir_network_name, path, use_existing_dir, create_prefix,
381
force_new_repo, stacked_on, stack_on_pwd, repo_format_name,
382
make_working_trees, shared_repo):
383
"""Initialize a bzrdir at path as per
384
BzrDirFormat.initialize_on_transport_ex.
386
New in 1.16. (Replaces BzrDirFormat.initialize_ex verb from 1.15).
388
:return: return SuccessfulSmartServerResponse((repo_path, rich_root,
389
tree_ref, external_lookup, repo_network_name,
390
repo_bzrdir_network_name, bzrdir_format_network_name,
391
NoneTrueFalse(stacking), final_stack, final_stack_pwd,
141
class SmartServerRequestOpenBranch(SmartServerRequest):
144
"""try to open a branch at path and return ok/nobranch.
146
If a bzrdir is not present, an exception is propogated
147
rather than 'no branch' because these are different conditions.
394
target_transport = self.transport_from_client_path(path)
395
format = network_format_registry.get(bzrdir_network_name)
396
use_existing_dir = self.parse_NoneTrueFalse(use_existing_dir)
397
create_prefix = self.parse_NoneTrueFalse(create_prefix)
398
force_new_repo = self.parse_NoneTrueFalse(force_new_repo)
399
stacked_on = self.parse_NoneString(stacked_on)
400
stack_on_pwd = self.parse_NoneString(stack_on_pwd)
401
make_working_trees = self.parse_NoneTrueFalse(make_working_trees)
402
shared_repo = self.parse_NoneTrueFalse(shared_repo)
403
if stack_on_pwd == '.':
404
stack_on_pwd = target_transport.base
405
repo_format_name = self.parse_NoneString(repo_format_name)
406
repo, bzrdir, stacking, repository_policy = \
407
format.initialize_on_transport_ex(target_transport,
408
use_existing_dir=use_existing_dir, create_prefix=create_prefix,
409
force_new_repo=force_new_repo, stacked_on=stacked_on,
410
stack_on_pwd=stack_on_pwd, repo_format_name=repo_format_name,
411
make_working_trees=make_working_trees, shared_repo=shared_repo)
415
rich_root = tree_ref = external_lookup = ''
416
repo_bzrdir_name = ''
418
final_stack_pwd = None
421
repo_path = self._repo_relpath(bzrdir.root_transport, repo)
424
rich_root, tree_ref, external_lookup = self._format_to_capabilities(
426
repo_name = repo._format.network_name()
427
repo_bzrdir_name = repo.bzrdir._format.network_name()
428
final_stack = repository_policy._stack_on
429
final_stack_pwd = repository_policy._stack_on_pwd
430
# It is returned locked, but we need to do the lock to get the lock
433
repo_lock_token = repo.lock_write().repository_token or ''
435
repo.leave_lock_in_place()
437
final_stack = final_stack or ''
438
final_stack_pwd = final_stack_pwd or ''
440
# We want this to be relative to the bzrdir.
442
final_stack_pwd = urlutils.relative_url(
443
target_transport.base, final_stack_pwd)
445
# Can't meaningfully return a root path.
446
if final_stack.startswith('/'):
447
client_path = self._root_client_path + final_stack[1:]
448
final_stack = urlutils.relative_url(
449
self._root_client_path, client_path)
450
final_stack_pwd = '.'
452
return SuccessfulSmartServerResponse((repo_path, rich_root, tree_ref,
453
external_lookup, repo_name, repo_bzrdir_name,
454
bzrdir._format.network_name(),
455
self._serialize_NoneTrueFalse(stacking), final_stack,
456
final_stack_pwd, repo_lock_token))
459
class SmartServerRequestOpenBranch(SmartServerRequestBzrDir):
461
def do_bzrdir_request(self):
462
"""open a branch at path and return the branch reference or branch."""
149
bzrdir = BzrDir.open_from_transport(self._backing_transport.clone(path))
464
reference_url = self._bzrdir.get_branch_reference()
151
reference_url = bzrdir.get_branch_reference()
465
152
if reference_url is None:
466
153
return SuccessfulSmartServerResponse(('ok', ''))
468
155
return SuccessfulSmartServerResponse(('ok', reference_url))
469
except errors.NotBranchError, e:
470
return FailedSmartServerResponse(('nobranch',))
473
class SmartServerRequestOpenBranchV2(SmartServerRequestBzrDir):
475
def do_bzrdir_request(self):
476
"""open a branch at path and return the reference or format."""
478
reference_url = self._bzrdir.get_branch_reference()
479
if reference_url is None:
480
br = self._bzrdir.open_branch(ignore_fallbacks=True)
481
format = br._format.network_name()
482
return SuccessfulSmartServerResponse(('branch', format))
484
return SuccessfulSmartServerResponse(('ref', reference_url))
485
except errors.NotBranchError, e:
486
return FailedSmartServerResponse(('nobranch',))
489
class SmartServerRequestOpenBranchV3(SmartServerRequestBzrDir):
491
def do_bzrdir_request(self):
492
"""Open a branch at path and return the reference or format.
494
This version introduced in 2.1.
496
Differences to SmartServerRequestOpenBranchV2:
497
* can return 2-element ('nobranch', extra), where 'extra' is a string
498
with an explanation like 'location is a repository'. Previously
499
a 'nobranch' response would never have more than one element.
502
reference_url = self._bzrdir.get_branch_reference()
503
if reference_url is None:
504
br = self._bzrdir.open_branch(ignore_fallbacks=True)
505
format = br._format.network_name()
506
return SuccessfulSmartServerResponse(('branch', format))
508
return SuccessfulSmartServerResponse(('ref', reference_url))
509
except errors.NotBranchError, e:
510
# Stringify the exception so that its .detail attribute will be
516
if detail.startswith(': '):
519
return FailedSmartServerResponse(resp)
156
except errors.NotBranchError:
157
return FailedSmartServerResponse(('nobranch', ))