1
# Copyright (C) 2006 Canonical Ltd
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
# GNU General Public License for more details.
13
# You should have received a copy of the GNU General Public License
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
17
"""Server-side bzrdir related request implmentations."""
20
from bzrlib import errors
21
from bzrlib.bzrdir import BzrDir, BzrDirFormat
22
from bzrlib.smart.request import (
23
FailedSmartServerResponse,
25
SuccessfulSmartServerResponse,
27
from bzrlib.repository import network_format_registry
30
class SmartServerRequestOpenBzrDir(SmartServerRequest):
33
from bzrlib.bzrdir import BzrDirFormat
35
t = self.transport_from_client_path(path)
36
except errors.PathNotChild:
37
# The client is trying to ask about a path that they have no access
39
# Ideally we'd return a FailedSmartServerResponse here rather than
40
# a "successful" negative, but we want to be compatibile with
41
# clients that don't anticipate errors from this method.
44
default_format = BzrDirFormat.get_default_format()
45
real_bzrdir = default_format.open(t, _found=True)
47
real_bzrdir._format.probe_transport(t)
48
except (errors.NotBranchError, errors.UnknownFormatError):
52
return SuccessfulSmartServerResponse((answer,))
55
class SmartServerRequestBzrDir(SmartServerRequest):
57
def _boolean_to_yes_no(self, a_boolean):
63
def _format_to_capabilities(self, repo_format):
64
rich_root = self._boolean_to_yes_no(repo_format.rich_root_data)
65
tree_ref = self._boolean_to_yes_no(
66
repo_format.supports_tree_reference)
67
external_lookup = self._boolean_to_yes_no(
68
repo_format.supports_external_lookups)
69
return rich_root, tree_ref, external_lookup
72
class SmartServerRequestCreateRepository(SmartServerRequestBzrDir):
74
def do(self, path, network_name, shared):
75
"""Create a repository in the bzr dir at path.
77
This operates precisely like 'bzrdir.create_repository'.
79
If a bzrdir is not present, an exception is propogated
80
rather than 'no branch' because these are different conditions (and
81
this method should only be called after establishing that a bzr dir
84
This is the initial version of this method introduced to the smart
87
:param path: The path to the bzrdir.
88
:param network_name: The network name of the repository type to create.
89
:param shared: The value to pass create_repository for the shared
91
:return: (ok, rich_root, tree_ref, external_lookup, network_name)
93
bzrdir = BzrDir.open_from_transport(
94
self.transport_from_client_path(path))
95
shared = shared == 'True'
96
format = network_format_registry.get(network_name)
97
bzrdir.repository_format = format
98
result = format.initialize(bzrdir, shared=shared)
99
rich_root, tree_ref, external_lookup = self._format_to_capabilities(
101
return SuccessfulSmartServerResponse(('ok', rich_root, tree_ref,
102
external_lookup, result._format.network_name()))
105
class SmartServerRequestFindRepository(SmartServerRequestBzrDir):
107
def _find(self, path):
108
"""try to find a repository from path upwards
110
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'.
115
:raises errors.NoRepositoryPresent: When there is no repository
118
bzrdir = BzrDir.open_from_transport(
119
self.transport_from_client_path(path))
120
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('/'))
129
rich_root, tree_ref, external_lookup = self._format_to_capabilities(
131
return '/'.join(segments), rich_root, tree_ref, external_lookup
134
class SmartServerRequestFindRepositoryV1(SmartServerRequestFindRepository):
137
"""try to find a repository from path upwards
139
This operates precisely like 'bzrdir.find_repository'.
141
If a bzrdir is not present, an exception is propogated
142
rather than 'no branch' because these are different conditions.
144
This is the initial version of this method introduced with the smart
145
server. Modern clients will try the V2 method that adds support for the
146
supports_external_lookups attribute.
148
:return: norepository or ok, relpath.
151
path, rich_root, tree_ref, external_lookup = self._find(path)
152
return SuccessfulSmartServerResponse(('ok', path, rich_root, tree_ref))
153
except errors.NoRepositoryPresent:
154
return FailedSmartServerResponse(('norepository', ))
157
class SmartServerRequestFindRepositoryV2(SmartServerRequestFindRepository):
160
"""try to find a repository from path upwards
162
This operates precisely like 'bzrdir.find_repository'.
164
If a bzrdir is not present, an exception is propogated
165
rather than 'no branch' because these are different conditions.
167
This is the second edition of this method introduced in bzr 1.3, which
168
returns information about the supports_external_lookups format
171
:return: norepository or ok, relpath.
174
path, rich_root, tree_ref, external_lookup = self._find(path)
175
return SuccessfulSmartServerResponse(
176
('ok', path, rich_root, tree_ref, external_lookup))
177
except errors.NoRepositoryPresent:
178
return FailedSmartServerResponse(('norepository', ))
181
class SmartServerRequestInitializeBzrDir(SmartServerRequest):
184
"""Initialize a bzrdir at path.
186
The default format of the server is used.
187
:return: SmartServerResponse(('ok', ))
189
target_transport = self.transport_from_client_path(path)
190
BzrDirFormat.get_default_format().initialize_on_transport(target_transport)
191
return SuccessfulSmartServerResponse(('ok', ))
194
class SmartServerRequestOpenBranch(SmartServerRequest):
197
"""try to open a branch at path and return ok/nobranch.
199
If a bzrdir is not present, an exception is propogated
200
rather than 'no branch' because these are different conditions.
202
bzrdir = BzrDir.open_from_transport(
203
self.transport_from_client_path(path))
205
reference_url = bzrdir.get_branch_reference()
206
if reference_url is None:
207
return SuccessfulSmartServerResponse(('ok', ''))
209
return SuccessfulSmartServerResponse(('ok', reference_url))
210
except errors.NotBranchError:
211
return FailedSmartServerResponse(('nobranch', ))