~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/smart/request.py

  • Committer: Martin Pool
  • Date: 2010-07-16 15:20:17 UTC
  • mfrom: (5346.3.1 pathnotchild)
  • mto: This revision was merged to the branch mainline in revision 5351.
  • Revision ID: mbp@canonical.com-20100716152017-t4c73h9y1uoih7fb
PathNotChild should not give a traceback.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2006, 2007 Canonical Ltd
 
1
# Copyright (C) 2006-2010 Canonical Ltd
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
32
32
 
33
33
 
34
34
import tempfile
 
35
import thread
35
36
import threading
36
37
 
37
38
from bzrlib import (
38
39
    bzrdir,
 
40
    debug,
39
41
    errors,
 
42
    osutils,
40
43
    registry,
41
44
    revision,
42
45
    trace,
69
72
            continue
70
73
        else:
71
74
            return
72
 
    raise errors.BzrError('jail break: %r' % (abspath,))
 
75
    raise errors.JailBreak(abspath)
73
76
 
74
77
 
75
78
_install_hook()
86
89
    # XXX: rename this class to BaseSmartServerRequestHandler ?  A request
87
90
    # *handler* is a different concept to the request.
88
91
 
89
 
    def __init__(self, backing_transport, root_client_path='/'):
 
92
    def __init__(self, backing_transport, root_client_path='/', jail_root=None):
90
93
        """Constructor.
91
94
 
92
95
        :param backing_transport: the base transport to be used when performing
96
99
            from the client.  Clients will not be able to refer to paths above
97
100
            this root.  If root_client_path is None, then no translation will
98
101
            be performed on client paths.  Default is '/'.
 
102
        :param jail_root: if specified, the root of the BzrDir.open jail to use
 
103
            instead of backing_transport.
99
104
        """
100
105
        self._backing_transport = backing_transport
 
106
        if jail_root is None:
 
107
            jail_root = backing_transport
 
108
        self._jail_root = jail_root
101
109
        if root_client_path is not None:
102
110
            if not root_client_path.startswith('/'):
103
111
                root_client_path = '/' + root_client_path
155
163
        return self.do_body(body_bytes)
156
164
 
157
165
    def setup_jail(self):
158
 
        jail_info.transports = [self._backing_transport]
 
166
        jail_info.transports = [self._jail_root]
159
167
 
160
168
    def teardown_jail(self):
161
169
        jail_info.transports = None
176
184
            return client_path
177
185
        if not client_path.startswith('/'):
178
186
            client_path = '/' + client_path
 
187
        if client_path + '/' == self._root_client_path:
 
188
            return '.'
179
189
        if client_path.startswith(self._root_client_path):
180
190
            path = client_path[len(self._root_client_path):]
181
191
            relpath = urlutils.joinpath('/', path)
182
192
            if not relpath.startswith('/'):
183
193
                raise ValueError(relpath)
184
 
            return '.' + relpath
 
194
            return urlutils.escape('.' + relpath)
185
195
        else:
186
196
            raise errors.PathNotChild(client_path, self._root_client_path)
187
197
 
263
273
    # TODO: Better way of representing the body for commands that take it,
264
274
    # and allow it to be streamed into the server.
265
275
 
266
 
    def __init__(self, backing_transport, commands, root_client_path):
 
276
    def __init__(self, backing_transport, commands, root_client_path,
 
277
        jail_root=None):
267
278
        """Constructor.
268
279
 
269
280
        :param backing_transport: a Transport to handle requests for.
273
284
        self._backing_transport = backing_transport
274
285
        self._root_client_path = root_client_path
275
286
        self._commands = commands
 
287
        if jail_root is None:
 
288
            jail_root = backing_transport
 
289
        self._jail_root = jail_root
276
290
        self.response = None
277
291
        self.finished_reading = False
278
292
        self._command = None
 
293
        if 'hpss' in debug.debug_flags:
 
294
            self._request_start_time = osutils.timer_func()
 
295
            self._thread_id = thread.get_ident()
 
296
 
 
297
    def _trace(self, action, message, extra_bytes=None, include_time=False):
 
298
        # It is a bit of a shame that this functionality overlaps with that of 
 
299
        # ProtocolThreeRequester._trace. However, there is enough difference
 
300
        # that just putting it in a helper doesn't help a lot. And some state
 
301
        # is taken from the instance.
 
302
        if include_time:
 
303
            t = '%5.3fs ' % (osutils.timer_func() - self._request_start_time)
 
304
        else:
 
305
            t = ''
 
306
        if extra_bytes is None:
 
307
            extra = ''
 
308
        else:
 
309
            extra = ' ' + repr(extra_bytes[:40])
 
310
            if len(extra) > 33:
 
311
                extra = extra[:29] + extra[-1] + '...'
 
312
        trace.mutter('%12s: [%s] %s%s%s'
 
313
                     % (action, self._thread_id, t, message, extra))
279
314
 
280
315
    def accept_body(self, bytes):
281
316
        """Accept body data."""
 
317
        if self._command is None:
 
318
            # no active command object, so ignore the event.
 
319
            return
282
320
        self._run_handler_code(self._command.do_chunk, (bytes,), {})
 
321
        if 'hpss' in debug.debug_flags:
 
322
            self._trace('accept body',
 
323
                        '%d bytes' % (len(bytes),), bytes)
283
324
 
284
325
    def end_of_body(self):
285
326
        """No more body data will be received."""
286
327
        self._run_handler_code(self._command.do_end, (), {})
287
328
        # cannot read after this.
288
329
        self.finished_reading = True
289
 
 
290
 
    def dispatch_command(self, cmd, args):
291
 
        """Deprecated compatibility method.""" # XXX XXX
292
 
        try:
293
 
            command = self._commands.get(cmd)
294
 
        except LookupError:
295
 
            raise errors.UnknownSmartMethod(cmd)
296
 
        self._command = command(self._backing_transport, self._root_client_path)
297
 
        self._run_handler_code(self._command.execute, args, {})
 
330
        if 'hpss' in debug.debug_flags:
 
331
            self._trace('end of body', '', include_time=True)
298
332
 
299
333
    def _run_handler_code(self, callable, args, kwargs):
300
334
        """Run some handler specific code 'callable'.
329
363
 
330
364
    def headers_received(self, headers):
331
365
        # Just a no-op at the moment.
332
 
        pass
 
366
        if 'hpss' in debug.debug_flags:
 
367
            self._trace('headers', repr(headers))
333
368
 
334
369
    def args_received(self, args):
335
370
        cmd = args[0]
337
372
        try:
338
373
            command = self._commands.get(cmd)
339
374
        except LookupError:
 
375
            if 'hpss' in debug.debug_flags:
 
376
                self._trace('hpss unknown request', 
 
377
                            cmd, repr(args)[1:-1])
340
378
            raise errors.UnknownSmartMethod(cmd)
341
 
        self._command = command(self._backing_transport)
 
379
        if 'hpss' in debug.debug_flags:
 
380
            from bzrlib.smart import vfs
 
381
            if issubclass(command, vfs.VfsRequest):
 
382
                action = 'hpss vfs req'
 
383
            else:
 
384
                action = 'hpss request'
 
385
            self._trace(action, 
 
386
                        '%s %s' % (cmd, repr(args)[1:-1]))
 
387
        self._command = command(
 
388
            self._backing_transport, self._root_client_path, self._jail_root)
342
389
        self._run_handler_code(self._command.execute, args, {})
343
390
 
344
391
    def end_received(self):
 
392
        if self._command is None:
 
393
            # no active command object, so ignore the event.
 
394
            return
345
395
        self._run_handler_code(self._command.do_end, (), {})
 
396
        if 'hpss' in debug.debug_flags:
 
397
            self._trace('end', '', include_time=True)
346
398
 
347
399
    def post_body_error_received(self, error_args):
348
400
        # Just a no-op at the moment.
356
408
        return ('FileExists', err.path)
357
409
    elif isinstance(err, errors.DirectoryNotEmpty):
358
410
        return ('DirectoryNotEmpty', err.path)
 
411
    elif isinstance(err, errors.IncompatibleRepositories):
 
412
        return ('IncompatibleRepositories', str(err.source), str(err.target),
 
413
            str(err.details))
359
414
    elif isinstance(err, errors.ShortReadvError):
360
415
        return ('ShortReadvError', err.path, str(err.offset), str(err.length),
361
416
                str(err.actual))
390
445
    elif isinstance(err, errors.TokenMismatch):
391
446
        return ('TokenMismatch', err.given_token, err.lock_token)
392
447
    elif isinstance(err, errors.LockContention):
393
 
        return ('LockContention', err.lock, err.msg)
 
448
        return ('LockContention',)
394
449
    # Unserialisable error.  Log it, and return a generic error
395
450
    trace.log_exception_quietly()
396
451
    return ('error', str(err))
443
498
    'Branch.get_tags_bytes', 'bzrlib.smart.branch',
444
499
    'SmartServerBranchGetTagsBytes')
445
500
request_handlers.register_lazy(
 
501
    'Branch.set_tags_bytes', 'bzrlib.smart.branch',
 
502
    'SmartServerBranchSetTagsBytes')
 
503
request_handlers.register_lazy(
446
504
    'Branch.get_stacked_on_url', 'bzrlib.smart.branch', 'SmartServerBranchRequestGetStackedOnURL')
447
505
request_handlers.register_lazy(
448
506
    'Branch.last_revision_info', 'bzrlib.smart.branch', 'SmartServerBranchRequestLastRevisionInfo')
449
507
request_handlers.register_lazy(
450
508
    'Branch.lock_write', 'bzrlib.smart.branch', 'SmartServerBranchRequestLockWrite')
451
 
request_handlers.register_lazy(
452
 
    'Branch.revision_history', 'bzrlib.smart.branch', 'SmartServerRequestRevisionHistory')
453
 
request_handlers.register_lazy(
454
 
    'Branch.set_last_revision', 'bzrlib.smart.branch', 'SmartServerBranchRequestSetLastRevision')
 
509
request_handlers.register_lazy( 'Branch.revision_history',
 
510
    'bzrlib.smart.branch', 'SmartServerRequestRevisionHistory')
 
511
request_handlers.register_lazy( 'Branch.set_config_option',
 
512
    'bzrlib.smart.branch', 'SmartServerBranchRequestSetConfigOption')
 
513
request_handlers.register_lazy( 'Branch.set_config_option_dict',
 
514
    'bzrlib.smart.branch', 'SmartServerBranchRequestSetConfigOptionDict')
 
515
request_handlers.register_lazy( 'Branch.set_last_revision',
 
516
    'bzrlib.smart.branch', 'SmartServerBranchRequestSetLastRevision')
455
517
request_handlers.register_lazy(
456
518
    'Branch.set_last_revision_info', 'bzrlib.smart.branch',
457
519
    'SmartServerBranchRequestSetLastRevisionInfo')
459
521
    'Branch.set_last_revision_ex', 'bzrlib.smart.branch',
460
522
    'SmartServerBranchRequestSetLastRevisionEx')
461
523
request_handlers.register_lazy(
 
524
    'Branch.set_parent_location', 'bzrlib.smart.branch',
 
525
    'SmartServerBranchRequestSetParentLocation')
 
526
request_handlers.register_lazy(
462
527
    'Branch.unlock', 'bzrlib.smart.branch', 'SmartServerBranchRequestUnlock')
463
528
request_handlers.register_lazy(
464
529
    'BzrDir.cloning_metadir', 'bzrlib.smart.bzrdir',
479
544
    'BzrDir.find_repositoryV3', 'bzrlib.smart.bzrdir',
480
545
    'SmartServerRequestFindRepositoryV3')
481
546
request_handlers.register_lazy(
 
547
    'BzrDir.get_config_file', 'bzrlib.smart.bzrdir',
 
548
    'SmartServerBzrDirRequestConfigFile')
 
549
request_handlers.register_lazy(
482
550
    'BzrDirFormat.initialize', 'bzrlib.smart.bzrdir',
483
551
    'SmartServerRequestInitializeBzrDir')
484
552
request_handlers.register_lazy(
 
553
    'BzrDirFormat.initialize_ex_1.16', 'bzrlib.smart.bzrdir',
 
554
    'SmartServerRequestBzrDirInitializeEx')
 
555
request_handlers.register_lazy(
 
556
    'BzrDir.open', 'bzrlib.smart.bzrdir', 'SmartServerRequestOpenBzrDir')
 
557
request_handlers.register_lazy(
 
558
    'BzrDir.open_2.1', 'bzrlib.smart.bzrdir', 'SmartServerRequestOpenBzrDir_2_1')
 
559
request_handlers.register_lazy(
485
560
    'BzrDir.open_branch', 'bzrlib.smart.bzrdir',
486
561
    'SmartServerRequestOpenBranch')
487
562
request_handlers.register_lazy(
488
563
    'BzrDir.open_branchV2', 'bzrlib.smart.bzrdir',
489
564
    'SmartServerRequestOpenBranchV2')
490
565
request_handlers.register_lazy(
 
566
    'BzrDir.open_branchV3', 'bzrlib.smart.bzrdir',
 
567
    'SmartServerRequestOpenBranchV3')
 
568
request_handlers.register_lazy(
491
569
    'delete', 'bzrlib.smart.vfs', 'DeleteRequest')
492
570
request_handlers.register_lazy(
493
571
    'get', 'bzrlib.smart.vfs', 'GetRequest')
529
607
request_handlers.register_lazy(
530
608
    'Repository.insert_stream', 'bzrlib.smart.repository', 'SmartServerRepositoryInsertStream')
531
609
request_handlers.register_lazy(
 
610
    'Repository.insert_stream_1.19', 'bzrlib.smart.repository', 'SmartServerRepositoryInsertStream_1_19')
 
611
request_handlers.register_lazy(
532
612
    'Repository.insert_stream_locked', 'bzrlib.smart.repository', 'SmartServerRepositoryInsertStreamLocked')
533
613
request_handlers.register_lazy(
534
614
    'Repository.is_shared', 'bzrlib.smart.repository', 'SmartServerRepositoryIsShared')
540
620
request_handlers.register_lazy(
541
621
    'Repository.unlock', 'bzrlib.smart.repository', 'SmartServerRepositoryUnlock')
542
622
request_handlers.register_lazy(
 
623
    'Repository.get_rev_id_for_revno', 'bzrlib.smart.repository',
 
624
    'SmartServerRepositoryGetRevIdForRevno')
 
625
request_handlers.register_lazy(
543
626
    'Repository.get_stream', 'bzrlib.smart.repository',
544
627
    'SmartServerRepositoryGetStream')
545
628
request_handlers.register_lazy(
 
629
    'Repository.get_stream_1.19', 'bzrlib.smart.repository',
 
630
    'SmartServerRepositoryGetStream_1_19')
 
631
request_handlers.register_lazy(
546
632
    'Repository.tarball', 'bzrlib.smart.repository',
547
633
    'SmartServerRepositoryTarball')
548
634
request_handlers.register_lazy(
551
637
    'stat', 'bzrlib.smart.vfs', 'StatRequest')
552
638
request_handlers.register_lazy(
553
639
    'Transport.is_readonly', 'bzrlib.smart.request', 'SmartServerIsReadonly')
554
 
request_handlers.register_lazy(
555
 
    'BzrDir.open', 'bzrlib.smart.bzrdir', 'SmartServerRequestOpenBzrDir')