17
17
"""Server-side bzrdir related request implmentations."""
19
from __future__ import absolute_import
29
from ..bzrdir import (
28
from bzrlib.bzrdir import (
33
from ...controldir import (
33
from bzrlib.controldir import (
34
34
network_format_registry,
36
from .request import (
36
from bzrlib.smart.request import (
37
37
FailedSmartServerResponse,
38
38
SmartServerRequest,
39
39
SuccessfulSmartServerResponse,
51
51
# Ideally we'd return a FailedSmartServerResponse here rather than
52
52
# a "successful" negative, but we want to be compatibile with
53
53
# clients that don't anticipate errors from this method.
56
56
bzr_prober = BzrProber()
58
58
bzr_prober.probe_transport(t)
59
59
except (errors.NotBranchError, errors.UnknownFormatError):
63
63
return SuccessfulSmartServerResponse((answer,))
75
75
except errors.PathNotChild:
76
76
# The client is trying to ask about a path that they have no access
78
return SuccessfulSmartServerResponse((b'no',))
78
return SuccessfulSmartServerResponse(('no',))
80
80
bd = BzrDir.open_from_transport(t)
81
81
except errors.NotBranchError:
85
85
if bd.has_workingtree():
89
89
return SuccessfulSmartServerResponse(answer)
97
97
self._bzrdir = BzrDir.open_from_transport(
98
98
self.transport_from_client_path(path))
99
except errors.NotBranchError as e:
100
return FailedSmartServerResponse((b'nobranch',))
99
except errors.NotBranchError, e:
100
return FailedSmartServerResponse(('nobranch',))
101
101
return self.do_bzrdir_request(*args)
103
103
def _boolean_to_yes_no(self, a_boolean):
109
109
def _format_to_capabilities(self, repo_format):
110
110
rich_root = self._boolean_to_yes_no(repo_format.rich_root_data)
136
136
:return: On success, 'ok'.
139
self._bzrdir.destroy_branch(
140
name.decode('utf-8') if name is not None else None)
141
except errors.NotBranchError as e:
142
return FailedSmartServerResponse((b'nobranch',))
143
return SuccessfulSmartServerResponse((b'ok',))
139
self._bzrdir.destroy_branch(name)
140
except errors.NotBranchError, e:
141
return FailedSmartServerResponse(('nobranch',))
142
return SuccessfulSmartServerResponse(('ok',))
146
145
class SmartServerBzrDirRequestHasWorkingTree(SmartServerRequestBzrDir):
156
155
if self._bzrdir.has_workingtree():
157
return SuccessfulSmartServerResponse((b'yes', ))
156
return SuccessfulSmartServerResponse(('yes', ))
159
return SuccessfulSmartServerResponse((b'no', ))
158
return SuccessfulSmartServerResponse(('no', ))
162
161
class SmartServerBzrDirRequestDestroyRepository(SmartServerRequestBzrDir):
172
171
self._bzrdir.destroy_repository()
173
except errors.NoRepositoryPresent as e:
174
return FailedSmartServerResponse((b'norepository',))
175
return SuccessfulSmartServerResponse((b'ok',))
172
except errors.NoRepositoryPresent, e:
173
return FailedSmartServerResponse(('norepository',))
174
return SuccessfulSmartServerResponse(('ok',))
178
177
class SmartServerBzrDirRequestCloningMetaDir(SmartServerRequestBzrDir):
181
180
"""Get the format that should be used when cloning from this dir.
185
184
:return: on success, a 3-tuple of network names for (control,
186
185
repository, branch) directories, where '' signifies "not present".
187
186
If this BzrDir contains a branch reference then this will fail with
196
195
# The server shouldn't try to resolve references, and it quite
197
196
# possibly can't reach them anyway. The client needs to resolve
198
197
# the branch reference to determine the cloning_metadir.
199
return FailedSmartServerResponse((b'BranchReference',))
200
if require_stacking == b"True":
198
return FailedSmartServerResponse(('BranchReference',))
199
if require_stacking == "True":
201
200
require_stacking = True
203
202
require_stacking = False
205
204
require_stacking=require_stacking)
206
205
control_name = control_format.network_name()
207
206
if not control_format.fixed_components:
208
branch_name = (b'branch',
209
control_format.get_branch_format().network_name())
207
branch_name = ('branch',
208
control_format.get_branch_format().network_name())
210
209
repository_name = control_format.repository_format.network_name()
212
211
# Only MetaDir has delegated formats today.
213
branch_name = (b'branch', b'')
214
repository_name = b''
212
branch_name = ('branch', '')
215
214
return SuccessfulSmartServerResponse((control_name, repository_name,
219
218
class SmartServerBzrDirRequestCheckoutMetaDir(SmartServerRequestBzrDir):
238
237
# The server shouldn't try to resolve references, and it quite
239
238
# possibly can't reach them anyway. The client needs to resolve
240
239
# the branch reference to determine the cloning_metadir.
241
return FailedSmartServerResponse((b'BranchReference',))
240
return FailedSmartServerResponse(('BranchReference',))
242
241
control_format = self._bzrdir.checkout_metadir()
243
242
control_name = control_format.network_name()
244
243
if not control_format.fixed_components:
245
244
branch_name = control_format.get_branch_format().network_name()
246
245
repo_name = control_format.repository_format.network_name()
250
249
return SuccessfulSmartServerResponse(
251
250
(control_name, repo_name, branch_name))
281
280
branch_format = result._format.network_name()
282
281
repo_format = result.repository._format.network_name()
283
282
repo_path = self._repo_relpath(bzrdir.root_transport,
285
284
# branch format, repo relpath, rich_root, tree_ref, external_lookup,
286
285
# repo_network_name
287
return SuccessfulSmartServerResponse((b'ok', branch_format, repo_path,
288
rich_root, tree_ref, external_lookup, repo_format))
286
return SuccessfulSmartServerResponse(('ok', branch_format, repo_path,
287
rich_root, tree_ref, external_lookup, repo_format))
291
290
class SmartServerRequestCreateRepository(SmartServerRequestBzrDir):
312
311
bzrdir = BzrDir.open_from_transport(
313
312
self.transport_from_client_path(path))
314
shared = shared == b'True'
313
shared = shared == 'True'
315
314
format = repository.network_format_registry.get(network_name)
316
315
bzrdir.repository_format = format
317
316
result = format.initialize(bzrdir, shared=shared)
318
317
rich_root, tree_ref, external_lookup = self._format_to_capabilities(
320
return SuccessfulSmartServerResponse((b'ok', rich_root, tree_ref,
321
external_lookup, result._format.network_name()))
319
return SuccessfulSmartServerResponse(('ok', rich_root, tree_ref,
320
external_lookup, result._format.network_name()))
324
323
class SmartServerRequestFindRepository(SmartServerRequestBzrDir):
365
364
path, rich_root, tree_ref, external_lookup, name = self._find(path)
366
return SuccessfulSmartServerResponse((b'ok', path.encode('utf-8'), rich_root, tree_ref))
365
return SuccessfulSmartServerResponse(('ok', path, rich_root, tree_ref))
367
366
except errors.NoRepositoryPresent:
368
return FailedSmartServerResponse((b'norepository', ))
367
return FailedSmartServerResponse(('norepository', ))
371
370
class SmartServerRequestFindRepositoryV2(SmartServerRequestFindRepository):
389
388
path, rich_root, tree_ref, external_lookup, name = self._find(path)
390
389
return SuccessfulSmartServerResponse(
391
(b'ok', path.encode('utf-8'), rich_root, tree_ref, external_lookup))
390
('ok', path, rich_root, tree_ref, external_lookup))
392
391
except errors.NoRepositoryPresent:
393
return FailedSmartServerResponse((b'norepository', ))
392
return FailedSmartServerResponse(('norepository', ))
396
395
class SmartServerRequestFindRepositoryV3(SmartServerRequestFindRepository):
413
412
path, rich_root, tree_ref, external_lookup, name = self._find(path)
414
413
return SuccessfulSmartServerResponse(
415
(b'ok', path.encode('utf-8'), rich_root, tree_ref, external_lookup, name))
414
('ok', path, rich_root, tree_ref, external_lookup, name))
416
415
except errors.NoRepositoryPresent:
417
return FailedSmartServerResponse((b'norepository', ))
416
return FailedSmartServerResponse(('norepository', ))
420
419
class SmartServerBzrDirRequestConfigFile(SmartServerRequestBzrDir):
422
421
def do_bzrdir_request(self):
423
422
"""Get the configuration bytes for a config file in bzrdir.
425
424
The body is not utf8 decoded - it is the literal bytestream from disk.
427
426
config = self._bzrdir._get_config()
428
427
if config is None:
431
430
content = config._get_config_file().read()
432
431
return SuccessfulSmartServerResponse((), content)
437
436
def do_bzrdir_request(self):
438
437
"""Get the branches in a control directory.
440
439
The body is a bencoded dictionary, with values similar to the return
441
440
value of the open branch request.
443
branch_names = self._bzrdir.branch_names()
442
branches = self._bzrdir.get_branches()
445
for name in branch_names:
444
for name, b in branches.iteritems():
448
branch_ref = self._bzrdir.get_branch_reference(name=name)
449
if branch_ref is not None:
450
branch_ref = urlutils.relative_url(self._bzrdir.user_url, branch_ref)
451
value = (b"ref", branch_ref.encode('utf-8'))
453
b = self._bzrdir.open_branch(name=name, ignore_fallbacks=True)
454
value = (b"branch", b._format.network_name())
455
ret[name.encode('utf-8')] = value
447
ret[name] = ("branch", b._format.network_name())
456
448
return SuccessfulSmartServerResponse(
457
(b"success", ), bencode.bencode(ret))
449
("success", ), bencode.bencode(ret))
460
452
class SmartServerRequestInitializeBzrDir(SmartServerRequest):
468
460
target_transport = self.transport_from_client_path(path)
469
461
BzrDirFormat.get_default_format().initialize_on_transport(target_transport)
470
return SuccessfulSmartServerResponse((b'ok', ))
462
return SuccessfulSmartServerResponse(('ok', ))
473
465
class SmartServerRequestBzrDirInitializeEx(SmartServerRequestBzrDir):
475
467
def parse_NoneTrueFalse(self, arg):
482
474
raise AssertionError("invalid arg %r" % arg)
484
def parse_NoneBytestring(self, arg):
476
def parse_NoneString(self, arg):
485
477
return arg or None
487
def parse_NoneString(self, arg):
490
return arg.decode('utf-8')
492
479
def _serialize_NoneTrueFalse(self, arg):
499
486
def do(self, bzrdir_network_name, path, use_existing_dir, create_prefix,
500
force_new_repo, stacked_on, stack_on_pwd, repo_format_name,
501
make_working_trees, shared_repo):
487
force_new_repo, stacked_on, stack_on_pwd, repo_format_name,
488
make_working_trees, shared_repo):
502
489
"""Initialize a bzrdir at path as per
503
490
BzrDirFormat.initialize_on_transport_ex.
519
506
stack_on_pwd = self.parse_NoneString(stack_on_pwd)
520
507
make_working_trees = self.parse_NoneTrueFalse(make_working_trees)
521
508
shared_repo = self.parse_NoneTrueFalse(shared_repo)
522
if stack_on_pwd == b'.':
523
stack_on_pwd = target_transport.base.encode('utf-8')
524
repo_format_name = self.parse_NoneBytestring(repo_format_name)
509
if stack_on_pwd == '.':
510
stack_on_pwd = target_transport.base
511
repo_format_name = self.parse_NoneString(repo_format_name)
525
512
repo, bzrdir, stacking, repository_policy = \
526
513
format.initialize_on_transport_ex(target_transport,
527
use_existing_dir=use_existing_dir, create_prefix=create_prefix,
528
force_new_repo=force_new_repo, stacked_on=stacked_on,
529
stack_on_pwd=stack_on_pwd, repo_format_name=repo_format_name,
530
make_working_trees=make_working_trees, shared_repo=shared_repo)
514
use_existing_dir=use_existing_dir, create_prefix=create_prefix,
515
force_new_repo=force_new_repo, stacked_on=stacked_on,
516
stack_on_pwd=stack_on_pwd, repo_format_name=repo_format_name,
517
make_working_trees=make_working_trees, shared_repo=shared_repo)
534
rich_root = tree_ref = external_lookup = b''
535
repo_bzrdir_name = b''
521
rich_root = tree_ref = external_lookup = ''
522
repo_bzrdir_name = ''
536
523
final_stack = None
537
524
final_stack_pwd = None
538
repo_lock_token = b''
540
527
repo_path = self._repo_relpath(bzrdir.root_transport, repo)
541
528
if repo_path == '':
543
530
rich_root, tree_ref, external_lookup = self._format_to_capabilities(
545
532
repo_name = repo._format.network_name()
546
repo_bzrdir_name = repo.controldir._format.network_name()
533
repo_bzrdir_name = repo.bzrdir._format.network_name()
547
534
final_stack = repository_policy._stack_on
548
535
final_stack_pwd = repository_policy._stack_on_pwd
549
536
# It is returned locked, but we need to do the lock to get the lock
552
repo_lock_token = repo.lock_write().repository_token or b''
539
repo_lock_token = repo.lock_write().repository_token or ''
553
540
if repo_lock_token:
554
541
repo.leave_lock_in_place()
568
555
self._root_client_path, client_path)
569
556
final_stack_pwd = '.'
571
return SuccessfulSmartServerResponse((repo_path.encode('utf-8'),
572
rich_root, tree_ref, external_lookup, repo_name, repo_bzrdir_name,
573
bzrdir._format.network_name(),
574
self._serialize_NoneTrueFalse(
575
stacking), final_stack.encode('utf-8'),
576
final_stack_pwd.encode('utf-8'), repo_lock_token))
558
return SuccessfulSmartServerResponse((repo_path, rich_root, tree_ref,
559
external_lookup, repo_name, repo_bzrdir_name,
560
bzrdir._format.network_name(),
561
self._serialize_NoneTrueFalse(stacking), final_stack,
562
final_stack_pwd, repo_lock_token))
579
565
class SmartServerRequestOpenBranch(SmartServerRequestBzrDir):
584
570
reference_url = self._bzrdir.get_branch_reference()
585
571
if reference_url is None:
587
return SuccessfulSmartServerResponse((b'ok', reference_url.encode('utf-8')))
588
except errors.NotBranchError as e:
589
return FailedSmartServerResponse((b'nobranch',))
572
return SuccessfulSmartServerResponse(('ok', ''))
574
return SuccessfulSmartServerResponse(('ok', reference_url))
575
except errors.NotBranchError, e:
576
return FailedSmartServerResponse(('nobranch',))
592
579
class SmartServerRequestOpenBranchV2(SmartServerRequestBzrDir):
598
585
if reference_url is None:
599
586
br = self._bzrdir.open_branch(ignore_fallbacks=True)
600
587
format = br._format.network_name()
601
return SuccessfulSmartServerResponse((b'branch', format))
588
return SuccessfulSmartServerResponse(('branch', format))
603
return SuccessfulSmartServerResponse((b'ref', reference_url.encode('utf-8')))
604
except errors.NotBranchError as e:
605
return FailedSmartServerResponse((b'nobranch',))
590
return SuccessfulSmartServerResponse(('ref', reference_url))
591
except errors.NotBranchError, e:
592
return FailedSmartServerResponse(('nobranch',))
608
595
class SmartServerRequestOpenBranchV3(SmartServerRequestBzrDir):
610
597
def do_bzrdir_request(self):
611
598
"""Open a branch at path and return the reference or format.
613
600
This version introduced in 2.1.
615
602
Differences to SmartServerRequestOpenBranchV2:
622
609
if reference_url is None:
623
610
br = self._bzrdir.open_branch(ignore_fallbacks=True)
624
611
format = br._format.network_name()
625
return SuccessfulSmartServerResponse((b'branch', format))
612
return SuccessfulSmartServerResponse(('branch', format))
627
return SuccessfulSmartServerResponse((b'ref', reference_url.encode('utf-8')))
628
except errors.NotBranchError as e:
614
return SuccessfulSmartServerResponse(('ref', reference_url))
615
except errors.NotBranchError, e:
629
616
# Stringify the exception so that its .detail attribute will be
632
resp = (b'nobranch',)
633
620
detail = e.detail
635
622
if detail.startswith(': '):
636
623
detail = detail[2:]
637
resp += (detail.encode('utf-8'),)
638
625
return FailedSmartServerResponse(resp)