1
# Copyright (C) 2006 Canonical Ltd
1
# Copyright (C) 2006-2010 Canonical Ltd
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
17
17
"""Server-side bzrdir related request implmentations."""
19
from __future__ import absolute_import
20
21
from bzrlib import branch, errors, repository, urlutils
21
22
from bzrlib.bzrdir import (
27
from bzrlib.controldir import (
25
28
network_format_registry,
27
30
from bzrlib.smart.request import (
44
47
# clients that don't anticipate errors from this method.
47
default_format = BzrDirFormat.get_default_format()
48
real_bzrdir = default_format.open(t, _found=True)
50
bzr_prober = BzrProber()
50
real_bzrdir._format.probe_transport(t)
52
bzr_prober.probe_transport(t)
51
53
except (errors.NotBranchError, errors.UnknownFormatError):
84
86
class SmartServerRequestBzrDir(SmartServerRequest):
86
88
def do(self, path, *args):
87
"""Open a BzrDir at path, and return self.do_bzrdir_request(*args)."""
89
"""Open a BzrDir at path, and return `self.do_bzrdir_request(*args)`."""
89
91
self._bzrdir = BzrDir.open_from_transport(
90
92
self.transport_from_client_path(path))
91
except errors.NotBranchError:
92
return FailedSmartServerResponse(('nobranch', ))
93
except errors.NotBranchError, e:
94
return FailedSmartServerResponse(('nobranch',))
93
95
return self.do_bzrdir_request(*args)
95
97
def _boolean_to_yes_no(self, a_boolean):
110
112
"""Get the relative path for repository from current_transport."""
111
113
# the relpath of the bzrdir in the found repository gives us the
112
114
# path segments to pop-out.
113
relpath = repository.bzrdir.root_transport.relpath(
115
relpath = repository.user_transport.relpath(
114
116
current_transport.base)
116
118
segments = ['..'] * len(relpath.split('/'))
119
121
return '/'.join(segments)
124
class SmartServerBzrDirRequestDestroyBranch(SmartServerRequestBzrDir):
126
def do_bzrdir_request(self, name=None):
127
"""Destroy the branch with the specified name.
130
:return: On success, 'ok'.
133
self._bzrdir.destroy_branch(name)
134
except errors.NotBranchError, e:
135
return FailedSmartServerResponse(('nobranch',))
136
return SuccessfulSmartServerResponse(('ok',))
139
class SmartServerBzrDirRequestHasWorkingTree(SmartServerRequestBzrDir):
141
def do_bzrdir_request(self, name=None):
142
"""Check whether there is a working tree present.
146
:return: If there is a working tree present, 'yes'.
149
if self._bzrdir.has_workingtree():
150
return SuccessfulSmartServerResponse(('yes', ))
152
return SuccessfulSmartServerResponse(('no', ))
155
class SmartServerBzrDirRequestDestroyRepository(SmartServerRequestBzrDir):
157
def do_bzrdir_request(self, name=None):
158
"""Destroy the repository.
162
:return: On success, 'ok'.
165
self._bzrdir.destroy_repository()
166
except errors.NoRepositoryPresent, e:
167
return FailedSmartServerResponse(('norepository',))
168
return SuccessfulSmartServerResponse(('ok',))
122
171
class SmartServerBzrDirRequestCloningMetaDir(SmartServerRequestBzrDir):
124
173
def do_bzrdir_request(self, require_stacking):
148
197
control_format = self._bzrdir.cloning_metadir(
149
198
require_stacking=require_stacking)
150
199
control_name = control_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):
200
if not control_format.fixed_components:
154
201
branch_name = ('branch',
155
202
control_format.get_branch_format().network_name())
156
203
repository_name = control_format.repository_format.network_name()
212
class SmartServerBzrDirRequestCheckoutMetaDir(SmartServerRequestBzrDir):
213
"""Get the format to use for checkouts.
217
:return: on success, a 3-tuple of network names for (control,
218
repository, branch) directories, where '' signifies "not present".
219
If this BzrDir contains a branch reference then this will fail with
220
BranchReference; clients should resolve branch references before
221
calling this RPC (they should not try to create a checkout of a
225
def do_bzrdir_request(self):
227
branch_ref = self._bzrdir.get_branch_reference()
228
except errors.NotBranchError:
230
if branch_ref is not None:
231
# The server shouldn't try to resolve references, and it quite
232
# possibly can't reach them anyway. The client needs to resolve
233
# the branch reference to determine the cloning_metadir.
234
return FailedSmartServerResponse(('BranchReference',))
235
control_format = self._bzrdir.checkout_metadir()
236
control_name = control_format.network_name()
237
if not control_format.fixed_components:
238
branch_name = control_format.get_branch_format().network_name()
239
repo_name = control_format.repository_format.network_name()
243
return SuccessfulSmartServerResponse(
244
(control_name, repo_name, branch_name))
165
247
class SmartServerRequestCreateBranch(SmartServerRequestBzrDir):
167
249
def do(self, path, network_name):
180
262
:param path: The path to the bzrdir.
181
263
:param network_name: The network name of the branch type to create.
182
:return: (ok, network_name)
264
:return: ('ok', branch_format, repo_path, rich_root, tree_ref,
265
external_lookup, repo_format)
184
267
bzrdir = BzrDir.open_from_transport(
185
268
self.transport_from_client_path(path))
429
512
# It is returned locked, but we need to do the lock to get the lock
432
repo_lock_token = repo.lock_write() or ''
515
repo_lock_token = repo.lock_write().repository_token or ''
433
516
if repo_lock_token:
434
517
repo.leave_lock_in_place()
465
548
return SuccessfulSmartServerResponse(('ok', ''))
467
550
return SuccessfulSmartServerResponse(('ok', reference_url))
468
except errors.NotBranchError:
469
return FailedSmartServerResponse(('nobranch', ))
551
except errors.NotBranchError, e:
552
return FailedSmartServerResponse(('nobranch',))
472
555
class SmartServerRequestOpenBranchV2(SmartServerRequestBzrDir):
481
564
return SuccessfulSmartServerResponse(('branch', format))
483
566
return SuccessfulSmartServerResponse(('ref', reference_url))
484
except errors.NotBranchError:
485
return FailedSmartServerResponse(('nobranch', ))
567
except errors.NotBranchError, e:
568
return FailedSmartServerResponse(('nobranch',))
571
class SmartServerRequestOpenBranchV3(SmartServerRequestBzrDir):
573
def do_bzrdir_request(self):
574
"""Open a branch at path and return the reference or format.
576
This version introduced in 2.1.
578
Differences to SmartServerRequestOpenBranchV2:
579
* can return 2-element ('nobranch', extra), where 'extra' is a string
580
with an explanation like 'location is a repository'. Previously
581
a 'nobranch' response would never have more than one element.
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
# Stringify the exception so that its .detail attribute will be
598
if detail.startswith(': '):
601
return FailedSmartServerResponse(resp)