13
13
# You should have received a copy of the GNU General Public License
14
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17
17
"""Server-side bzrdir related request implmentations."""
20
from bzrlib import errors
21
from bzrlib.bzrdir import BzrDir, BzrDirFormat
20
from bzrlib import branch, errors, repository
21
from bzrlib.bzrdir import BzrDir, BzrDirFormat, BzrDirMetaFormat1
22
22
from bzrlib.smart.request import (
23
23
FailedSmartServerResponse,
24
24
SmartServerRequest,
25
25
SuccessfulSmartServerResponse,
27
from bzrlib.repository import network_format_registry
30
29
class SmartServerRequestOpenBzrDir(SmartServerRequest):
68
76
repo_format.supports_external_lookups)
69
77
return rich_root, tree_ref, external_lookup
79
def _repo_relpath(self, current_transport, repository):
80
"""Get the relative path for repository from current_transport."""
81
# the relpath of the bzrdir in the found repository gives us the
82
# path segments to pop-out.
83
relpath = repository.bzrdir.root_transport.relpath(
84
current_transport.base)
86
segments = ['..'] * len(relpath.split('/'))
89
return '/'.join(segments)
92
class SmartServerBzrDirRequestCloningMetaDir(SmartServerRequestBzrDir):
94
def do_bzrdir_request(self, require_stacking):
95
"""Get the format that should be used when cloning from this dir.
99
:return: on success, a 3-tuple of network names for (control,
100
repository, branch) directories, where '' signifies "not present".
101
If this BzrDir contains a branch reference then this will fail with
102
BranchReference; clients should resolve branch references before
106
branch_ref = self._bzrdir.get_branch_reference()
107
except errors.NotBranchError:
109
if branch_ref is not None:
110
# The server shouldn't try to resolve references, and it quite
111
# possibly can't reach them anyway. The client needs to resolve
112
# the branch reference to determine the cloning_metadir.
113
return FailedSmartServerResponse(('BranchReference',))
114
if require_stacking == "True":
115
require_stacking = True
117
require_stacking = False
118
control_format = self._bzrdir.cloning_metadir(
119
require_stacking=require_stacking)
120
control_name = control_format.network_name()
121
# XXX: There should be a method that tells us that the format does/does
122
# not have subformats.
123
if isinstance(control_format, BzrDirMetaFormat1):
124
branch_name = ('branch',
125
control_format.get_branch_format().network_name())
126
repository_name = control_format.repository_format.network_name()
128
# Only MetaDir has delegated formats today.
129
branch_name = ('branch', '')
131
return SuccessfulSmartServerResponse((control_name, repository_name,
135
class SmartServerRequestCreateBranch(SmartServerRequestBzrDir):
137
def do(self, path, network_name):
138
"""Create a branch in the bzr dir at path.
140
This operates precisely like 'bzrdir.create_branch'.
142
If a bzrdir is not present, an exception is propogated
143
rather than 'no branch' because these are different conditions (and
144
this method should only be called after establishing that a bzr dir
147
This is the initial version of this method introduced to the smart
150
:param path: The path to the bzrdir.
151
:param network_name: The network name of the branch type to create.
152
:return: (ok, network_name)
154
bzrdir = BzrDir.open_from_transport(
155
self.transport_from_client_path(path))
156
format = branch.network_format_registry.get(network_name)
157
bzrdir.branch_format = format
158
result = format.initialize(bzrdir)
159
rich_root, tree_ref, external_lookup = self._format_to_capabilities(
160
result.repository._format)
161
branch_format = result._format.network_name()
162
repo_format = result.repository._format.network_name()
163
repo_path = self._repo_relpath(bzrdir.root_transport,
165
# branch format, repo relpath, rich_root, tree_ref, external_lookup,
167
return SuccessfulSmartServerResponse(('ok', branch_format, repo_path,
168
rich_root, tree_ref, external_lookup, repo_format))
72
171
class SmartServerRequestCreateRepository(SmartServerRequestBzrDir):
74
173
def do(self, path, network_name, shared):
75
174
"""Create a repository in the bzr dir at path.
77
176
This operates precisely like 'bzrdir.create_repository'.
79
178
If a bzrdir is not present, an exception is propagated
80
179
rather than 'no branch' because these are different conditions (and
81
180
this method should only be called after establishing that a bzr dir
107
206
def _find(self, path):
108
207
"""try to find a repository from path upwards
110
209
This operates precisely like 'bzrdir.find_repository'.
112
:return: (relpath, rich_root, tree_ref, external_lookup) flags. All are
113
strings, relpath is a / prefixed path, and the other three are
114
either 'yes' or 'no'.
211
:return: (relpath, rich_root, tree_ref, external_lookup, network_name).
212
All are strings, relpath is a / prefixed path, the next three are
213
either 'yes' or 'no', and the last is a repository format network
115
215
:raises errors.NoRepositoryPresent: When there is no repository
118
218
bzrdir = BzrDir.open_from_transport(
119
219
self.transport_from_client_path(path))
120
220
repository = bzrdir.find_repository()
121
# the relpath of the bzrdir in the found repository gives us the
122
# path segments to pop-out.
123
relpath = repository.bzrdir.root_transport.relpath(
124
bzrdir.root_transport.base)
126
segments = ['..'] * len(relpath.split('/'))
221
path = self._repo_relpath(bzrdir.root_transport, repository)
129
222
rich_root, tree_ref, external_lookup = self._format_to_capabilities(
130
223
repository._format)
131
return '/'.join(segments), rich_root, tree_ref, external_lookup
224
network_name = repository._format.network_name()
225
return path, rich_root, tree_ref, external_lookup, network_name
134
228
class SmartServerRequestFindRepositoryV1(SmartServerRequestFindRepository):
136
230
def do(self, path):
137
231
"""try to find a repository from path upwards
139
233
This operates precisely like 'bzrdir.find_repository'.
141
235
If a bzrdir is not present, an exception is propagated
142
236
rather than 'no branch' because these are different conditions.
168
262
returns information about the supports_external_lookups format
171
:return: norepository or ok, relpath.
265
:return: norepository or ok, relpath, rich_root, tree_ref,
174
path, rich_root, tree_ref, external_lookup = self._find(path)
269
path, rich_root, tree_ref, external_lookup, name = self._find(path)
175
270
return SuccessfulSmartServerResponse(
176
271
('ok', path, rich_root, tree_ref, external_lookup))
177
272
except errors.NoRepositoryPresent:
178
273
return FailedSmartServerResponse(('norepository', ))
276
class SmartServerRequestFindRepositoryV3(SmartServerRequestFindRepository):
279
"""try to find a repository from path upwards
281
This operates precisely like 'bzrdir.find_repository'.
283
If a bzrdir is not present, an exception is propogated
284
rather than 'no branch' because these are different conditions.
286
This is the third edition of this method introduced in bzr 1.13, which
287
returns information about the network name of the repository format.
289
:return: norepository or ok, relpath, rich_root, tree_ref,
290
external_lookup, network_name.
293
path, rich_root, tree_ref, external_lookup, name = self._find(path)
294
return SuccessfulSmartServerResponse(
295
('ok', path, rich_root, tree_ref, external_lookup, name))
296
except errors.NoRepositoryPresent:
297
return FailedSmartServerResponse(('norepository', ))
181
300
class SmartServerRequestInitializeBzrDir(SmartServerRequest):
183
302
def do(self, path):
191
310
return SuccessfulSmartServerResponse(('ok', ))
194
class SmartServerRequestOpenBranch(SmartServerRequest):
313
class SmartServerRequestOpenBranch(SmartServerRequestBzrDir):
197
"""try to open a branch at path and return ok/nobranch.
199
If a bzrdir is not present, an exception is propagated
200
rather than 'no branch' because these are different conditions.
202
bzrdir = BzrDir.open_from_transport(
203
self.transport_from_client_path(path))
315
def do_bzrdir_request(self):
316
"""open a branch at path and return the branch reference or branch."""
205
reference_url = bzrdir.get_branch_reference()
318
reference_url = self._bzrdir.get_branch_reference()
206
319
if reference_url is None:
207
320
return SuccessfulSmartServerResponse(('ok', ''))
209
322
return SuccessfulSmartServerResponse(('ok', reference_url))
210
323
except errors.NotBranchError:
211
324
return FailedSmartServerResponse(('nobranch', ))
327
class SmartServerRequestOpenBranchV2(SmartServerRequestBzrDir):
329
def do_bzrdir_request(self):
330
"""open a branch at path and return the reference or format."""
332
reference_url = self._bzrdir.get_branch_reference()
333
if reference_url is None:
334
br = self._bzrdir.open_branch(ignore_fallbacks=True)
335
format = br._format.network_name()
336
return SuccessfulSmartServerResponse(('branch', format))
338
return SuccessfulSmartServerResponse(('ref', reference_url))
339
except errors.NotBranchError:
340
return FailedSmartServerResponse(('nobranch', ))