bzr branch
http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
| 2018.5.157
by Andrew Bennetts Remove unnecessary trivial divergences from bzr.dev. | 1 | # Copyright (C) 2006, 2007 Canonical Ltd
 | 
| 2018.5.4
by Andrew Bennetts Split smart server VFS logic out into a new file, and start using the command pattern in the SmartServerRequestHandler. | 2 | #
 | 
| 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.
 | |
| 7 | #
 | |
| 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.
 | |
| 12 | #
 | |
| 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
 | |
| 16 | ||
| 3195.3.4
by Andrew Bennetts Make the general request handler dispatch version 3 events to the specific request handler (i.e. to the SmartServerRequest instance). | 17 | """Basic server-side logic for dealing with requests.
 | 
| 18 | ||
| 19 | **XXX**:
 | |
| 20 | ||
| 21 | The class names are a little confusing: the protocol will instantiate a
 | |
| 22 | SmartServerRequestHandler, whose dispatch_command method creates an instance of
 | |
| 23 | a SmartServerRequest subclass.
 | |
| 24 | ||
| 25 | The request_handlers registry tracks SmartServerRequest classes (rather than
 | |
| 26 | SmartServerRequestHandler).
 | |
| 27 | """
 | |
| 2018.5.19
by Andrew Bennetts Add docstrings to all the new modules, and a few other places. | 28 | |
| 2018.5.6
by Andrew Bennetts Tidy ups, and turn do_hello and do_get_bundle into command objects. | 29 | import tempfile | 
| 30 | ||
| 2402.1.2
by Andrew Bennetts Deal with review comments. | 31 | from bzrlib import ( | 
| 32 | bzrdir, | |
| 33 | errors, | |
| 34 | registry, | |
| 35 | revision, | |
| 2692.1.1
by Andrew Bennetts Add translate_client_path method to SmartServerRequest. | 36 | urlutils, | 
| 2402.1.2
by Andrew Bennetts Deal with review comments. | 37 |     )
 | 
| 2018.5.6
by Andrew Bennetts Tidy ups, and turn do_hello and do_get_bundle into command objects. | 38 | from bzrlib.bundle.serializer import write_bundle | 
| 39 | ||
| 2018.5.4
by Andrew Bennetts Split smart server VFS logic out into a new file, and start using the command pattern in the SmartServerRequestHandler. | 40 | |
| 41 | class SmartServerRequest(object): | |
| 2692.1.10
by Andrew Bennetts More docstring polish | 42 | """Base class for request handlers. | 
| 43 |     
 | |
| 44 |     To define a new request, subclass this class and override the `do` method
 | |
| 45 |     (and if appropriate, `do_body` as well).  Request implementors should take
 | |
| 46 |     care to call `translate_client_path` and `transport_from_client_path` as
 | |
| 47 |     appropriate when dealing with paths received from the client.
 | |
| 48 |     """
 | |
| 3195.3.2
by Andrew Bennetts Checkpoint first rough cut of SmartServerRequestProtocolThree, this implementation reuses the _StatefulDecoder class. Plus some attempts to start tidying the smart protocol tests. | 49 |     # XXX: rename this class to BaseSmartServerRequestHandler ?  A request
 | 
| 50 |     # *handler* is a different concept to the request.
 | |
| 2018.5.4
by Andrew Bennetts Split smart server VFS logic out into a new file, and start using the command pattern in the SmartServerRequestHandler. | 51 | |
| 2692.1.1
by Andrew Bennetts Add translate_client_path method to SmartServerRequest. | 52 | def __init__(self, backing_transport, root_client_path='/'): | 
| 2402.1.2
by Andrew Bennetts Deal with review comments. | 53 | """Constructor. | 
| 54 | ||
| 55 |         :param backing_transport: the base transport to be used when performing
 | |
| 56 |             this request.
 | |
| 2692.1.1
by Andrew Bennetts Add translate_client_path method to SmartServerRequest. | 57 |         :param root_client_path: the client path that maps to the root of
 | 
| 2692.1.9
by Andrew Bennetts Docstrings for translate_client_path and transport_from_client_path. | 58 |             backing_transport.  This is used to interpret relpaths received
 | 
| 59 |             from the client.  Clients will not be able to refer to paths above
 | |
| 2692.1.16
by Andrew Bennetts Improve comments. | 60 |             this root.  If root_client_path is None, then no translation will
 | 
| 61 |             be performed on client paths.  Default is '/'.
 | |
| 2402.1.2
by Andrew Bennetts Deal with review comments. | 62 |         """
 | 
| 2018.5.4
by Andrew Bennetts Split smart server VFS logic out into a new file, and start using the command pattern in the SmartServerRequestHandler. | 63 | self._backing_transport = backing_transport | 
| 2692.1.14
by Andrew Bennetts All WSGI tests passing, and manual testing works too. | 64 | if root_client_path is not None: | 
| 65 | if not root_client_path.startswith('/'): | |
| 66 | root_client_path = '/' + root_client_path | |
| 67 | if not root_client_path.endswith('/'): | |
| 68 | root_client_path += '/' | |
| 2692.1.1
by Andrew Bennetts Add translate_client_path method to SmartServerRequest. | 69 | self._root_client_path = root_client_path | 
| 2018.5.5
by Andrew Bennetts Pass body_bytes directly to SmartServerRequest.do_body | 70 | |
| 2018.5.24
by Andrew Bennetts Setting NO_SMART_VFS in environment will disable VFS methods in the smart server. (Robert Collins, John Arbash Meinel, Andrew Bennetts) | 71 | def _check_enabled(self): | 
| 72 | """Raises DisabledMethod if this method is disabled.""" | |
| 73 |         pass
 | |
| 74 | ||
| 2018.5.19
by Andrew Bennetts Add docstrings to all the new modules, and a few other places. | 75 | def do(self, *args): | 
| 2018.5.24
by Andrew Bennetts Setting NO_SMART_VFS in environment will disable VFS methods in the smart server. (Robert Collins, John Arbash Meinel, Andrew Bennetts) | 76 | """Mandatory extension point for SmartServerRequest subclasses. | 
| 77 |         
 | |
| 78 |         Subclasses must implement this.
 | |
| 2018.5.19
by Andrew Bennetts Add docstrings to all the new modules, and a few other places. | 79 |         
 | 
| 80 |         This should return a SmartServerResponse if this command expects to
 | |
| 81 |         receive no body.
 | |
| 82 |         """
 | |
| 2018.5.5
by Andrew Bennetts Pass body_bytes directly to SmartServerRequest.do_body | 83 | raise NotImplementedError(self.do) | 
| 84 | ||
| 2018.5.24
by Andrew Bennetts Setting NO_SMART_VFS in environment will disable VFS methods in the smart server. (Robert Collins, John Arbash Meinel, Andrew Bennetts) | 85 | def execute(self, *args): | 
| 86 | """Public entry point to execute this request. | |
| 87 | ||
| 88 |         It will return a SmartServerResponse if the command does not expect a
 | |
| 89 |         body.
 | |
| 90 | ||
| 91 |         :param *args: the arguments of the request.
 | |
| 92 |         """
 | |
| 93 | self._check_enabled() | |
| 94 | return self.do(*args) | |
| 95 | ||
| 2018.5.5
by Andrew Bennetts Pass body_bytes directly to SmartServerRequest.do_body | 96 | def do_body(self, body_bytes): | 
| 2018.5.19
by Andrew Bennetts Add docstrings to all the new modules, and a few other places. | 97 | """Called if the client sends a body with the request. | 
| 3184.1.10
by Robert Collins Change the smart server verb for Repository.stream_revisions_chunked to use SearchResults as the request mechanism for downloads. | 98 | |
| 99 |         The do() method is still called, and must have returned None.
 | |
| 2018.5.19
by Andrew Bennetts Add docstrings to all the new modules, and a few other places. | 100 |         
 | 
| 101 |         Must return a SmartServerResponse.
 | |
| 102 |         """
 | |
| 2018.5.4
by Andrew Bennetts Split smart server VFS logic out into a new file, and start using the command pattern in the SmartServerRequestHandler. | 103 | raise NotImplementedError(self.do_body) | 
| 104 | ||
| 3195.3.4
by Andrew Bennetts Make the general request handler dispatch version 3 events to the specific request handler (i.e. to the SmartServerRequest instance). | 105 | def do_chunk(self, chunk_bytes): | 
| 106 | """Called with each body chunk if the request has a streamed body. | |
| 107 | ||
| 108 |         The do() method is still called, and must have returned None.
 | |
| 109 |         """
 | |
| 110 | raise NotImplementedError(self.do_chunk) | |
| 111 | ||
| 112 | def do_end(self): | |
| 113 | """Called when the end of the request has been received.""" | |
| 114 |         pass
 | |
| 2692.1.1
by Andrew Bennetts Add translate_client_path method to SmartServerRequest. | 115 | |
| 116 | def translate_client_path(self, client_path): | |
| 2692.1.9
by Andrew Bennetts Docstrings for translate_client_path and transport_from_client_path. | 117 | """Translate a path received from a network client into a local | 
| 118 |         relpath.
 | |
| 119 | ||
| 120 |         All paths received from the client *must* be translated.
 | |
| 121 | ||
| 2692.1.14
by Andrew Bennetts All WSGI tests passing, and manual testing works too. | 122 |         :param client_path: the path from the client.
 | 
| 2692.1.9
by Andrew Bennetts Docstrings for translate_client_path and transport_from_client_path. | 123 |         :returns: a relpath that may be used with self._backing_transport
 | 
| 2692.1.14
by Andrew Bennetts All WSGI tests passing, and manual testing works too. | 124 |             (unlike the untranslated client_path, which must not be used with
 | 
| 125 |             the backing transport).
 | |
| 2692.1.9
by Andrew Bennetts Docstrings for translate_client_path and transport_from_client_path. | 126 |         """
 | 
| 2692.1.14
by Andrew Bennetts All WSGI tests passing, and manual testing works too. | 127 | if self._root_client_path is None: | 
| 128 |             # no translation necessary!
 | |
| 129 | return client_path | |
| 2692.1.1
by Andrew Bennetts Add translate_client_path method to SmartServerRequest. | 130 | if not client_path.startswith('/'): | 
| 131 | client_path = '/' + client_path | |
| 132 | if client_path.startswith(self._root_client_path): | |
| 133 | path = client_path[len(self._root_client_path):] | |
| 134 | relpath = urlutils.joinpath('/', path) | |
| 3376.2.4
by Martin Pool Remove every assert statement from bzrlib! | 135 | if not relpath.startswith('/'): | 
| 136 | raise ValueError(relpath) | |
| 2692.1.1
by Andrew Bennetts Add translate_client_path method to SmartServerRequest. | 137 | return '.' + relpath | 
| 138 | else: | |
| 139 | raise errors.PathNotChild(client_path, self._root_client_path) | |
| 140 | ||
| 141 | def transport_from_client_path(self, client_path): | |
| 2692.1.9
by Andrew Bennetts Docstrings for translate_client_path and transport_from_client_path. | 142 | """Get a backing transport corresponding to the location referred to by | 
| 143 |         a network client.
 | |
| 144 | ||
| 145 |         :seealso: translate_client_path
 | |
| 146 |         :returns: a transport cloned from self._backing_transport
 | |
| 147 |         """
 | |
| 2692.1.1
by Andrew Bennetts Add translate_client_path method to SmartServerRequest. | 148 | relpath = self.translate_client_path(client_path) | 
| 2692.1.16
by Andrew Bennetts Improve comments. | 149 | return self._backing_transport.clone(relpath) | 
| 3195.3.4
by Andrew Bennetts Make the general request handler dispatch version 3 events to the specific request handler (i.e. to the SmartServerRequest instance). | 150 | |
| 2018.5.6
by Andrew Bennetts Tidy ups, and turn do_hello and do_get_bundle into command objects. | 151 | |
| 2018.5.16
by Andrew Bennetts Move SmartServerResponse to smart/request.py, untangling more import dependencies. | 152 | class SmartServerResponse(object): | 
| 2432.4.5
by Robert Collins Make using SuccessfulSmartServerResponse and FailedSmartServerResponse mandatory rather than optional in smart server logic. | 153 | """A response to a client request. | 
| 154 |     
 | |
| 155 |     This base class should not be used. Instead use
 | |
| 156 |     SuccessfulSmartServerResponse and FailedSmartServerResponse as appropriate.
 | |
| 157 |     """
 | |
| 2018.5.16
by Andrew Bennetts Move SmartServerResponse to smart/request.py, untangling more import dependencies. | 158 | |
| 2748.4.2
by Andrew Bennetts Add protocol (version two) support for streaming bodies (using chunking) in responses. | 159 | def __init__(self, args, body=None, body_stream=None): | 
| 160 | """Constructor. | |
| 161 | ||
| 162 |         :param args: tuple of response arguments.
 | |
| 163 |         :param body: string of a response body.
 | |
| 164 |         :param body_stream: iterable of bytestrings to be streamed to the
 | |
| 165 |             client.
 | |
| 166 |         """
 | |
| 2018.5.16
by Andrew Bennetts Move SmartServerResponse to smart/request.py, untangling more import dependencies. | 167 | self.args = args | 
| 2748.4.2
by Andrew Bennetts Add protocol (version two) support for streaming bodies (using chunking) in responses. | 168 | if body is not None and body_stream is not None: | 
| 169 | raise errors.BzrError( | |
| 170 | "'body' and 'body_stream' are mutually exclusive.") | |
| 2018.5.16
by Andrew Bennetts Move SmartServerResponse to smart/request.py, untangling more import dependencies. | 171 | self.body = body | 
| 2748.4.2
by Andrew Bennetts Add protocol (version two) support for streaming bodies (using chunking) in responses. | 172 | self.body_stream = body_stream | 
| 2018.5.16
by Andrew Bennetts Move SmartServerResponse to smart/request.py, untangling more import dependencies. | 173 | |
| 2402.1.1
by Andrew Bennetts Use the Command pattern for handling smart server commands. | 174 | def __eq__(self, other): | 
| 175 | if other is None: | |
| 176 | return False | |
| 2748.4.2
by Andrew Bennetts Add protocol (version two) support for streaming bodies (using chunking) in responses. | 177 | return (other.args == self.args and | 
| 178 | other.body == self.body and | |
| 179 | other.body_stream is self.body_stream) | |
| 2402.1.1
by Andrew Bennetts Use the Command pattern for handling smart server commands. | 180 | |
| 181 | def __repr__(self): | |
| 2692.1.1
by Andrew Bennetts Add translate_client_path method to SmartServerRequest. | 182 | status = {True: 'OK', False: 'ERR'}[self.is_successful()] | 
| 183 | return "<SmartServerResponse status=%s args=%r body=%r>" % (status, | |
| 2432.4.5
by Robert Collins Make using SuccessfulSmartServerResponse and FailedSmartServerResponse mandatory rather than optional in smart server logic. | 184 | self.args, self.body) | 
| 2402.1.1
by Andrew Bennetts Use the Command pattern for handling smart server commands. | 185 | |
| 2018.5.16
by Andrew Bennetts Move SmartServerResponse to smart/request.py, untangling more import dependencies. | 186 | |
| 2432.4.2
by Robert Collins Add FailedSmartServerResponse. | 187 | class FailedSmartServerResponse(SmartServerResponse): | 
| 188 | """A SmartServerResponse for a request which failed.""" | |
| 189 | ||
| 190 | def is_successful(self): | |
| 191 | """FailedSmartServerResponse are not successful.""" | |
| 192 | return False | |
| 193 | ||
| 194 | ||
| 2432.4.1
by Robert Collins Add SuccessfulSmartServerResponse. | 195 | class SuccessfulSmartServerResponse(SmartServerResponse): | 
| 196 | """A SmartServerResponse for a successfully completed request.""" | |
| 197 | ||
| 198 | def is_successful(self): | |
| 199 | """SuccessfulSmartServerResponse are successful.""" | |
| 200 | return True | |
| 201 | ||
| 2018.5.16
by Andrew Bennetts Move SmartServerResponse to smart/request.py, untangling more import dependencies. | 202 | |
| 2018.5.14
by Andrew Bennetts Move SmartTCPServer to smart/server.py, and SmartServerRequestHandler to smart/request.py. | 203 | class SmartServerRequestHandler(object): | 
| 204 | """Protocol logic for smart server. | |
| 205 |     
 | |
| 206 |     This doesn't handle serialization at all, it just processes requests and
 | |
| 207 |     creates responses.
 | |
| 208 |     """
 | |
| 209 | ||
| 210 |     # IMPORTANT FOR IMPLEMENTORS: It is important that SmartServerRequestHandler
 | |
| 211 |     # not contain encoding or decoding logic to allow the wire protocol to vary
 | |
| 212 |     # from the object protocol: we will want to tweak the wire protocol separate
 | |
| 213 |     # from the object model, and ideally we will be able to do that without
 | |
| 214 |     # having a SmartServerRequestHandler subclass for each wire protocol, rather
 | |
| 215 |     # just a Protocol subclass.
 | |
| 216 | ||
| 217 |     # TODO: Better way of representing the body for commands that take it,
 | |
| 218 |     # and allow it to be streamed into the server.
 | |
| 219 | ||
| 2692.1.1
by Andrew Bennetts Add translate_client_path method to SmartServerRequest. | 220 | def __init__(self, backing_transport, commands, root_client_path): | 
| 2018.5.17
by Andrew Bennetts Paramaterise the commands handled by SmartServerRequestHandler. | 221 | """Constructor. | 
| 222 | ||
| 223 |         :param backing_transport: a Transport to handle requests for.
 | |
| 2018.5.23
by Andrew Bennetts Use a Registry for smart server command handlers. | 224 |         :param commands: a registry mapping command names to SmartServerRequest
 | 
| 2018.5.17
by Andrew Bennetts Paramaterise the commands handled by SmartServerRequestHandler. | 225 |             subclasses. e.g. bzrlib.transport.smart.vfs.vfs_commands.
 | 
| 226 |         """
 | |
| 2018.5.14
by Andrew Bennetts Move SmartTCPServer to smart/server.py, and SmartServerRequestHandler to smart/request.py. | 227 | self._backing_transport = backing_transport | 
| 2692.1.1
by Andrew Bennetts Add translate_client_path method to SmartServerRequest. | 228 | self._root_client_path = root_client_path | 
| 2018.5.17
by Andrew Bennetts Paramaterise the commands handled by SmartServerRequestHandler. | 229 | self._commands = commands | 
| 2018.5.14
by Andrew Bennetts Move SmartTCPServer to smart/server.py, and SmartServerRequestHandler to smart/request.py. | 230 | self._body_bytes = '' | 
| 231 | self.response = None | |
| 232 | self.finished_reading = False | |
| 233 | self._command = None | |
| 234 | ||
| 235 | def accept_body(self, bytes): | |
| 236 | """Accept body data.""" | |
| 237 | ||
| 238 |         # TODO: This should be overriden for each command that desired body data
 | |
| 239 |         # to handle the right format of that data, i.e. plain bytes, a bundle,
 | |
| 240 |         # etc.  The deserialisation into that format should be done in the
 | |
| 241 |         # Protocol object.
 | |
| 242 | ||
| 243 |         # default fallback is to accumulate bytes.
 | |
| 244 | self._body_bytes += bytes | |
| 245 | ||
| 246 | def end_of_body(self): | |
| 247 | """No more body data will be received.""" | |
| 248 | self._run_handler_code(self._command.do_body, (self._body_bytes,), {}) | |
| 249 |         # cannot read after this.
 | |
| 250 | self.finished_reading = True | |
| 251 | ||
| 252 | def dispatch_command(self, cmd, args): | |
| 253 | """Deprecated compatibility method.""" # XXX XXX | |
| 2018.5.23
by Andrew Bennetts Use a Registry for smart server command handlers. | 254 | try: | 
| 255 | command = self._commands.get(cmd) | |
| 256 | except LookupError: | |
| 3245.4.29
by Andrew Bennetts Add/tidy some comments, remove dud test_errors_are_logged test, add explicit UnknownSmartMethod to v3. | 257 | raise errors.UnknownSmartMethod(cmd) | 
| 2692.1.1
by Andrew Bennetts Add translate_client_path method to SmartServerRequest. | 258 | self._command = command(self._backing_transport, self._root_client_path) | 
| 2018.5.24
by Andrew Bennetts Setting NO_SMART_VFS in environment will disable VFS methods in the smart server. (Robert Collins, John Arbash Meinel, Andrew Bennetts) | 259 | self._run_handler_code(self._command.execute, args, {}) | 
| 2018.5.14
by Andrew Bennetts Move SmartTCPServer to smart/server.py, and SmartServerRequestHandler to smart/request.py. | 260 | |
| 261 | def _run_handler_code(self, callable, args, kwargs): | |
| 262 | """Run some handler specific code 'callable'. | |
| 263 | ||
| 264 |         If a result is returned, it is considered to be the commands response,
 | |
| 265 |         and finished_reading is set true, and its assigned to self.response.
 | |
| 266 | ||
| 267 |         Any exceptions caught are translated and a response object created
 | |
| 268 |         from them.
 | |
| 269 |         """
 | |
| 270 | result = self._call_converting_errors(callable, args, kwargs) | |
| 2018.5.19
by Andrew Bennetts Add docstrings to all the new modules, and a few other places. | 271 | |
| 2018.5.14
by Andrew Bennetts Move SmartTCPServer to smart/server.py, and SmartServerRequestHandler to smart/request.py. | 272 | if result is not None: | 
| 273 | self.response = result | |
| 274 | self.finished_reading = True | |
| 275 | ||
| 276 | def _call_converting_errors(self, callable, args, kwargs): | |
| 277 | """Call callable converting errors to Response objects.""" | |
| 278 |         # XXX: most of this error conversion is VFS-related, and thus ought to
 | |
| 279 |         # be in SmartServerVFSRequestHandler somewhere.
 | |
| 280 | try: | |
| 281 | return callable(*args, **kwargs) | |
| 282 | except errors.NoSuchFile, e: | |
| 2432.4.5
by Robert Collins Make using SuccessfulSmartServerResponse and FailedSmartServerResponse mandatory rather than optional in smart server logic. | 283 | return FailedSmartServerResponse(('NoSuchFile', e.path)) | 
| 2018.5.14
by Andrew Bennetts Move SmartTCPServer to smart/server.py, and SmartServerRequestHandler to smart/request.py. | 284 | except errors.FileExists, e: | 
| 2432.4.5
by Robert Collins Make using SuccessfulSmartServerResponse and FailedSmartServerResponse mandatory rather than optional in smart server logic. | 285 | return FailedSmartServerResponse(('FileExists', e.path)) | 
| 2018.5.14
by Andrew Bennetts Move SmartTCPServer to smart/server.py, and SmartServerRequestHandler to smart/request.py. | 286 | except errors.DirectoryNotEmpty, e: | 
| 2432.4.5
by Robert Collins Make using SuccessfulSmartServerResponse and FailedSmartServerResponse mandatory rather than optional in smart server logic. | 287 | return FailedSmartServerResponse(('DirectoryNotEmpty', e.path)) | 
| 2018.5.14
by Andrew Bennetts Move SmartTCPServer to smart/server.py, and SmartServerRequestHandler to smart/request.py. | 288 | except errors.ShortReadvError, e: | 
| 2432.4.5
by Robert Collins Make using SuccessfulSmartServerResponse and FailedSmartServerResponse mandatory rather than optional in smart server logic. | 289 | return FailedSmartServerResponse(('ShortReadvError', | 
| 2018.5.14
by Andrew Bennetts Move SmartTCPServer to smart/server.py, and SmartServerRequestHandler to smart/request.py. | 290 | e.path, str(e.offset), str(e.length), str(e.actual))) | 
| 291 | except UnicodeError, e: | |
| 292 |             # If it is a DecodeError, than most likely we are starting
 | |
| 293 |             # with a plain string
 | |
| 294 | str_or_unicode = e.object | |
| 295 | if isinstance(str_or_unicode, unicode): | |
| 296 |                 # XXX: UTF-8 might have \x01 (our seperator byte) in it.  We
 | |
| 297 |                 # should escape it somehow.
 | |
| 298 | val = 'u:' + str_or_unicode.encode('utf-8') | |
| 299 | else: | |
| 300 | val = 's:' + str_or_unicode.encode('base64') | |
| 301 |             # This handles UnicodeEncodeError or UnicodeDecodeError
 | |
| 2432.4.5
by Robert Collins Make using SuccessfulSmartServerResponse and FailedSmartServerResponse mandatory rather than optional in smart server logic. | 302 | return FailedSmartServerResponse((e.__class__.__name__, | 
| 2018.5.14
by Andrew Bennetts Move SmartTCPServer to smart/server.py, and SmartServerRequestHandler to smart/request.py. | 303 | e.encoding, val, str(e.start), str(e.end), e.reason)) | 
| 304 | except errors.TransportNotPossible, e: | |
| 305 | if e.msg == "readonly transport": | |
| 2432.4.5
by Robert Collins Make using SuccessfulSmartServerResponse and FailedSmartServerResponse mandatory rather than optional in smart server logic. | 306 | return FailedSmartServerResponse(('ReadOnlyError', )) | 
| 2018.5.14
by Andrew Bennetts Move SmartTCPServer to smart/server.py, and SmartServerRequestHandler to smart/request.py. | 307 | else: | 
| 308 |                 raise
 | |
| 309 | ||
| 3195.3.2
by Andrew Bennetts Checkpoint first rough cut of SmartServerRequestProtocolThree, this implementation reuses the _StatefulDecoder class. Plus some attempts to start tidying the smart protocol tests. | 310 | def headers_received(self, headers): | 
| 3245.4.33
by Andrew Bennetts Remove unused no_body_received method on SmartServerRequestHandler. | 311 |         # Just a no-op at the moment.
 | 
| 3195.3.2
by Andrew Bennetts Checkpoint first rough cut of SmartServerRequestProtocolThree, this implementation reuses the _StatefulDecoder class. Plus some attempts to start tidying the smart protocol tests. | 312 |         pass
 | 
| 313 | ||
| 314 | def args_received(self, args): | |
| 3195.3.4
by Andrew Bennetts Make the general request handler dispatch version 3 events to the specific request handler (i.e. to the SmartServerRequest instance). | 315 | cmd = args[0] | 
| 316 | args = args[1:] | |
| 317 | try: | |
| 318 | command = self._commands.get(cmd) | |
| 319 | except LookupError: | |
| 3245.4.48
by Andrew Bennetts raise UnknownSmartMethod from dispatch_command. | 320 | raise errors.UnknownSmartMethod(cmd) | 
| 3195.3.4
by Andrew Bennetts Make the general request handler dispatch version 3 events to the specific request handler (i.e. to the SmartServerRequest instance). | 321 | self._command = command(self._backing_transport) | 
| 322 | self._run_handler_code(self._command.execute, args, {}) | |
| 3195.3.2
by Andrew Bennetts Checkpoint first rough cut of SmartServerRequestProtocolThree, this implementation reuses the _StatefulDecoder class. Plus some attempts to start tidying the smart protocol tests. | 323 | |
| 324 | def prefixed_body_received(self, body_bytes): | |
| 3195.3.4
by Andrew Bennetts Make the general request handler dispatch version 3 events to the specific request handler (i.e. to the SmartServerRequest instance). | 325 | """No more body data will be received.""" | 
| 326 | self._run_handler_code(self._command.do_body, (body_bytes,), {}) | |
| 327 |         # cannot read after this.
 | |
| 328 | self.finished_reading = True | |
| 3195.3.2
by Andrew Bennetts Checkpoint first rough cut of SmartServerRequestProtocolThree, this implementation reuses the _StatefulDecoder class. Plus some attempts to start tidying the smart protocol tests. | 329 | |
| 330 | def body_chunk_received(self, chunk_bytes): | |
| 3195.3.4
by Andrew Bennetts Make the general request handler dispatch version 3 events to the specific request handler (i.e. to the SmartServerRequest instance). | 331 | self._run_handler_code(self._command.do_chunk, (chunk_bytes,), {}) | 
| 3195.3.2
by Andrew Bennetts Checkpoint first rough cut of SmartServerRequestProtocolThree, this implementation reuses the _StatefulDecoder class. Plus some attempts to start tidying the smart protocol tests. | 332 | |
| 3195.3.4
by Andrew Bennetts Make the general request handler dispatch version 3 events to the specific request handler (i.e. to the SmartServerRequest instance). | 333 | def end_received(self): | 
| 334 | self._run_handler_code(self._command.do_end, (), {}) | |
| 3195.3.2
by Andrew Bennetts Checkpoint first rough cut of SmartServerRequestProtocolThree, this implementation reuses the _StatefulDecoder class. Plus some attempts to start tidying the smart protocol tests. | 335 | |
| 2018.5.14
by Andrew Bennetts Move SmartTCPServer to smart/server.py, and SmartServerRequestHandler to smart/request.py. | 336 | |
| 2018.5.6
by Andrew Bennetts Tidy ups, and turn do_hello and do_get_bundle into command objects. | 337 | class HelloRequest(SmartServerRequest): | 
| 2432.2.6
by Andrew Bennetts Improve HelloRequest's docstring. | 338 | """Answer a version request with the highest protocol version this server | 
| 339 |     supports.
 | |
| 340 |     """
 | |
| 2018.5.6
by Andrew Bennetts Tidy ups, and turn do_hello and do_get_bundle into command objects. | 341 | |
| 342 | def do(self): | |
| 3245.4.59
by Andrew Bennetts Various tweaks in response to Martin's review. | 343 | return SuccessfulSmartServerResponse(('ok', '2')) | 
| 2018.5.6
by Andrew Bennetts Tidy ups, and turn do_hello and do_get_bundle into command objects. | 344 | |
| 345 | ||
| 346 | class GetBundleRequest(SmartServerRequest): | |
| 2402.1.2
by Andrew Bennetts Deal with review comments. | 347 | """Get a bundle of from the null revision to the specified revision.""" | 
| 2018.5.6
by Andrew Bennetts Tidy ups, and turn do_hello and do_get_bundle into command objects. | 348 | |
| 349 | def do(self, path, revision_id): | |
| 350 |         # open transport relative to our base
 | |
| 2692.1.7
by Andrew Bennetts Translate path in GetBundleRequest too. | 351 | t = self.transport_from_client_path(path) | 
| 2018.5.6
by Andrew Bennetts Tidy ups, and turn do_hello and do_get_bundle into command objects. | 352 | control, extra_path = bzrdir.BzrDir.open_containing_from_transport(t) | 
| 353 | repo = control.open_repository() | |
| 354 | tmpf = tempfile.TemporaryFile() | |
| 355 | base_revision = revision.NULL_REVISION | |
| 356 | write_bundle(repo, revision_id, base_revision, tmpf) | |
| 357 | tmpf.seek(0) | |
| 2432.4.5
by Robert Collins Make using SuccessfulSmartServerResponse and FailedSmartServerResponse mandatory rather than optional in smart server logic. | 358 | return SuccessfulSmartServerResponse((), tmpf.read()) | 
| 2018.5.6
by Andrew Bennetts Tidy ups, and turn do_hello and do_get_bundle into command objects. | 359 | |
| 360 | ||
| 2018.5.95
by Andrew Bennetts Add a Transport.is_readonly remote call, let {Branch,Repository}.lock_write remote call return UnlockableTransport, and miscellaneous test fixes. | 361 | class SmartServerIsReadonly(SmartServerRequest): | 
| 362 |     # XXX: this request method belongs somewhere else.
 | |
| 363 | ||
| 364 | def do(self): | |
| 365 | if self._backing_transport.is_readonly(): | |
| 366 | answer = 'yes' | |
| 367 | else: | |
| 368 | answer = 'no' | |
| 2432.4.5
by Robert Collins Make using SuccessfulSmartServerResponse and FailedSmartServerResponse mandatory rather than optional in smart server logic. | 369 | return SuccessfulSmartServerResponse((answer,)) | 
| 2018.5.95
by Andrew Bennetts Add a Transport.is_readonly remote call, let {Branch,Repository}.lock_write remote call return UnlockableTransport, and miscellaneous test fixes. | 370 | |
| 371 | ||
| 2018.5.23
by Andrew Bennetts Use a Registry for smart server command handlers. | 372 | request_handlers = registry.Registry() | 
| 373 | request_handlers.register_lazy( | |
| 374 | 'append', 'bzrlib.smart.vfs', 'AppendRequest') | |
| 375 | request_handlers.register_lazy( | |
| 2018.5.59
by Robert Collins Get BranchConfig working somewhat on RemoteBranches (Robert Collins, Vincent Ladeuil). | 376 | 'Branch.get_config_file', 'bzrlib.smart.branch', 'SmartServerBranchGetConfigFile') | 
| 377 | request_handlers.register_lazy( | |
| 2018.5.51
by Wouter van Heyst Test and implement RemoteBranch.last_revision_info() | 378 | 'Branch.last_revision_info', 'bzrlib.smart.branch', 'SmartServerBranchRequestLastRevisionInfo') | 
| 379 | request_handlers.register_lazy( | |
| 2018.5.79
by Andrew Bennetts Implement RemoteBranch.lock_write/unlock as smart operations. | 380 | 'Branch.lock_write', 'bzrlib.smart.branch', 'SmartServerBranchRequestLockWrite') | 
| 381 | request_handlers.register_lazy( | |
| 2018.5.38
by Robert Collins Implement RemoteBranch.revision_history(). | 382 | 'Branch.revision_history', 'bzrlib.smart.branch', 'SmartServerRequestRevisionHistory') | 
| 383 | request_handlers.register_lazy( | |
| 2018.5.77
by Wouter van Heyst Fix typo in request_handlers registration of Branch.set_last_revision, and test that registration | 384 | 'Branch.set_last_revision', 'bzrlib.smart.branch', 'SmartServerBranchRequestSetLastRevision') | 
| 2018.12.3
by Andrew Bennetts Add a Branch.set_last_revision smart method, and make RemoteBranch.set_revision_history use it. | 385 | request_handlers.register_lazy( | 
| 2892.2.1
by Andrew Bennetts Add Branch.set_last_revision_info smart method, and make the RemoteBranch client use it. | 386 | 'Branch.set_last_revision_info', 'bzrlib.smart.branch', | 
| 387 | 'SmartServerBranchRequestSetLastRevisionInfo') | |
| 388 | request_handlers.register_lazy( | |
| 3441.5.25
by Andrew Bennetts Rename Branch.set_last_revision_descendant verb to Branch.set_last_revision_ex. It's a cop out, but at least it's not misleading. | 389 | 'Branch.set_last_revision_ex', 'bzrlib.smart.branch', | 
| 390 | 'SmartServerBranchRequestSetLastRevisionEx') | |
| 3441.5.6
by Andrew Bennetts Greatly simplify RemoteBranch.update_revisions. Still needs more tests. | 391 | request_handlers.register_lazy( | 
| 2018.5.79
by Andrew Bennetts Implement RemoteBranch.lock_write/unlock as smart operations. | 392 | 'Branch.unlock', 'bzrlib.smart.branch', 'SmartServerBranchRequestUnlock') | 
| 393 | request_handlers.register_lazy( | |
| 3221.3.2
by Robert Collins * New remote method ``RemoteBzrDir.find_repositoryV2`` adding support for | 394 | 'BzrDir.find_repository', 'bzrlib.smart.bzrdir', 'SmartServerRequestFindRepositoryV1') | 
| 395 | request_handlers.register_lazy( | |
| 396 | 'BzrDir.find_repositoryV2', 'bzrlib.smart.bzrdir', 'SmartServerRequestFindRepositoryV2') | |
| 2018.5.34
by Robert Collins Get test_remote.BasicRemoteObjectTests.test_open_remote_branch passing by implementing a remote method BzrDir.find_repository. | 397 | request_handlers.register_lazy( | 
| 2018.5.42
by Robert Collins Various hopefully improvements, but wsgi is broken, handing over to spiv :). | 398 | 'BzrDirFormat.initialize', 'bzrlib.smart.bzrdir', 'SmartServerRequestInitializeBzrDir') | 
| 399 | request_handlers.register_lazy( | |
| 2018.6.1
by Robert Collins Implement a BzrDir.open_branch smart server method for opening a branch without VFS. | 400 | 'BzrDir.open_branch', 'bzrlib.smart.bzrdir', 'SmartServerRequestOpenBranch') | 
| 401 | request_handlers.register_lazy( | |
| 2018.5.23
by Andrew Bennetts Use a Registry for smart server command handlers. | 402 | 'delete', 'bzrlib.smart.vfs', 'DeleteRequest') | 
| 403 | request_handlers.register_lazy( | |
| 404 | 'get', 'bzrlib.smart.vfs', 'GetRequest') | |
| 405 | request_handlers.register_lazy( | |
| 406 | 'get_bundle', 'bzrlib.smart.request', 'GetBundleRequest') | |
| 407 | request_handlers.register_lazy( | |
| 408 | 'has', 'bzrlib.smart.vfs', 'HasRequest') | |
| 409 | request_handlers.register_lazy( | |
| 410 | 'hello', 'bzrlib.smart.request', 'HelloRequest') | |
| 411 | request_handlers.register_lazy( | |
| 2018.5.37
by Andrew Bennetts Make sure all the request handlers in bzrlib/smart/vfs.py have consistent names. | 412 | 'iter_files_recursive', 'bzrlib.smart.vfs', 'IterFilesRecursiveRequest') | 
| 2018.5.23
by Andrew Bennetts Use a Registry for smart server command handlers. | 413 | request_handlers.register_lazy( | 
| 414 | 'list_dir', 'bzrlib.smart.vfs', 'ListDirRequest') | |
| 415 | request_handlers.register_lazy( | |
| 2018.5.37
by Andrew Bennetts Make sure all the request handlers in bzrlib/smart/vfs.py have consistent names. | 416 | 'mkdir', 'bzrlib.smart.vfs', 'MkdirRequest') | 
| 417 | request_handlers.register_lazy( | |
| 418 | 'move', 'bzrlib.smart.vfs', 'MoveRequest') | |
| 419 | request_handlers.register_lazy( | |
| 420 | 'put', 'bzrlib.smart.vfs', 'PutRequest') | |
| 421 | request_handlers.register_lazy( | |
| 422 | 'put_non_atomic', 'bzrlib.smart.vfs', 'PutNonAtomicRequest') | |
| 423 | request_handlers.register_lazy( | |
| 424 | 'readv', 'bzrlib.smart.vfs', 'ReadvRequest') | |
| 425 | request_handlers.register_lazy( | |
| 426 | 'rename', 'bzrlib.smart.vfs', 'RenameRequest') | |
| 2018.10.2
by v.ladeuil+lp at free gather_stats server side and request registration | 427 | request_handlers.register_lazy('Repository.gather_stats', | 
| 428 | 'bzrlib.smart.repository', | |
| 429 | 'SmartServerRepositoryGatherStats') | |
| 3172.5.6
by Robert Collins Create new smart server verb Repository.get_parent_map. | 430 | request_handlers.register_lazy('Repository.get_parent_map', | 
| 431 | 'bzrlib.smart.repository', | |
| 432 | 'SmartServerRepositoryGetParentMap') | |
| 2018.5.37
by Andrew Bennetts Make sure all the request handlers in bzrlib/smart/vfs.py have consistent names. | 433 | request_handlers.register_lazy( | 
| 2535.4.29
by Andrew Bennetts Add a new smart method, Repository.stream_revisions_chunked, rather than changing the behaviour of an existing method. | 434 | 'Repository.stream_knit_data_for_revisions', | 
| 435 | 'bzrlib.smart.repository', | |
| 436 | 'SmartServerRepositoryStreamKnitDataForRevisions') | |
| 437 | request_handlers.register_lazy( | |
| 438 | 'Repository.stream_revisions_chunked', | |
| 439 | 'bzrlib.smart.repository', | |
| 440 | 'SmartServerRepositoryStreamRevisionsChunked') | |
| 441 | request_handlers.register_lazy( | |
| 2018.5.67
by Wouter van Heyst Implement RemoteRepository.get_revision_graph (Wouter van Heyst, Robert Collins) | 442 | 'Repository.get_revision_graph', 'bzrlib.smart.repository', 'SmartServerRepositoryGetRevisionGraph') | 
| 443 | request_handlers.register_lazy( | |
| 2018.5.40
by Robert Collins Implement a remote Repository.has_revision method. | 444 | 'Repository.has_revision', 'bzrlib.smart.repository', 'SmartServerRequestHasRevision') | 
| 445 | request_handlers.register_lazy( | |
| 2018.5.57
by Robert Collins Implement RemoteRepository.is_shared (Robert Collins, Vincent Ladeuil). | 446 | 'Repository.is_shared', 'bzrlib.smart.repository', 'SmartServerRepositoryIsShared') | 
| 447 | request_handlers.register_lazy( | |
| 2018.5.78
by Andrew Bennetts Implement RemoteRepository.lock_write/unlock to expect and send tokens over the | 448 | 'Repository.lock_write', 'bzrlib.smart.repository', 'SmartServerRepositoryLockWrite') | 
| 449 | request_handlers.register_lazy( | |
| 450 | 'Repository.unlock', 'bzrlib.smart.repository', 'SmartServerRepositoryUnlock') | |
| 451 | request_handlers.register_lazy( | |
| 2018.18.1
by Martin Pool Add stub Repository.tarball smart method | 452 | 'Repository.tarball', 'bzrlib.smart.repository', | 
| 453 | 'SmartServerRepositoryTarball') | |
| 454 | request_handlers.register_lazy( | |
| 2018.5.37
by Andrew Bennetts Make sure all the request handlers in bzrlib/smart/vfs.py have consistent names. | 455 | 'rmdir', 'bzrlib.smart.vfs', 'RmdirRequest') | 
| 456 | request_handlers.register_lazy( | |
| 457 | 'stat', 'bzrlib.smart.vfs', 'StatRequest') | |
| 2018.5.26
by Andrew Bennetts Extract a simple SmartClient class from RemoteTransport, and a hack to avoid VFS operations when probing for a bzrdir over a smart transport. | 458 | request_handlers.register_lazy( | 
| 2018.5.95
by Andrew Bennetts Add a Transport.is_readonly remote call, let {Branch,Repository}.lock_write remote call return UnlockableTransport, and miscellaneous test fixes. | 459 | 'Transport.is_readonly', 'bzrlib.smart.request', 'SmartServerIsReadonly') | 
| 460 | request_handlers.register_lazy( | |
| 2018.5.163
by Andrew Bennetts Deal with various review comments from Robert. | 461 | 'BzrDir.open', 'bzrlib.smart.bzrdir', 'SmartServerRequestOpenBzrDir') |