17
17
"""Server-side bzrdir related request implmentations."""
19
from __future__ import absolute_import
31
from ..bzrdir import (
20
from bzrlib import branch, errors, repository, urlutils
21
from bzrlib.bzrdir import (
35
from ...controldir import (
36
25
network_format_registry,
38
from ...sixish import PY3
39
from .request import (
27
from bzrlib.smart.request import (
40
28
FailedSmartServerResponse,
41
29
SmartServerRequest,
42
30
SuccessfulSmartServerResponse,
54
42
# Ideally we'd return a FailedSmartServerResponse here rather than
55
43
# a "successful" negative, but we want to be compatibile with
56
44
# clients that don't anticipate errors from this method.
59
bzr_prober = BzrProber()
47
default_format = BzrDirFormat.get_default_format()
48
real_bzrdir = default_format.open(t, _found=True)
61
bzr_prober.probe_transport(t)
50
real_bzrdir._format.probe_transport(t)
62
51
except (errors.NotBranchError, errors.UnknownFormatError):
66
55
return SuccessfulSmartServerResponse((answer,))
78
67
except errors.PathNotChild:
79
68
# The client is trying to ask about a path that they have no access
81
return SuccessfulSmartServerResponse((b'no',))
70
return SuccessfulSmartServerResponse(('no',))
83
72
bd = BzrDir.open_from_transport(t)
84
73
except errors.NotBranchError:
88
77
if bd.has_workingtree():
92
81
return SuccessfulSmartServerResponse(answer)
95
84
class SmartServerRequestBzrDir(SmartServerRequest):
97
86
def do(self, path, *args):
98
"""Open a BzrDir at path, and return `self.do_bzrdir_request(*args)`."""
87
"""Open a BzrDir at path, and return self.do_bzrdir_request(*args)."""
100
89
self._bzrdir = BzrDir.open_from_transport(
101
90
self.transport_from_client_path(path))
102
except errors.NotBranchError as e:
103
return FailedSmartServerResponse((b'nobranch',))
91
except errors.NotBranchError, e:
92
return FailedSmartServerResponse(('nobranch',))
104
93
return self.do_bzrdir_request(*args)
106
95
def _boolean_to_yes_no(self, a_boolean):
112
101
def _format_to_capabilities(self, repo_format):
113
102
rich_root = self._boolean_to_yes_no(repo_format.rich_root_data)
130
119
return '/'.join(segments)
133
class SmartServerBzrDirRequestDestroyBranch(SmartServerRequestBzrDir):
135
def do_bzrdir_request(self, name=None):
136
"""Destroy the branch with the specified name.
139
:return: On success, 'ok'.
142
self._bzrdir.destroy_branch(
143
name.decode('utf-8') if name is not None else None)
144
except errors.NotBranchError as e:
145
return FailedSmartServerResponse((b'nobranch',))
146
return SuccessfulSmartServerResponse((b'ok',))
149
class SmartServerBzrDirRequestHasWorkingTree(SmartServerRequestBzrDir):
151
def do_bzrdir_request(self, name=None):
152
"""Check whether there is a working tree present.
156
:return: If there is a working tree present, 'yes'.
159
if self._bzrdir.has_workingtree():
160
return SuccessfulSmartServerResponse((b'yes', ))
162
return SuccessfulSmartServerResponse((b'no', ))
165
class SmartServerBzrDirRequestDestroyRepository(SmartServerRequestBzrDir):
167
def do_bzrdir_request(self, name=None):
168
"""Destroy the repository.
172
:return: On success, 'ok'.
175
self._bzrdir.destroy_repository()
176
except errors.NoRepositoryPresent as e:
177
return FailedSmartServerResponse((b'norepository',))
178
return SuccessfulSmartServerResponse((b'ok',))
181
122
class SmartServerBzrDirRequestCloningMetaDir(SmartServerRequestBzrDir):
183
124
def do_bzrdir_request(self, require_stacking):
184
125
"""Get the format that should be used when cloning from this dir.
188
129
:return: on success, a 3-tuple of network names for (control,
189
130
repository, branch) directories, where '' signifies "not present".
190
131
If this BzrDir contains a branch reference then this will fail with
199
140
# The server shouldn't try to resolve references, and it quite
200
141
# possibly can't reach them anyway. The client needs to resolve
201
142
# the branch reference to determine the cloning_metadir.
202
return FailedSmartServerResponse((b'BranchReference',))
203
if require_stacking == b"True":
143
return FailedSmartServerResponse(('BranchReference',))
144
if require_stacking == "True":
204
145
require_stacking = True
206
147
require_stacking = False
207
148
control_format = self._bzrdir.cloning_metadir(
208
149
require_stacking=require_stacking)
209
150
control_name = control_format.network_name()
210
if not control_format.fixed_components:
211
branch_name = (b'branch',
212
control_format.get_branch_format().network_name())
151
# XXX: There should be a method that tells us that the format does/does
152
# not have subformats.
153
if isinstance(control_format, BzrDirMetaFormat1):
154
branch_name = ('branch',
155
control_format.get_branch_format().network_name())
213
156
repository_name = control_format.repository_format.network_name()
215
158
# Only MetaDir has delegated formats today.
216
branch_name = (b'branch', b'')
217
repository_name = b''
159
branch_name = ('branch', '')
218
161
return SuccessfulSmartServerResponse((control_name, repository_name,
222
class SmartServerBzrDirRequestCheckoutMetaDir(SmartServerRequestBzrDir):
223
"""Get the format to use for checkouts.
227
:return: on success, a 3-tuple of network names for (control,
228
repository, branch) directories, where '' signifies "not present".
229
If this BzrDir contains a branch reference then this will fail with
230
BranchReference; clients should resolve branch references before
231
calling this RPC (they should not try to create a checkout of a
235
def do_bzrdir_request(self):
237
branch_ref = self._bzrdir.get_branch_reference()
238
except errors.NotBranchError:
240
if branch_ref is not None:
241
# The server shouldn't try to resolve references, and it quite
242
# possibly can't reach them anyway. The client needs to resolve
243
# the branch reference to determine the cloning_metadir.
244
return FailedSmartServerResponse((b'BranchReference',))
245
control_format = self._bzrdir.checkout_metadir()
246
control_name = control_format.network_name()
247
if not control_format.fixed_components:
248
branch_name = control_format.get_branch_format().network_name()
249
repo_name = control_format.repository_format.network_name()
253
return SuccessfulSmartServerResponse(
254
(control_name, repo_name, branch_name))
257
165
class SmartServerRequestCreateBranch(SmartServerRequestBzrDir):
272
180
:param path: The path to the bzrdir.
273
181
:param network_name: The network name of the branch type to create.
274
:return: ('ok', branch_format, repo_path, rich_root, tree_ref,
275
external_lookup, repo_format)
182
:return: (ok, network_name)
277
184
bzrdir = BzrDir.open_from_transport(
278
185
self.transport_from_client_path(path))
279
186
format = branch.network_format_registry.get(network_name)
280
187
bzrdir.branch_format = format
281
result = format.initialize(bzrdir, name="")
188
result = format.initialize(bzrdir)
282
189
rich_root, tree_ref, external_lookup = self._format_to_capabilities(
283
190
result.repository._format)
284
191
branch_format = result._format.network_name()
285
192
repo_format = result.repository._format.network_name()
286
193
repo_path = self._repo_relpath(bzrdir.root_transport,
288
195
# branch format, repo relpath, rich_root, tree_ref, external_lookup,
289
196
# repo_network_name
290
return SuccessfulSmartServerResponse((b'ok', branch_format, repo_path,
291
rich_root, tree_ref, external_lookup, repo_format))
197
return SuccessfulSmartServerResponse(('ok', branch_format, repo_path,
198
rich_root, tree_ref, external_lookup, repo_format))
294
201
class SmartServerRequestCreateRepository(SmartServerRequestBzrDir):
315
222
bzrdir = BzrDir.open_from_transport(
316
223
self.transport_from_client_path(path))
317
shared = shared == b'True'
224
shared = shared == 'True'
318
225
format = repository.network_format_registry.get(network_name)
319
226
bzrdir.repository_format = format
320
227
result = format.initialize(bzrdir, shared=shared)
321
228
rich_root, tree_ref, external_lookup = self._format_to_capabilities(
323
return SuccessfulSmartServerResponse((b'ok', rich_root, tree_ref,
324
external_lookup, result._format.network_name()))
230
return SuccessfulSmartServerResponse(('ok', rich_root, tree_ref,
231
external_lookup, result._format.network_name()))
327
234
class SmartServerRequestFindRepository(SmartServerRequestBzrDir):
368
275
path, rich_root, tree_ref, external_lookup, name = self._find(path)
369
return SuccessfulSmartServerResponse((b'ok', path.encode('utf-8'), rich_root, tree_ref))
276
return SuccessfulSmartServerResponse(('ok', path, rich_root, tree_ref))
370
277
except errors.NoRepositoryPresent:
371
return FailedSmartServerResponse((b'norepository', ))
278
return FailedSmartServerResponse(('norepository', ))
374
281
class SmartServerRequestFindRepositoryV2(SmartServerRequestFindRepository):
392
299
path, rich_root, tree_ref, external_lookup, name = self._find(path)
393
300
return SuccessfulSmartServerResponse(
394
(b'ok', path.encode('utf-8'), rich_root, tree_ref, external_lookup))
301
('ok', path, rich_root, tree_ref, external_lookup))
395
302
except errors.NoRepositoryPresent:
396
return FailedSmartServerResponse((b'norepository', ))
303
return FailedSmartServerResponse(('norepository', ))
399
306
class SmartServerRequestFindRepositoryV3(SmartServerRequestFindRepository):
416
323
path, rich_root, tree_ref, external_lookup, name = self._find(path)
417
324
return SuccessfulSmartServerResponse(
418
(b'ok', path.encode('utf-8'), rich_root, tree_ref, external_lookup, name))
325
('ok', path, rich_root, tree_ref, external_lookup, name))
419
326
except errors.NoRepositoryPresent:
420
return FailedSmartServerResponse((b'norepository', ))
327
return FailedSmartServerResponse(('norepository', ))
423
330
class SmartServerBzrDirRequestConfigFile(SmartServerRequestBzrDir):
425
332
def do_bzrdir_request(self):
426
333
"""Get the configuration bytes for a config file in bzrdir.
428
335
The body is not utf8 decoded - it is the literal bytestream from disk.
430
337
config = self._bzrdir._get_config()
431
338
if config is None:
434
341
content = config._get_config_file().read()
435
342
return SuccessfulSmartServerResponse((), content)
438
class SmartServerBzrDirRequestGetBranches(SmartServerRequestBzrDir):
440
def do_bzrdir_request(self):
441
"""Get the branches in a control directory.
443
The body is a bencoded dictionary, with values similar to the return
444
value of the open branch request.
446
branches = self._bzrdir.get_branches()
448
for name, b in branches.items():
451
ret[name.encode('utf-8')] = (b"branch", b._format.network_name())
452
return SuccessfulSmartServerResponse(
453
(b"success", ), bencode.bencode(ret))
456
345
class SmartServerRequestInitializeBzrDir(SmartServerRequest):
458
347
def do(self, path):
471
360
def parse_NoneTrueFalse(self, arg):
478
367
raise AssertionError("invalid arg %r" % arg)
480
def parse_NoneBytestring(self, arg):
369
def parse_NoneString(self, arg):
481
370
return arg or None
483
def parse_NoneString(self, arg):
487
return arg.decode('utf-8')
491
372
def _serialize_NoneTrueFalse(self, arg):
498
379
def do(self, bzrdir_network_name, path, use_existing_dir, create_prefix,
499
force_new_repo, stacked_on, stack_on_pwd, repo_format_name,
500
make_working_trees, shared_repo):
380
force_new_repo, stacked_on, stack_on_pwd, repo_format_name,
381
make_working_trees, shared_repo):
501
382
"""Initialize a bzrdir at path as per
502
383
BzrDirFormat.initialize_on_transport_ex.
518
399
stack_on_pwd = self.parse_NoneString(stack_on_pwd)
519
400
make_working_trees = self.parse_NoneTrueFalse(make_working_trees)
520
401
shared_repo = self.parse_NoneTrueFalse(shared_repo)
521
if stack_on_pwd == b'.':
522
stack_on_pwd = target_transport.base.encode('utf-8')
523
repo_format_name = self.parse_NoneBytestring(repo_format_name)
402
if stack_on_pwd == '.':
403
stack_on_pwd = target_transport.base
404
repo_format_name = self.parse_NoneString(repo_format_name)
524
405
repo, bzrdir, stacking, repository_policy = \
525
406
format.initialize_on_transport_ex(target_transport,
526
use_existing_dir=use_existing_dir, create_prefix=create_prefix,
527
force_new_repo=force_new_repo, stacked_on=stacked_on,
528
stack_on_pwd=stack_on_pwd, repo_format_name=repo_format_name,
529
make_working_trees=make_working_trees, shared_repo=shared_repo)
407
use_existing_dir=use_existing_dir, create_prefix=create_prefix,
408
force_new_repo=force_new_repo, stacked_on=stacked_on,
409
stack_on_pwd=stack_on_pwd, repo_format_name=repo_format_name,
410
make_working_trees=make_working_trees, shared_repo=shared_repo)
533
rich_root = tree_ref = external_lookup = b''
534
repo_bzrdir_name = b''
414
rich_root = tree_ref = external_lookup = ''
415
repo_bzrdir_name = ''
535
416
final_stack = None
536
417
final_stack_pwd = None
537
repo_lock_token = b''
539
420
repo_path = self._repo_relpath(bzrdir.root_transport, repo)
540
421
if repo_path == '':
542
423
rich_root, tree_ref, external_lookup = self._format_to_capabilities(
544
425
repo_name = repo._format.network_name()
545
repo_bzrdir_name = repo.controldir._format.network_name()
426
repo_bzrdir_name = repo.bzrdir._format.network_name()
546
427
final_stack = repository_policy._stack_on
547
428
final_stack_pwd = repository_policy._stack_on_pwd
548
429
# It is returned locked, but we need to do the lock to get the lock
551
repo_lock_token = repo.lock_write().repository_token or b''
432
repo_lock_token = repo.lock_write() or ''
552
433
if repo_lock_token:
553
434
repo.leave_lock_in_place()
567
448
self._root_client_path, client_path)
568
449
final_stack_pwd = '.'
570
return SuccessfulSmartServerResponse((repo_path.encode('utf-8'),
571
rich_root, tree_ref, external_lookup, repo_name, repo_bzrdir_name,
572
bzrdir._format.network_name(),
573
self._serialize_NoneTrueFalse(
574
stacking), final_stack.encode('utf-8'),
575
final_stack_pwd.encode('utf-8'), repo_lock_token))
451
return SuccessfulSmartServerResponse((repo_path, rich_root, tree_ref,
452
external_lookup, repo_name, repo_bzrdir_name,
453
bzrdir._format.network_name(),
454
self._serialize_NoneTrueFalse(stacking), final_stack,
455
final_stack_pwd, repo_lock_token))
578
458
class SmartServerRequestOpenBranch(SmartServerRequestBzrDir):
583
463
reference_url = self._bzrdir.get_branch_reference()
584
464
if reference_url is None:
586
return SuccessfulSmartServerResponse((b'ok', reference_url.encode('utf-8')))
587
except errors.NotBranchError as e:
588
return FailedSmartServerResponse((b'nobranch',))
465
return SuccessfulSmartServerResponse(('ok', ''))
467
return SuccessfulSmartServerResponse(('ok', reference_url))
468
except errors.NotBranchError, e:
469
return FailedSmartServerResponse(('nobranch',))
591
472
class SmartServerRequestOpenBranchV2(SmartServerRequestBzrDir):
597
478
if reference_url is None:
598
479
br = self._bzrdir.open_branch(ignore_fallbacks=True)
599
480
format = br._format.network_name()
600
return SuccessfulSmartServerResponse((b'branch', format))
481
return SuccessfulSmartServerResponse(('branch', format))
602
return SuccessfulSmartServerResponse((b'ref', reference_url.encode('utf-8')))
603
except errors.NotBranchError as e:
604
return FailedSmartServerResponse((b'nobranch',))
483
return SuccessfulSmartServerResponse(('ref', reference_url))
484
except errors.NotBranchError, e:
485
return FailedSmartServerResponse(('nobranch',))
607
488
class SmartServerRequestOpenBranchV3(SmartServerRequestBzrDir):
609
490
def do_bzrdir_request(self):
610
491
"""Open a branch at path and return the reference or format.
612
493
This version introduced in 2.1.
614
495
Differences to SmartServerRequestOpenBranchV2:
621
502
if reference_url is None:
622
503
br = self._bzrdir.open_branch(ignore_fallbacks=True)
623
504
format = br._format.network_name()
624
return SuccessfulSmartServerResponse((b'branch', format))
505
return SuccessfulSmartServerResponse(('branch', format))
626
return SuccessfulSmartServerResponse((b'ref', reference_url.encode('utf-8')))
627
except errors.NotBranchError as e:
507
return SuccessfulSmartServerResponse(('ref', reference_url))
508
except errors.NotBranchError, e:
628
509
# Stringify the exception so that its .detail attribute will be
631
resp = (b'nobranch',)
632
513
detail = e.detail
634
515
if detail.startswith(': '):
635
516
detail = detail[2:]
636
resp += (detail.encode('utf-8'),)
637
518
return FailedSmartServerResponse(resp)