109
def _format_to_capabilities(self, repo_format):
110
rich_root = self._boolean_to_yes_no(repo_format.rich_root_data)
111
tree_ref = self._boolean_to_yes_no(
112
repo_format.supports_tree_reference)
113
external_lookup = self._boolean_to_yes_no(
114
repo_format.supports_external_lookups)
115
return rich_root, tree_ref, external_lookup
117
def _repo_relpath(self, current_transport, repository):
118
"""Get the relative path for repository from current_transport."""
119
# the relpath of the bzrdir in the found repository gives us the
120
# path segments to pop-out.
121
relpath = repository.user_transport.relpath(
122
current_transport.base)
124
segments = ['..'] * len(relpath.split('/'))
127
return '/'.join(segments)
130
class SmartServerBzrDirRequestDestroyBranch(SmartServerRequestBzrDir):
132
def do_bzrdir_request(self, name=None):
133
"""Destroy the branch with the specified name.
136
:return: On success, 'ok'.
139
self._bzrdir.destroy_branch(name)
140
except errors.NotBranchError, e:
141
return FailedSmartServerResponse(('nobranch',))
142
return SuccessfulSmartServerResponse(('ok',))
145
class SmartServerBzrDirRequestHasWorkingTree(SmartServerRequestBzrDir):
147
def do_bzrdir_request(self, name=None):
148
"""Check whether there is a working tree present.
152
:return: If there is a working tree present, 'yes'.
155
if self._bzrdir.has_workingtree():
156
return SuccessfulSmartServerResponse(('yes', ))
158
return SuccessfulSmartServerResponse(('no', ))
161
class SmartServerBzrDirRequestDestroyRepository(SmartServerRequestBzrDir):
163
def do_bzrdir_request(self, name=None):
164
"""Destroy the repository.
168
:return: On success, 'ok'.
171
self._bzrdir.destroy_repository()
172
except errors.NoRepositoryPresent, e:
173
return FailedSmartServerResponse(('norepository',))
174
return SuccessfulSmartServerResponse(('ok',))
177
class SmartServerBzrDirRequestCloningMetaDir(SmartServerRequestBzrDir):
179
def do_bzrdir_request(self, require_stacking):
180
"""Get the format that should be used when cloning from this dir.
184
:return: on success, a 3-tuple of network names for (control,
185
repository, branch) directories, where '' signifies "not present".
186
If this BzrDir contains a branch reference then this will fail with
187
BranchReference; clients should resolve branch references before
191
branch_ref = self._bzrdir.get_branch_reference()
192
except errors.NotBranchError:
194
if branch_ref is not None:
195
# The server shouldn't try to resolve references, and it quite
196
# possibly can't reach them anyway. The client needs to resolve
197
# the branch reference to determine the cloning_metadir.
198
return FailedSmartServerResponse(('BranchReference',))
199
if require_stacking == "True":
200
require_stacking = True
202
require_stacking = False
203
control_format = self._bzrdir.cloning_metadir(
204
require_stacking=require_stacking)
205
control_name = control_format.network_name()
206
if not control_format.fixed_components:
207
branch_name = ('branch',
208
control_format.get_branch_format().network_name())
209
repository_name = control_format.repository_format.network_name()
211
# Only MetaDir has delegated formats today.
212
branch_name = ('branch', '')
214
return SuccessfulSmartServerResponse((control_name, repository_name,
218
class SmartServerBzrDirRequestCheckoutMetaDir(SmartServerRequestBzrDir):
219
"""Get the format to use for checkouts.
223
:return: on success, a 3-tuple of network names for (control,
224
repository, branch) directories, where '' signifies "not present".
225
If this BzrDir contains a branch reference then this will fail with
226
BranchReference; clients should resolve branch references before
227
calling this RPC (they should not try to create a checkout of a
231
def do_bzrdir_request(self):
233
branch_ref = self._bzrdir.get_branch_reference()
234
except errors.NotBranchError:
236
if branch_ref is not None:
237
# The server shouldn't try to resolve references, and it quite
238
# possibly can't reach them anyway. The client needs to resolve
239
# the branch reference to determine the cloning_metadir.
240
return FailedSmartServerResponse(('BranchReference',))
241
control_format = self._bzrdir.checkout_metadir()
242
control_name = control_format.network_name()
243
if not control_format.fixed_components:
244
branch_name = control_format.get_branch_format().network_name()
245
repo_name = control_format.repository_format.network_name()
249
return SuccessfulSmartServerResponse(
250
(control_name, repo_name, branch_name))
253
class SmartServerRequestCreateBranch(SmartServerRequestBzrDir):
255
def do(self, path, network_name):
256
"""Create a branch in the bzr dir at path.
258
This operates precisely like 'bzrdir.create_branch'.
260
If a bzrdir is not present, an exception is propogated
261
rather than 'no branch' because these are different conditions (and
262
this method should only be called after establishing that a bzr dir
265
This is the initial version of this method introduced to the smart
268
:param path: The path to the bzrdir.
269
:param network_name: The network name of the branch type to create.
270
:return: ('ok', branch_format, repo_path, rich_root, tree_ref,
271
external_lookup, repo_format)
273
bzrdir = BzrDir.open_from_transport(
274
self.transport_from_client_path(path))
275
format = branch.network_format_registry.get(network_name)
276
bzrdir.branch_format = format
277
result = format.initialize(bzrdir, name="")
278
rich_root, tree_ref, external_lookup = self._format_to_capabilities(
279
result.repository._format)
280
branch_format = result._format.network_name()
281
repo_format = result.repository._format.network_name()
282
repo_path = self._repo_relpath(bzrdir.root_transport,
284
# branch format, repo relpath, rich_root, tree_ref, external_lookup,
286
return SuccessfulSmartServerResponse(('ok', branch_format, repo_path,
287
rich_root, tree_ref, external_lookup, repo_format))
290
class SmartServerRequestCreateRepository(SmartServerRequestBzrDir):
292
def do(self, path, network_name, shared):
293
"""Create a repository in the bzr dir at path.
295
This operates precisely like 'bzrdir.create_repository'.
297
If a bzrdir is not present, an exception is propagated
298
rather than 'no branch' because these are different conditions (and
299
this method should only be called after establishing that a bzr dir
302
This is the initial version of this method introduced to the smart
305
:param path: The path to the bzrdir.
306
:param network_name: The network name of the repository type to create.
307
:param shared: The value to pass create_repository for the shared
309
:return: (ok, rich_root, tree_ref, external_lookup, network_name)
311
bzrdir = BzrDir.open_from_transport(
312
self.transport_from_client_path(path))
313
shared = shared == 'True'
314
format = repository.network_format_registry.get(network_name)
315
bzrdir.repository_format = format
316
result = format.initialize(bzrdir, shared=shared)
317
rich_root, tree_ref, external_lookup = self._format_to_capabilities(
319
return SuccessfulSmartServerResponse(('ok', rich_root, tree_ref,
320
external_lookup, result._format.network_name()))
323
class SmartServerRequestFindRepository(SmartServerRequestBzrDir):
62
325
def _find(self, path):
63
326
"""try to find a repository from path upwards
65
328
This operates precisely like 'bzrdir.find_repository'.
67
:return: (relpath, rich_root, tree_ref, external_lookup) flags. All are
68
strings, relpath is a / prefixed path, and the other three are
330
:return: (relpath, rich_root, tree_ref, external_lookup, network_name).
331
All are strings, relpath is a / prefixed path, the next three are
332
either 'yes' or 'no', and the last is a repository format network
70
334
:raises errors.NoRepositoryPresent: When there is no repository
73
337
bzrdir = BzrDir.open_from_transport(
74
338
self.transport_from_client_path(path))
75
339
repository = bzrdir.find_repository()
76
# the relpath of the bzrdir in the found repository gives us the
77
# path segments to pop-out.
78
relpath = repository.bzrdir.root_transport.relpath(
79
bzrdir.root_transport.base)
81
segments = ['..'] * len(relpath.split('/'))
84
rich_root = self._boolean_to_yes_no(repository.supports_rich_root())
85
tree_ref = self._boolean_to_yes_no(
86
repository._format.supports_tree_reference)
87
external_lookup = self._boolean_to_yes_no(
88
repository._format.supports_external_lookups)
89
return '/'.join(segments), rich_root, tree_ref, external_lookup
340
path = self._repo_relpath(bzrdir.root_transport, repository)
341
rich_root, tree_ref, external_lookup = self._format_to_capabilities(
343
network_name = repository._format.network_name()
344
return path, rich_root, tree_ref, external_lookup, network_name
92
347
class SmartServerRequestFindRepositoryV1(SmartServerRequestFindRepository):
94
349
def do(self, path):
95
350
"""try to find a repository from path upwards
97
352
This operates precisely like 'bzrdir.find_repository'.
99
If a bzrdir is not present, an exception is propogated
354
If a bzrdir is not present, an exception is propagated
100
355
rather than 'no branch' because these are different conditions.
102
357
This is the initial version of this method introduced with the smart
117
372
def do(self, path):
118
373
"""try to find a repository from path upwards
120
375
This operates precisely like 'bzrdir.find_repository'.
122
If a bzrdir is not present, an exception is propogated
377
If a bzrdir is not present, an exception is propagated
123
378
rather than 'no branch' because these are different conditions.
125
380
This is the second edition of this method introduced in bzr 1.3, which
126
381
returns information about the supports_external_lookups format
129
:return: norepository or ok, relpath.
384
:return: norepository or ok, relpath, rich_root, tree_ref,
132
path, rich_root, tree_ref, external_lookup = self._find(path)
388
path, rich_root, tree_ref, external_lookup, name = self._find(path)
133
389
return SuccessfulSmartServerResponse(
134
390
('ok', path, rich_root, tree_ref, external_lookup))
135
391
except errors.NoRepositoryPresent:
136
392
return FailedSmartServerResponse(('norepository', ))
395
class SmartServerRequestFindRepositoryV3(SmartServerRequestFindRepository):
398
"""try to find a repository from path upwards
400
This operates precisely like 'bzrdir.find_repository'.
402
If a bzrdir is not present, an exception is propogated
403
rather than 'no branch' because these are different conditions.
405
This is the third edition of this method introduced in bzr 1.13, which
406
returns information about the network name of the repository format.
408
:return: norepository or ok, relpath, rich_root, tree_ref,
409
external_lookup, network_name.
412
path, rich_root, tree_ref, external_lookup, name = self._find(path)
413
return SuccessfulSmartServerResponse(
414
('ok', path, rich_root, tree_ref, external_lookup, name))
415
except errors.NoRepositoryPresent:
416
return FailedSmartServerResponse(('norepository', ))
419
class SmartServerBzrDirRequestConfigFile(SmartServerRequestBzrDir):
421
def do_bzrdir_request(self):
422
"""Get the configuration bytes for a config file in bzrdir.
424
The body is not utf8 decoded - it is the literal bytestream from disk.
426
config = self._bzrdir._get_config()
430
content = config._get_config_file().read()
431
return SuccessfulSmartServerResponse((), content)
434
class SmartServerBzrDirRequestGetBranches(SmartServerRequestBzrDir):
436
def do_bzrdir_request(self):
437
"""Get the branches in a control directory.
439
The body is a bencoded dictionary, with values similar to the return
440
value of the open branch request.
442
branches = self._bzrdir.get_branches()
444
for name, b in branches.iteritems():
447
ret[name] = ("branch", b._format.network_name())
448
return SuccessfulSmartServerResponse(
449
("success", ), bencode.bencode(ret))
139
452
class SmartServerRequestInitializeBzrDir(SmartServerRequest):
141
454
def do(self, path):
149
462
return SuccessfulSmartServerResponse(('ok', ))
152
class SmartServerRequestOpenBranch(SmartServerRequest):
155
"""try to open a branch at path and return ok/nobranch.
157
If a bzrdir is not present, an exception is propogated
158
rather than 'no branch' because these are different conditions.
465
class SmartServerRequestBzrDirInitializeEx(SmartServerRequestBzrDir):
467
def parse_NoneTrueFalse(self, arg):
474
raise AssertionError("invalid arg %r" % arg)
476
def parse_NoneString(self, arg):
479
def _serialize_NoneTrueFalse(self, arg):
486
def do(self, bzrdir_network_name, path, use_existing_dir, create_prefix,
487
force_new_repo, stacked_on, stack_on_pwd, repo_format_name,
488
make_working_trees, shared_repo):
489
"""Initialize a bzrdir at path as per
490
BzrDirFormat.initialize_on_transport_ex.
492
New in 1.16. (Replaces BzrDirFormat.initialize_ex verb from 1.15).
494
:return: return SuccessfulSmartServerResponse((repo_path, rich_root,
495
tree_ref, external_lookup, repo_network_name,
496
repo_bzrdir_network_name, bzrdir_format_network_name,
497
NoneTrueFalse(stacking), final_stack, final_stack_pwd,
160
bzrdir = BzrDir.open_from_transport(
161
self.transport_from_client_path(path))
500
target_transport = self.transport_from_client_path(path)
501
format = network_format_registry.get(bzrdir_network_name)
502
use_existing_dir = self.parse_NoneTrueFalse(use_existing_dir)
503
create_prefix = self.parse_NoneTrueFalse(create_prefix)
504
force_new_repo = self.parse_NoneTrueFalse(force_new_repo)
505
stacked_on = self.parse_NoneString(stacked_on)
506
stack_on_pwd = self.parse_NoneString(stack_on_pwd)
507
make_working_trees = self.parse_NoneTrueFalse(make_working_trees)
508
shared_repo = self.parse_NoneTrueFalse(shared_repo)
509
if stack_on_pwd == '.':
510
stack_on_pwd = target_transport.base
511
repo_format_name = self.parse_NoneString(repo_format_name)
512
repo, bzrdir, stacking, repository_policy = \
513
format.initialize_on_transport_ex(target_transport,
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)
521
rich_root = tree_ref = external_lookup = ''
522
repo_bzrdir_name = ''
524
final_stack_pwd = None
527
repo_path = self._repo_relpath(bzrdir.root_transport, repo)
530
rich_root, tree_ref, external_lookup = self._format_to_capabilities(
532
repo_name = repo._format.network_name()
533
repo_bzrdir_name = repo.bzrdir._format.network_name()
534
final_stack = repository_policy._stack_on
535
final_stack_pwd = repository_policy._stack_on_pwd
536
# It is returned locked, but we need to do the lock to get the lock
539
repo_lock_token = repo.lock_write().repository_token or ''
541
repo.leave_lock_in_place()
543
final_stack = final_stack or ''
544
final_stack_pwd = final_stack_pwd or ''
546
# We want this to be relative to the bzrdir.
548
final_stack_pwd = urlutils.relative_url(
549
target_transport.base, final_stack_pwd)
551
# Can't meaningfully return a root path.
552
if final_stack.startswith('/'):
553
client_path = self._root_client_path + final_stack[1:]
554
final_stack = urlutils.relative_url(
555
self._root_client_path, client_path)
556
final_stack_pwd = '.'
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))
565
class SmartServerRequestOpenBranch(SmartServerRequestBzrDir):
567
def do_bzrdir_request(self):
568
"""open a branch at path and return the branch reference or branch."""
163
reference_url = bzrdir.get_branch_reference()
570
reference_url = self._bzrdir.get_branch_reference()
164
571
if reference_url is None:
165
572
return SuccessfulSmartServerResponse(('ok', ''))
167
574
return SuccessfulSmartServerResponse(('ok', reference_url))
168
except errors.NotBranchError:
169
return FailedSmartServerResponse(('nobranch', ))
575
except errors.NotBranchError, e:
576
return FailedSmartServerResponse(('nobranch',))
579
class SmartServerRequestOpenBranchV2(SmartServerRequestBzrDir):
581
def do_bzrdir_request(self):
582
"""open a branch at path and return the reference or format."""
584
reference_url = self._bzrdir.get_branch_reference()
585
if reference_url is None:
586
br = self._bzrdir.open_branch(ignore_fallbacks=True)
587
format = br._format.network_name()
588
return SuccessfulSmartServerResponse(('branch', format))
590
return SuccessfulSmartServerResponse(('ref', reference_url))
591
except errors.NotBranchError, e:
592
return FailedSmartServerResponse(('nobranch',))
595
class SmartServerRequestOpenBranchV3(SmartServerRequestBzrDir):
597
def do_bzrdir_request(self):
598
"""Open a branch at path and return the reference or format.
600
This version introduced in 2.1.
602
Differences to SmartServerRequestOpenBranchV2:
603
* can return 2-element ('nobranch', extra), where 'extra' is a string
604
with an explanation like 'location is a repository'. Previously
605
a 'nobranch' response would never have more than one element.
608
reference_url = self._bzrdir.get_branch_reference()
609
if reference_url is None:
610
br = self._bzrdir.open_branch(ignore_fallbacks=True)
611
format = br._format.network_name()
612
return SuccessfulSmartServerResponse(('branch', format))
614
return SuccessfulSmartServerResponse(('ref', reference_url))
615
except errors.NotBranchError, e:
616
# Stringify the exception so that its .detail attribute will be
622
if detail.startswith(': '):
625
return FailedSmartServerResponse(resp)