~bzr-pqm/bzr/bzr.dev

3245.4.31 by Andrew Bennetts
Fix year in copyright statement of message.py
1
# Copyright (C) 2008 Canonical Ltd
3195.3.17 by Andrew Bennetts
Some tests now passing using protocol 3.
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
4183.7.1 by Sabin Iacob
update FSF mailing address
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
3195.3.17 by Andrew Bennetts
Some tests now passing using protocol 3.
16
3195.3.24 by Andrew Bennetts
Implement read_streamed_body on ConventionalResponseHandler.
17
import collections
3195.3.17 by Andrew Bennetts
Some tests now passing using protocol 3.
18
from cStringIO import StringIO
19
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
20
from bzrlib import (
21
    debug,
22
    errors,
23
    )
24
from bzrlib.trace import mutter
3195.3.17 by Andrew Bennetts
Some tests now passing using protocol 3.
25
3245.4.39 by Andrew Bennetts
Tweaks to bzrlib/smart/message.py suggested by John's review.
26
3195.3.17 by Andrew Bennetts
Some tests now passing using protocol 3.
27
class MessageHandler(object):
3245.4.39 by Andrew Bennetts
Tweaks to bzrlib/smart/message.py suggested by John's review.
28
    """Base class for handling messages received via the smart protocol.
29
30
    As parts of a message are received, the corresponding PART_received method
31
    will be called.
32
    """
3195.3.17 by Andrew Bennetts
Some tests now passing using protocol 3.
33
34
    def __init__(self):
35
        self.headers = None
36
37
    def headers_received(self, headers):
3245.4.39 by Andrew Bennetts
Tweaks to bzrlib/smart/message.py suggested by John's review.
38
        """Called when message headers are received.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
39
3245.4.39 by Andrew Bennetts
Tweaks to bzrlib/smart/message.py suggested by John's review.
40
        This default implementation just stores them in self.headers.
41
        """
3195.3.17 by Andrew Bennetts
Some tests now passing using protocol 3.
42
        self.headers = headers
43
44
    def byte_part_received(self, byte):
3245.4.39 by Andrew Bennetts
Tweaks to bzrlib/smart/message.py suggested by John's review.
45
        """Called when a 'byte' part is received.
46
47
        Note that a 'byte' part is a message part consisting of exactly one
48
        byte.
49
        """
3195.3.17 by Andrew Bennetts
Some tests now passing using protocol 3.
50
        raise NotImplementedError(self.byte_received)
51
52
    def bytes_part_received(self, bytes):
3245.4.39 by Andrew Bennetts
Tweaks to bzrlib/smart/message.py suggested by John's review.
53
        """Called when a 'bytes' part is received.
54
55
        A 'bytes' message part can contain any number of bytes.  It should not
56
        be confused with a 'byte' part, which is always a single byte.
57
        """
3195.3.17 by Andrew Bennetts
Some tests now passing using protocol 3.
58
        raise NotImplementedError(self.bytes_received)
59
60
    def structure_part_received(self, structure):
3245.4.39 by Andrew Bennetts
Tweaks to bzrlib/smart/message.py suggested by John's review.
61
        """Called when a 'structure' part is received.
62
63
        :param structure: some structured data, which will be some combination
64
            of list, dict, int, and str objects.
65
        """
3195.3.17 by Andrew Bennetts
Some tests now passing using protocol 3.
66
        raise NotImplementedError(self.bytes_received)
67
68
    def protocol_error(self, exception):
3245.4.39 by Andrew Bennetts
Tweaks to bzrlib/smart/message.py suggested by John's review.
69
        """Called when there is a protocol decoding error.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
70
3245.4.39 by Andrew Bennetts
Tweaks to bzrlib/smart/message.py suggested by John's review.
71
        The default implementation just re-raises the exception.
72
        """
3195.3.17 by Andrew Bennetts
Some tests now passing using protocol 3.
73
        raise
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
74
3195.3.17 by Andrew Bennetts
Some tests now passing using protocol 3.
75
    def end_received(self):
3245.4.39 by Andrew Bennetts
Tweaks to bzrlib/smart/message.py suggested by John's review.
76
        """Called when the end of the message is received."""
3245.4.27 by Andrew Bennetts
Tidy some XXXs in bzrlib/smart/message.py.
77
        # No-op by default.
3195.3.17 by Andrew Bennetts
Some tests now passing using protocol 3.
78
        pass
79
80
81
class ConventionalRequestHandler(MessageHandler):
3245.4.39 by Andrew Bennetts
Tweaks to bzrlib/smart/message.py suggested by John's review.
82
    """A message handler for "conventional" requests.
83
84
    "Conventional" is used in the sense described in
85
    doc/developers/network-protocol.txt: a simple message with arguments and an
86
    optional body.
3842.3.4 by Andrew Bennetts
TestStacking.test_fetch_copies_from_stacked_on now passes using the VersionedFile.insert_record_stream RPC; lots of debugging cruft needs removal though.
87
88
    Possible states:
3842.3.19 by Andrew Bennetts
Tweaks suggested by review.
89
     * args: expecting args
90
     * body: expecting body (terminated by receiving a post-body status)
91
     * error: expecting post-body error
92
     * end: expecting end of message
93
     * nothing: finished
3245.4.39 by Andrew Bennetts
Tweaks to bzrlib/smart/message.py suggested by John's review.
94
    """
3195.3.17 by Andrew Bennetts
Some tests now passing using protocol 3.
95
96
    def __init__(self, request_handler, responder):
97
        MessageHandler.__init__(self)
98
        self.request_handler = request_handler
99
        self.responder = responder
3842.3.4 by Andrew Bennetts
TestStacking.test_fetch_copies_from_stacked_on now passes using the VersionedFile.insert_record_stream RPC; lots of debugging cruft needs removal though.
100
        self.expecting = 'args'
101
        self._should_finish_body = False
102
        self._response_sent = False
3195.3.17 by Andrew Bennetts
Some tests now passing using protocol 3.
103
104
    def protocol_error(self, exception):
3245.4.50 by Andrew Bennetts
Clarify the code a little.
105
        if self.responder.response_sent:
106
            # We can only send one response to a request, no matter how many
107
            # errors happen while processing it.
108
            return
109
        self.responder.send_error(exception)
3195.3.17 by Andrew Bennetts
Some tests now passing using protocol 3.
110
111
    def byte_part_received(self, byte):
3923.5.1 by Andrew Bennetts
Add _SmartClient.call_with_body_bytes, plus some server-side code for handling bodies delivered in multiple parts.
112
        if self.expecting == 'body':
3923.5.4 by Andrew Bennetts
Allow a request's body part(s) to be followed by an error.
113
            if byte == 'S':
114
                # Success.  Nothing more to come except the end of message.
115
                self.expecting = 'end'
116
            elif byte == 'E':
117
                # Error.  Expect an error structure.
118
                self.expecting = 'error'
119
            else:
3842.3.4 by Andrew Bennetts
TestStacking.test_fetch_copies_from_stacked_on now passes using the VersionedFile.insert_record_stream RPC; lots of debugging cruft needs removal though.
120
                raise errors.SmartProtocolError(
121
                    'Non-success status byte in request body: %r' % (byte,))
122
        else:
123
            raise errors.SmartProtocolError(
124
                'Unexpected message part: byte(%r)' % (byte,))
3195.3.17 by Andrew Bennetts
Some tests now passing using protocol 3.
125
126
    def structure_part_received(self, structure):
3923.5.4 by Andrew Bennetts
Allow a request's body part(s) to be followed by an error.
127
        if self.expecting == 'args':
128
            self._args_received(structure)
129
        elif self.expecting == 'error':
130
            self._error_received(structure)
131
        else:
3195.3.17 by Andrew Bennetts
Some tests now passing using protocol 3.
132
            raise errors.SmartProtocolError(
133
                'Unexpected message part: structure(%r)' % (structure,))
3923.5.4 by Andrew Bennetts
Allow a request's body part(s) to be followed by an error.
134
135
    def _args_received(self, args):
3842.3.4 by Andrew Bennetts
TestStacking.test_fetch_copies_from_stacked_on now passes using the VersionedFile.insert_record_stream RPC; lots of debugging cruft needs removal though.
136
        self.expecting = 'body'
3923.5.4 by Andrew Bennetts
Allow a request's body part(s) to be followed by an error.
137
        self.request_handler.dispatch_command(args[0], args[1:])
3195.3.17 by Andrew Bennetts
Some tests now passing using protocol 3.
138
        if self.request_handler.finished_reading:
3842.3.4 by Andrew Bennetts
TestStacking.test_fetch_copies_from_stacked_on now passes using the VersionedFile.insert_record_stream RPC; lots of debugging cruft needs removal though.
139
            self._response_sent = True
3195.3.17 by Andrew Bennetts
Some tests now passing using protocol 3.
140
            self.responder.send_response(self.request_handler.response)
3842.3.4 by Andrew Bennetts
TestStacking.test_fetch_copies_from_stacked_on now passes using the VersionedFile.insert_record_stream RPC; lots of debugging cruft needs removal though.
141
            self.expecting = 'end'
3195.3.17 by Andrew Bennetts
Some tests now passing using protocol 3.
142
3923.5.4 by Andrew Bennetts
Allow a request's body part(s) to be followed by an error.
143
    def _error_received(self, error_args):
144
        self.expecting = 'end'
145
        self.request_handler.post_body_error_received(error_args)
146
3842.3.4 by Andrew Bennetts
TestStacking.test_fetch_copies_from_stacked_on now passes using the VersionedFile.insert_record_stream RPC; lots of debugging cruft needs removal though.
147
    def bytes_part_received(self, bytes):
148
        if self.expecting == 'body':
149
            self._should_finish_body = True
150
            self.request_handler.accept_body(bytes)
151
        else:
152
            raise errors.SmartProtocolError(
153
                'Unexpected message part: bytes(%r)' % (bytes,))
154
155
    def end_received(self):
3923.5.2 by Andrew Bennetts
Completely delegate handling of request body chunks to the command object. The default implementation accumulates, like the existing behaviour.
156
        if self.expecting not in ['body', 'end']:
3923.5.3 by Andrew Bennetts
Raise a better exception if a premature message end happens.
157
            raise errors.SmartProtocolError(
158
                'End of message received prematurely (while expecting %s)'
3923.5.2 by Andrew Bennetts
Completely delegate handling of request body chunks to the command object. The default implementation accumulates, like the existing behaviour.
159
                % (self.expecting,))
3842.3.4 by Andrew Bennetts
TestStacking.test_fetch_copies_from_stacked_on now passes using the VersionedFile.insert_record_stream RPC; lots of debugging cruft needs removal though.
160
        self.expecting = 'nothing'
161
        self.request_handler.end_received()
3923.5.2 by Andrew Bennetts
Completely delegate handling of request body chunks to the command object. The default implementation accumulates, like the existing behaviour.
162
        if not self.request_handler.finished_reading:
163
            raise errors.SmartProtocolError(
164
                "Complete conventional request was received, but request "
165
                "handler has not finished reading.")
3842.3.4 by Andrew Bennetts
TestStacking.test_fetch_copies_from_stacked_on now passes using the VersionedFile.insert_record_stream RPC; lots of debugging cruft needs removal though.
166
        if not self._response_sent:
167
            self.responder.send_response(self.request_handler.response)
3195.3.17 by Andrew Bennetts
Some tests now passing using protocol 3.
168
169
3245.4.26 by Andrew Bennetts
Rename 'setProtoAndMedium' to more accurate 'setProtoAndMediumRequest', add ABCs for Requesters and ResponseHandlers.
170
class ResponseHandler(object):
171
    """Abstract base class for an object that handles a smart response."""
172
173
    def read_response_tuple(self, expect_body=False):
174
        """Reads and returns the response tuple for the current request.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
175
3245.4.26 by Andrew Bennetts
Rename 'setProtoAndMedium' to more accurate 'setProtoAndMediumRequest', add ABCs for Requesters and ResponseHandlers.
176
        :keyword expect_body: a boolean indicating if a body is expected in the
177
            response.  Some protocol versions needs this information to know
178
            when a response is finished.  If False, read_body_bytes should
179
            *not* be called afterwards.  Defaults to False.
180
        :returns: tuple of response arguments.
181
        """
182
        raise NotImplementedError(self.read_response_tuple)
183
184
    def read_body_bytes(self, count=-1):
185
        """Read and return some bytes from the body.
186
187
        :param count: if specified, read up to this many bytes.  By default,
188
            reads the entire body.
189
        :returns: str of bytes from the response body.
190
        """
191
        raise NotImplementedError(self.read_body_bytes)
192
193
    def read_streamed_body(self):
194
        """Returns an iterable that reads and returns a series of body chunks.
195
        """
196
        raise NotImplementedError(self.read_streamed_body)
197
198
    def cancel_read_body(self):
199
        """Stop expecting a body for this response.
200
201
        If expect_body was passed to read_response_tuple, this cancels that
202
        expectation (and thus finishes reading the response, allowing a new
203
        request to be issued).  This is useful if a response turns out to be an
204
        error rather than a normal result with a body.
205
        """
206
        raise NotImplementedError(self.cancel_read_body)
207
208
209
class ConventionalResponseHandler(MessageHandler, ResponseHandler):
3195.3.17 by Andrew Bennetts
Some tests now passing using protocol 3.
210
211
    def __init__(self):
212
        MessageHandler.__init__(self)
213
        self.status = None
214
        self.args = None
3195.3.24 by Andrew Bennetts
Implement read_streamed_body on ConventionalResponseHandler.
215
        self._bytes_parts = collections.deque()
3245.4.5 by Andrew Bennetts
Implement interrupting body streams with an error.
216
        self._body_started = False
217
        self._body_stream_status = None
3195.3.17 by Andrew Bennetts
Some tests now passing using protocol 3.
218
        self._body = None
3245.4.5 by Andrew Bennetts
Implement interrupting body streams with an error.
219
        self._body_error_args = None
3195.3.17 by Andrew Bennetts
Some tests now passing using protocol 3.
220
        self.finished_reading = False
221
3245.4.26 by Andrew Bennetts
Rename 'setProtoAndMedium' to more accurate 'setProtoAndMediumRequest', add ABCs for Requesters and ResponseHandlers.
222
    def setProtoAndMediumRequest(self, protocol_decoder, medium_request):
3195.3.17 by Andrew Bennetts
Some tests now passing using protocol 3.
223
        self._protocol_decoder = protocol_decoder
3245.4.26 by Andrew Bennetts
Rename 'setProtoAndMedium' to more accurate 'setProtoAndMediumRequest', add ABCs for Requesters and ResponseHandlers.
224
        self._medium_request = medium_request
3195.3.17 by Andrew Bennetts
Some tests now passing using protocol 3.
225
226
    def byte_part_received(self, byte):
227
        if byte not in ['E', 'S']:
228
            raise errors.SmartProtocolError(
229
                'Unknown response status: %r' % (byte,))
3245.4.5 by Andrew Bennetts
Implement interrupting body streams with an error.
230
        if self._body_started:
231
            if self._body_stream_status is not None:
232
                raise errors.SmartProtocolError(
233
                    'Unexpected byte part received: %r' % (byte,))
234
            self._body_stream_status = byte
235
        else:
236
            if self.status is not None:
237
                raise errors.SmartProtocolError(
238
                    'Unexpected byte part received: %r' % (byte,))
239
            self.status = byte
3195.3.17 by Andrew Bennetts
Some tests now passing using protocol 3.
240
241
    def bytes_part_received(self, bytes):
3245.4.5 by Andrew Bennetts
Implement interrupting body streams with an error.
242
        self._body_started = True
3195.3.17 by Andrew Bennetts
Some tests now passing using protocol 3.
243
        self._bytes_parts.append(bytes)
244
245
    def structure_part_received(self, structure):
3842.3.6 by Andrew Bennetts
Tweak bencode.py to decode sequences as tuples, not lists.
246
        if type(structure) is not tuple:
3195.3.17 by Andrew Bennetts
Some tests now passing using protocol 3.
247
            raise errors.SmartProtocolError(
3245.4.5 by Andrew Bennetts
Implement interrupting body streams with an error.
248
                'Args structure is not a sequence: %r' % (structure,))
249
        if not self._body_started:
250
            if self.args is not None:
251
                raise errors.SmartProtocolError(
252
                    'Unexpected structure received: %r (already got %r)'
253
                    % (structure, self.args))
254
            self.args = structure
255
        else:
256
            if self._body_stream_status != 'E':
257
                raise errors.SmartProtocolError(
258
                    'Unexpected structure received after body: %r'
259
                    % (structure,))
260
            self._body_error_args = structure
3195.3.17 by Andrew Bennetts
Some tests now passing using protocol 3.
261
262
    def _wait_for_response_args(self):
263
        while self.args is None and not self.finished_reading:
264
            self._read_more()
265
266
    def _wait_for_response_end(self):
267
        while not self.finished_reading:
268
            self._read_more()
269
270
    def _read_more(self):
271
        next_read_size = self._protocol_decoder.next_read_size()
272
        if next_read_size == 0:
273
            # a complete request has been read.
274
            self.finished_reading = True
3245.4.26 by Andrew Bennetts
Rename 'setProtoAndMedium' to more accurate 'setProtoAndMediumRequest', add ABCs for Requesters and ResponseHandlers.
275
            self._medium_request.finished_reading()
3195.3.17 by Andrew Bennetts
Some tests now passing using protocol 3.
276
            return
3750.1.2 by Vincent Ladeuil
Fixed as per Andrew's review.
277
        bytes = self._medium_request.read_bytes(next_read_size)
3195.3.17 by Andrew Bennetts
Some tests now passing using protocol 3.
278
        if bytes == '':
279
            # end of file encountered reading from server
3461.2.1 by Andrew Bennetts
Avoid unnecessary reconnections to old servers when the first HPSS is an error in the right protocol version.
280
            if 'hpss' in debug.debug_flags:
281
                mutter(
282
                    'decoder state: buf[:10]=%r, state_accept=%s',
3702.2.1 by Andrew Bennetts
Fix '_in_buffer' AttributeError when using the -Dhpss debug flag.
283
                    self._protocol_decoder._get_in_buffer()[:10],
3461.2.2 by Andrew Bennetts
Tweak suggested by John.
284
                    self._protocol_decoder.state_accept.__name__)
3195.3.17 by Andrew Bennetts
Some tests now passing using protocol 3.
285
            raise errors.ConnectionReset(
4070.8.1 by Martin Pool
Remove 'try -Dhpss' from error messages
286
                "please check connectivity and permissions")
3195.3.17 by Andrew Bennetts
Some tests now passing using protocol 3.
287
        self._protocol_decoder.accept_bytes(bytes)
288
3245.4.47 by Andrew Bennetts
Don't automatically send 'hello' requests from RemoteBzrDirFormat.probe_transport unless we have to (i.e. the transport is HTTP).
289
    def protocol_error(self, exception):
290
        # Whatever the error is, we're done with this request.
291
        self.finished_reading = True
292
        self._medium_request.finished_reading()
293
        raise
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
294
3195.3.17 by Andrew Bennetts
Some tests now passing using protocol 3.
295
    def read_response_tuple(self, expect_body=False):
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
296
        """Read a response tuple from the wire."""
3195.3.17 by Andrew Bennetts
Some tests now passing using protocol 3.
297
        self._wait_for_response_args()
3195.3.18 by Andrew Bennetts
call_with_body_bytes now works with v3 (e.g. test_copy_content_remote_to_local passes). Lots of debugging cruft, though.
298
        if not expect_body:
299
            self._wait_for_response_end()
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
300
        if 'hpss' in debug.debug_flags:
301
            mutter('   result:   %r', self.args)
302
        if self.status == 'E':
303
            self._wait_for_response_end()
304
            _translate_error(self.args)
3195.3.17 by Andrew Bennetts
Some tests now passing using protocol 3.
305
        return tuple(self.args)
306
307
    def read_body_bytes(self, count=-1):
308
        """Read bytes from the body, decoding into a byte stream.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
309
310
        We read all bytes at once to ensure we've checked the trailer for
3195.3.17 by Andrew Bennetts
Some tests now passing using protocol 3.
311
        errors, and then feed the buffer back as read_body_bytes is called.
3245.4.39 by Andrew Bennetts
Tweaks to bzrlib/smart/message.py suggested by John's review.
312
313
        Like the builtin file.read in Python, a count of -1 (the default) means
314
        read the entire body.
3195.3.17 by Andrew Bennetts
Some tests now passing using protocol 3.
315
        """
3245.4.39 by Andrew Bennetts
Tweaks to bzrlib/smart/message.py suggested by John's review.
316
        # TODO: we don't necessarily need to buffer the full request if count
317
        # != -1.  (2008/04/30, Andrew Bennetts)
3195.3.17 by Andrew Bennetts
Some tests now passing using protocol 3.
318
        if self._body is None:
3195.3.18 by Andrew Bennetts
call_with_body_bytes now works with v3 (e.g. test_copy_content_remote_to_local passes). Lots of debugging cruft, though.
319
            self._wait_for_response_end()
3245.4.25 by Andrew Bennetts
Add some -Dhpss mutters to the protocol v3 code, so that it gives comparable debug logging to earlier protocols.
320
            body_bytes = ''.join(self._bytes_parts)
321
            if 'hpss' in debug.debug_flags:
322
                mutter('              %d body bytes read', len(body_bytes))
323
            self._body = StringIO(body_bytes)
3195.3.17 by Andrew Bennetts
Some tests now passing using protocol 3.
324
            self._bytes_parts = None
325
        return self._body.read(count)
326
3195.3.24 by Andrew Bennetts
Implement read_streamed_body on ConventionalResponseHandler.
327
    def read_streamed_body(self):
328
        while not self.finished_reading:
329
            while self._bytes_parts:
3245.4.25 by Andrew Bennetts
Add some -Dhpss mutters to the protocol v3 code, so that it gives comparable debug logging to earlier protocols.
330
                bytes_part = self._bytes_parts.popleft()
4070.9.10 by Andrew Bennetts
Revert some cruft.
331
                if 'hpss' in debug.debug_flags:
332
                    mutter('              %d byte part read', len(bytes_part))
3245.4.25 by Andrew Bennetts
Add some -Dhpss mutters to the protocol v3 code, so that it gives comparable debug logging to earlier protocols.
333
                yield bytes_part
3195.3.24 by Andrew Bennetts
Implement read_streamed_body on ConventionalResponseHandler.
334
            self._read_more()
3245.4.5 by Andrew Bennetts
Implement interrupting body streams with an error.
335
        if self._body_stream_status == 'E':
336
            _translate_error(self._body_error_args)
3195.3.24 by Andrew Bennetts
Implement read_streamed_body on ConventionalResponseHandler.
337
3195.3.17 by Andrew Bennetts
Some tests now passing using protocol 3.
338
    def cancel_read_body(self):
339
        self._wait_for_response_end()
3245.4.5 by Andrew Bennetts
Implement interrupting body streams with an error.
340
341
342
def _translate_error(error_tuple):
3245.4.18 by Andrew Bennetts
Remove a bunch of cruft, especially the SmartClientRequestProtocolThree class.
343
    # Many exceptions need some state from the requestor to be properly
344
    # translated (e.g. they need a branch object).  So this only translates a
345
    # few errors, and the rest are turned into a generic ErrorFromSmartServer.
3245.4.5 by Andrew Bennetts
Implement interrupting body streams with an error.
346
    error_name = error_tuple[0]
347
    error_args = error_tuple[1:]
3245.4.35 by Andrew Bennetts
Remove some commented out cruft, test (and fix) handling of an 'UnknownMethod' response.
348
    if error_name == 'UnknownMethod':
349
        raise errors.UnknownSmartMethod(error_args[0])
3245.4.5 by Andrew Bennetts
Implement interrupting body streams with an error.
350
    if error_name == 'LockContention':
351
        raise errors.LockContention('(remote lock)')
352
    elif error_name == 'LockFailed':
3245.4.24 by Andrew Bennetts
Consistently raise errors from the server as ErrorFromSmartServer exceptions.
353
        raise errors.LockFailed(*error_args[:2])
4294.2.7 by Robert Collins
Start building up a BzrDir.initialize_ex verb for the smart server.
354
    elif error_name == 'FileExists':
355
        raise errors.FileExists(error_args[0])
356
    elif error_name == 'NoSuchFile':
357
        raise errors.NoSuchFile(error_args[0])
3245.4.5 by Andrew Bennetts
Implement interrupting body streams with an error.
358
    else:
359
        raise errors.ErrorFromSmartServer(error_tuple)