/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/smart/request.py

  • Committer: Aaron Bentley
  • Date: 2009-03-09 02:16:29 UTC
  • mfrom: (4090 +trunk)
  • mto: This revision was merged to the branch mainline in revision 4100.
  • Revision ID: aaron@aaronbentley.com-20090309021629-o4j18ltv1hzuuyhl
Merge bzr.dev into clean-tree2

Show diffs side-by-side

added added

removed removed

Lines of Context:
33
33
    errors,
34
34
    registry,
35
35
    revision,
 
36
    trace,
36
37
    urlutils,
37
38
    )
38
39
from bzrlib.lazy_import import lazy_import
43
44
 
44
45
class SmartServerRequest(object):
45
46
    """Base class for request handlers.
46
 
    
 
47
 
47
48
    To define a new request, subclass this class and override the `do` method
48
49
    (and if appropriate, `do_body` as well).  Request implementors should take
49
50
    care to call `translate_client_path` and `transport_from_client_path` as
78
79
 
79
80
    def do(self, *args):
80
81
        """Mandatory extension point for SmartServerRequest subclasses.
81
 
        
 
82
 
82
83
        Subclasses must implement this.
83
 
        
 
84
 
84
85
        This should return a SmartServerResponse if this command expects to
85
86
        receive no body.
86
87
        """
101
102
        """Called if the client sends a body with the request.
102
103
 
103
104
        The do() method is still called, and must have returned None.
104
 
        
 
105
 
105
106
        Must return a SmartServerResponse.
106
107
        """
107
108
        if body_bytes != '':
119
120
        body_bytes = ''.join(self._body_chunks)
120
121
        self._body_chunks = None
121
122
        return self.do_body(body_bytes)
122
 
    
 
123
 
123
124
    def translate_client_path(self, client_path):
124
125
        """Translate a path received from a network client into a local
125
126
        relpath.
158
159
 
159
160
class SmartServerResponse(object):
160
161
    """A response to a client request.
161
 
    
 
162
 
162
163
    This base class should not be used. Instead use
163
164
    SuccessfulSmartServerResponse and FailedSmartServerResponse as appropriate.
164
165
    """
208
209
 
209
210
class SmartServerRequestHandler(object):
210
211
    """Protocol logic for smart server.
211
 
    
 
212
 
212
213
    This doesn't handle serialization at all, it just processes requests and
213
214
    creates responses.
214
215
    """
240
241
    def accept_body(self, bytes):
241
242
        """Accept body data."""
242
243
        self._run_handler_code(self._command.do_chunk, (bytes,), {})
243
 
        
 
244
 
244
245
    def end_of_body(self):
245
246
        """No more body data will be received."""
246
247
        self._run_handler_code(self._command.do_end, (), {})
277
278
        # be in SmartServerVFSRequestHandler somewhere.
278
279
        try:
279
280
            return callable(*args, **kwargs)
280
 
        except errors.NoSuchFile, e:
281
 
            return FailedSmartServerResponse(('NoSuchFile', e.path))
282
 
        except errors.FileExists, e:
283
 
            return FailedSmartServerResponse(('FileExists', e.path))
284
 
        except errors.DirectoryNotEmpty, e:
285
 
            return FailedSmartServerResponse(('DirectoryNotEmpty', e.path))
286
 
        except errors.ShortReadvError, e:
287
 
            return FailedSmartServerResponse(('ShortReadvError',
288
 
                e.path, str(e.offset), str(e.length), str(e.actual)))
289
 
        except errors.UnstackableRepositoryFormat, e:
290
 
            return FailedSmartServerResponse(('UnstackableRepositoryFormat',
291
 
                str(e.format), e.url))
292
 
        except errors.UnstackableBranchFormat, e:
293
 
            return FailedSmartServerResponse(('UnstackableBranchFormat',
294
 
                str(e.format), e.url))
295
 
        except errors.NotStacked, e:
296
 
            return FailedSmartServerResponse(('NotStacked',))
297
 
        except UnicodeError, e:
298
 
            # If it is a DecodeError, than most likely we are starting
299
 
            # with a plain string
300
 
            str_or_unicode = e.object
301
 
            if isinstance(str_or_unicode, unicode):
302
 
                # XXX: UTF-8 might have \x01 (our protocol v1 and v2 seperator
303
 
                # byte) in it, so this encoding could cause broken responses.
304
 
                # Newer clients use protocol v3, so will be fine.
305
 
                val = 'u:' + str_or_unicode.encode('utf-8')
306
 
            else:
307
 
                val = 's:' + str_or_unicode.encode('base64')
308
 
            # This handles UnicodeEncodeError or UnicodeDecodeError
309
 
            return FailedSmartServerResponse((e.__class__.__name__,
310
 
                    e.encoding, val, str(e.start), str(e.end), e.reason))
311
 
        except errors.TransportNotPossible, e:
312
 
            if e.msg == "readonly transport":
313
 
                return FailedSmartServerResponse(('ReadOnlyError', ))
314
 
            else:
315
 
                raise
316
 
        except errors.ReadError, e:
317
 
            # cannot read the file
318
 
            return FailedSmartServerResponse(('ReadError', e.path))
319
 
        except errors.PermissionDenied, e:
320
 
            return FailedSmartServerResponse(
321
 
                ('PermissionDenied', e.path, e.extra))
 
281
        except (KeyboardInterrupt, SystemExit):
 
282
            raise
 
283
        except Exception, err:
 
284
            err_struct = _translate_error(err)
 
285
            return FailedSmartServerResponse(err_struct)
322
286
 
323
287
    def headers_received(self, headers):
324
288
        # Just a no-op at the moment.
342
306
        pass
343
307
 
344
308
 
 
309
def _translate_error(err):
 
310
    if isinstance(err, errors.NoSuchFile):
 
311
        return ('NoSuchFile', err.path)
 
312
    elif isinstance(err, errors.FileExists):
 
313
        return ('FileExists', err.path)
 
314
    elif isinstance(err, errors.DirectoryNotEmpty):
 
315
        return ('DirectoryNotEmpty', err.path)
 
316
    elif isinstance(err, errors.ShortReadvError):
 
317
        return ('ShortReadvError', err.path, str(err.offset), str(err.length),
 
318
                str(err.actual))
 
319
    elif isinstance(err, errors.UnstackableRepositoryFormat):
 
320
        return (('UnstackableRepositoryFormat', str(err.format), err.url))
 
321
    elif isinstance(err, errors.UnstackableBranchFormat):
 
322
        return ('UnstackableBranchFormat', str(err.format), err.url)
 
323
    elif isinstance(err, errors.NotStacked):
 
324
        return ('NotStacked',)
 
325
    elif isinstance(err, UnicodeError):
 
326
        # If it is a DecodeError, than most likely we are starting
 
327
        # with a plain string
 
328
        str_or_unicode = err.object
 
329
        if isinstance(str_or_unicode, unicode):
 
330
            # XXX: UTF-8 might have \x01 (our protocol v1 and v2 seperator
 
331
            # byte) in it, so this encoding could cause broken responses.
 
332
            # Newer clients use protocol v3, so will be fine.
 
333
            val = 'u:' + str_or_unicode.encode('utf-8')
 
334
        else:
 
335
            val = 's:' + str_or_unicode.encode('base64')
 
336
        # This handles UnicodeEncodeError or UnicodeDecodeError
 
337
        return (err.__class__.__name__, err.encoding, val, str(err.start),
 
338
                str(err.end), err.reason)
 
339
    elif isinstance(err, errors.TransportNotPossible):
 
340
        if err.msg == "readonly transport":
 
341
            return ('ReadOnlyError', )
 
342
    elif isinstance(err, errors.ReadError):
 
343
        # cannot read the file
 
344
        return ('ReadError', err.path)
 
345
    elif isinstance(err, errors.PermissionDenied):
 
346
        return ('PermissionDenied', err.path, err.extra)
 
347
    # Unserialisable error.  Log it, and return a generic error
 
348
    trace.log_exception_quietly()
 
349
    return ('error', str(err))
 
350
 
 
351
 
345
352
class HelloRequest(SmartServerRequest):
346
353
    """Answer a version request with the highest protocol version this server
347
354
    supports.
381
388
request_handlers.register_lazy(
382
389
    'append', 'bzrlib.smart.vfs', 'AppendRequest')
383
390
request_handlers.register_lazy(
384
 
    'Branch.get_config_file', 'bzrlib.smart.branch', 'SmartServerBranchGetConfigFile')
 
391
    'Branch.get_config_file', 'bzrlib.smart.branch',
 
392
    'SmartServerBranchGetConfigFile')
 
393
request_handlers.register_lazy(
 
394
    'Branch.get_parent', 'bzrlib.smart.branch', 'SmartServerBranchGetParent')
 
395
request_handlers.register_lazy(
 
396
    'Branch.get_tags_bytes', 'bzrlib.smart.branch',
 
397
    'SmartServerBranchGetTagsBytes')
385
398
request_handlers.register_lazy(
386
399
    'Branch.get_stacked_on_url', 'bzrlib.smart.branch', 'SmartServerBranchRequestGetStackedOnURL')
387
400
request_handlers.register_lazy(
401
414
request_handlers.register_lazy(
402
415
    'Branch.unlock', 'bzrlib.smart.branch', 'SmartServerBranchRequestUnlock')
403
416
request_handlers.register_lazy(
404
 
    'BzrDir.find_repository', 'bzrlib.smart.bzrdir', 'SmartServerRequestFindRepositoryV1')
405
 
request_handlers.register_lazy(
406
 
    'BzrDir.find_repositoryV2', 'bzrlib.smart.bzrdir', 'SmartServerRequestFindRepositoryV2')
407
 
request_handlers.register_lazy(
408
 
    'BzrDirFormat.initialize', 'bzrlib.smart.bzrdir', 'SmartServerRequestInitializeBzrDir')
409
 
request_handlers.register_lazy(
410
 
    'BzrDir.open_branch', 'bzrlib.smart.bzrdir', 'SmartServerRequestOpenBranch')
 
417
    'BzrDir.cloning_metadir', 'bzrlib.smart.bzrdir',
 
418
    'SmartServerBzrDirRequestCloningMetaDir')
 
419
request_handlers.register_lazy(
 
420
    'BzrDir.create_branch', 'bzrlib.smart.bzrdir',
 
421
    'SmartServerRequestCreateBranch')
 
422
request_handlers.register_lazy(
 
423
    'BzrDir.create_repository', 'bzrlib.smart.bzrdir',
 
424
    'SmartServerRequestCreateRepository')
 
425
request_handlers.register_lazy(
 
426
    'BzrDir.find_repository', 'bzrlib.smart.bzrdir',
 
427
    'SmartServerRequestFindRepositoryV1')
 
428
request_handlers.register_lazy(
 
429
    'BzrDir.find_repositoryV2', 'bzrlib.smart.bzrdir',
 
430
    'SmartServerRequestFindRepositoryV2')
 
431
request_handlers.register_lazy(
 
432
    'BzrDir.find_repositoryV3', 'bzrlib.smart.bzrdir',
 
433
    'SmartServerRequestFindRepositoryV3')
 
434
request_handlers.register_lazy(
 
435
    'BzrDirFormat.initialize', 'bzrlib.smart.bzrdir',
 
436
    'SmartServerRequestInitializeBzrDir')
 
437
request_handlers.register_lazy(
 
438
    'BzrDir.open_branch', 'bzrlib.smart.bzrdir',
 
439
    'SmartServerRequestOpenBranch')
 
440
request_handlers.register_lazy(
 
441
    'BzrDir.open_branchV2', 'bzrlib.smart.bzrdir',
 
442
    'SmartServerRequestOpenBranchV2')
411
443
request_handlers.register_lazy(
412
444
    'delete', 'bzrlib.smart.vfs', 'DeleteRequest')
413
445
request_handlers.register_lazy(
448
480
request_handlers.register_lazy(
449
481
    'Repository.has_revision', 'bzrlib.smart.repository', 'SmartServerRequestHasRevision')
450
482
request_handlers.register_lazy(
 
483
    'Repository.insert_stream', 'bzrlib.smart.repository', 'SmartServerRepositoryInsertStream')
 
484
request_handlers.register_lazy(
451
485
    'Repository.is_shared', 'bzrlib.smart.repository', 'SmartServerRepositoryIsShared')
452
486
request_handlers.register_lazy(
453
487
    'Repository.lock_write', 'bzrlib.smart.repository', 'SmartServerRepositoryLockWrite')
454
488
request_handlers.register_lazy(
 
489
    'Repository.set_make_working_trees', 'bzrlib.smart.repository',
 
490
    'SmartServerRepositorySetMakeWorkingTrees')
 
491
request_handlers.register_lazy(
455
492
    'Repository.unlock', 'bzrlib.smart.repository', 'SmartServerRepositoryUnlock')
456
493
request_handlers.register_lazy(
 
494
    'Repository.get_stream', 'bzrlib.smart.repository',
 
495
    'SmartServerRepositoryGetStream')
 
496
request_handlers.register_lazy(
457
497
    'Repository.tarball', 'bzrlib.smart.repository',
458
498
    'SmartServerRepositoryTarball')
459
499
request_handlers.register_lazy(