~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/smart/request.py

  • Committer: John Arbash Meinel
  • Date: 2008-03-04 14:25:46 UTC
  • mto: This revision was merged to the branch mainline in revision 3279.
  • Revision ID: john@arbash-meinel.com-20080304142546-zuwwy0o9roo14928
Implement cherrypick support for Merge3
When merging a cherrypick, use a slightly different resolve logic.
When encountering a conflict, the new logic does not include lines that
were present in BASE that are conflicting with OTHER.
This is done since a cherrypick is (by definition) avoiding changes that
are present in the base.
(related to bug #151731)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2006-2011 Canonical Ltd
 
1
# Copyright (C) 2006, 2007 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
12
12
#
13
13
# You should have received a copy of the GNU General Public License
14
14
# along with this program; if not, write to the Free Software
15
 
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
 
 
17
 
"""Infrastructure for server-side request handlers.
18
 
 
19
 
Interesting module attributes:
20
 
    * The request_handlers registry maps verb names to SmartServerRequest
21
 
      classes.
22
 
    * The jail_info threading.local() object is used to prevent accidental
23
 
      opening of BzrDirs outside of the backing transport, or any other
24
 
      transports placed in jail_info.transports.  The jail_info is reset on
25
 
      every call into a request handler (which can happen an arbitrary number
26
 
      of times during a request).
27
 
"""
28
 
 
29
 
from __future__ import absolute_import
30
 
 
31
 
# XXX: The class names are a little confusing: the protocol will instantiate a
32
 
# SmartServerRequestHandler, whose dispatch_command method creates an instance
33
 
# of a SmartServerRequest subclass.
34
 
 
35
 
 
36
 
import threading
 
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
16
 
 
17
"""Basic server-side logic for dealing with requests."""
 
18
 
 
19
 
 
20
import tempfile
37
21
 
38
22
from bzrlib import (
39
 
    debug,
 
23
    bzrdir,
40
24
    errors,
41
 
    osutils,
42
25
    registry,
43
26
    revision,
44
 
    trace,
45
 
    urlutils,
46
27
    )
47
 
from bzrlib.lazy_import import lazy_import
48
 
lazy_import(globals(), """
49
 
from bzrlib import bzrdir
50
 
from bzrlib.bundle import serializer
51
 
 
52
 
import tempfile
53
 
import thread
54
 
""")
55
 
 
56
 
 
57
 
jail_info = threading.local()
58
 
jail_info.transports = None
59
 
 
60
 
 
61
 
def _install_hook():
62
 
    bzrdir.BzrDir.hooks.install_named_hook(
63
 
        'pre_open', _pre_open_hook, 'checking server jail')
64
 
 
65
 
 
66
 
def _pre_open_hook(transport):
67
 
    allowed_transports = getattr(jail_info, 'transports', None)
68
 
    if allowed_transports is None:
69
 
        return
70
 
    abspath = transport.base
71
 
    for allowed_transport in allowed_transports:
72
 
        try:
73
 
            allowed_transport.relpath(abspath)
74
 
        except errors.PathNotChild:
75
 
            continue
76
 
        else:
77
 
            return
78
 
    raise errors.JailBreak(abspath)
79
 
 
80
 
 
81
 
_install_hook()
 
28
from bzrlib.bundle.serializer import write_bundle
82
29
 
83
30
 
84
31
class SmartServerRequest(object):
85
 
    """Base class for request handlers.
86
 
 
87
 
    To define a new request, subclass this class and override the `do` method
88
 
    (and if appropriate, `do_body` as well).  Request implementors should take
89
 
    care to call `translate_client_path` and `transport_from_client_path` as
90
 
    appropriate when dealing with paths received from the client.
91
 
    """
92
 
    # XXX: rename this class to BaseSmartServerRequestHandler ?  A request
93
 
    # *handler* is a different concept to the request.
94
 
 
95
 
    def __init__(self, backing_transport, root_client_path='/', jail_root=None):
 
32
    """Base class for request handlers."""
 
33
 
 
34
    def __init__(self, backing_transport):
96
35
        """Constructor.
97
36
 
98
37
        :param backing_transport: the base transport to be used when performing
99
38
            this request.
100
 
        :param root_client_path: the client path that maps to the root of
101
 
            backing_transport.  This is used to interpret relpaths received
102
 
            from the client.  Clients will not be able to refer to paths above
103
 
            this root.  If root_client_path is None, then no translation will
104
 
            be performed on client paths.  Default is '/'.
105
 
        :param jail_root: if specified, the root of the BzrDir.open jail to use
106
 
            instead of backing_transport.
107
39
        """
108
40
        self._backing_transport = backing_transport
109
 
        if jail_root is None:
110
 
            jail_root = backing_transport
111
 
        self._jail_root = jail_root
112
 
        if root_client_path is not None:
113
 
            if not root_client_path.startswith('/'):
114
 
                root_client_path = '/' + root_client_path
115
 
            if not root_client_path.endswith('/'):
116
 
                root_client_path += '/'
117
 
        self._root_client_path = root_client_path
118
 
        self._body_chunks = []
119
41
 
120
42
    def _check_enabled(self):
121
43
        """Raises DisabledMethod if this method is disabled."""
123
45
 
124
46
    def do(self, *args):
125
47
        """Mandatory extension point for SmartServerRequest subclasses.
126
 
 
 
48
        
127
49
        Subclasses must implement this.
128
 
 
 
50
        
129
51
        This should return a SmartServerResponse if this command expects to
130
52
        receive no body.
131
53
        """
137
59
        It will return a SmartServerResponse if the command does not expect a
138
60
        body.
139
61
 
140
 
        :param args: the arguments of the request.
 
62
        :param *args: the arguments of the request.
141
63
        """
142
64
        self._check_enabled()
143
65
        return self.do(*args)
146
68
        """Called if the client sends a body with the request.
147
69
 
148
70
        The do() method is still called, and must have returned None.
149
 
 
 
71
        
150
72
        Must return a SmartServerResponse.
151
73
        """
152
 
        if body_bytes != '':
153
 
            raise errors.SmartProtocolError('Request does not expect a body')
154
 
 
155
 
    def do_chunk(self, chunk_bytes):
156
 
        """Called with each body chunk if the request has a streamed body.
157
 
 
158
 
        The do() method is still called, and must have returned None.
159
 
        """
160
 
        self._body_chunks.append(chunk_bytes)
161
 
 
162
 
    def do_end(self):
163
 
        """Called when the end of the request has been received."""
164
 
        body_bytes = ''.join(self._body_chunks)
165
 
        self._body_chunks = None
166
 
        return self.do_body(body_bytes)
167
 
 
168
 
    def setup_jail(self):
169
 
        jail_info.transports = [self._jail_root]
170
 
 
171
 
    def teardown_jail(self):
172
 
        jail_info.transports = None
173
 
 
174
 
    def translate_client_path(self, client_path):
175
 
        """Translate a path received from a network client into a local
176
 
        relpath.
177
 
 
178
 
        All paths received from the client *must* be translated.
179
 
 
180
 
        :param client_path: the path from the client.
181
 
        :returns: a relpath that may be used with self._backing_transport
182
 
            (unlike the untranslated client_path, which must not be used with
183
 
            the backing transport).
184
 
        """
185
 
        if self._root_client_path is None:
186
 
            # no translation necessary!
187
 
            return client_path
188
 
        if not client_path.startswith('/'):
189
 
            client_path = '/' + client_path
190
 
        if client_path + '/' == self._root_client_path:
191
 
            return '.'
192
 
        if client_path.startswith(self._root_client_path):
193
 
            path = client_path[len(self._root_client_path):]
194
 
            relpath = urlutils.joinpath('/', path)
195
 
            if not relpath.startswith('/'):
196
 
                raise ValueError(relpath)
197
 
            return urlutils.escape('.' + relpath)
198
 
        else:
199
 
            raise errors.PathNotChild(client_path, self._root_client_path)
200
 
 
201
 
    def transport_from_client_path(self, client_path):
202
 
        """Get a backing transport corresponding to the location referred to by
203
 
        a network client.
204
 
 
205
 
        :seealso: translate_client_path
206
 
        :returns: a transport cloned from self._backing_transport
207
 
        """
208
 
        relpath = self.translate_client_path(client_path)
209
 
        return self._backing_transport.clone(relpath)
 
74
        # TODO: if a client erroneously sends a request that shouldn't have a
 
75
        # body, what to do?  Probably SmartServerRequestHandler should catch
 
76
        # this NotImplementedError and translate it into a 'bad request' error
 
77
        # to send to the client.
 
78
        raise NotImplementedError(self.do_body)
210
79
 
211
80
 
212
81
class SmartServerResponse(object):
213
82
    """A response to a client request.
214
 
 
 
83
    
215
84
    This base class should not be used. Instead use
216
85
    SuccessfulSmartServerResponse and FailedSmartServerResponse as appropriate.
217
86
    """
239
108
                other.body_stream is self.body_stream)
240
109
 
241
110
    def __repr__(self):
242
 
        return "<%s args=%r body=%r>" % (self.__class__.__name__,
243
 
            self.args, self.body)
 
111
        return ("<SmartServerResponse successful=%s args=%r body=%r>"
 
112
                % (self.is_successful(), self.args, self.body))
244
113
 
245
114
 
246
115
class FailedSmartServerResponse(SmartServerResponse):
261
130
 
262
131
class SmartServerRequestHandler(object):
263
132
    """Protocol logic for smart server.
264
 
 
 
133
    
265
134
    This doesn't handle serialization at all, it just processes requests and
266
135
    creates responses.
267
136
    """
276
145
    # TODO: Better way of representing the body for commands that take it,
277
146
    # and allow it to be streamed into the server.
278
147
 
279
 
    def __init__(self, backing_transport, commands, root_client_path,
280
 
        jail_root=None):
 
148
    def __init__(self, backing_transport, commands):
281
149
        """Constructor.
282
150
 
283
151
        :param backing_transport: a Transport to handle requests for.
285
153
            subclasses. e.g. bzrlib.transport.smart.vfs.vfs_commands.
286
154
        """
287
155
        self._backing_transport = backing_transport
288
 
        self._root_client_path = root_client_path
289
156
        self._commands = commands
290
 
        if jail_root is None:
291
 
            jail_root = backing_transport
292
 
        self._jail_root = jail_root
 
157
        self._body_bytes = ''
293
158
        self.response = None
294
159
        self.finished_reading = False
295
160
        self._command = None
296
 
        if 'hpss' in debug.debug_flags:
297
 
            self._request_start_time = osutils.timer_func()
298
 
            self._thread_id = thread.get_ident()
299
 
 
300
 
    def _trace(self, action, message, extra_bytes=None, include_time=False):
301
 
        # It is a bit of a shame that this functionality overlaps with that of 
302
 
        # ProtocolThreeRequester._trace. However, there is enough difference
303
 
        # that just putting it in a helper doesn't help a lot. And some state
304
 
        # is taken from the instance.
305
 
        if include_time:
306
 
            t = '%5.3fs ' % (osutils.timer_func() - self._request_start_time)
307
 
        else:
308
 
            t = ''
309
 
        if extra_bytes is None:
310
 
            extra = ''
311
 
        else:
312
 
            extra = ' ' + repr(extra_bytes[:40])
313
 
            if len(extra) > 33:
314
 
                extra = extra[:29] + extra[-1] + '...'
315
 
        trace.mutter('%12s: [%s] %s%s%s'
316
 
                     % (action, self._thread_id, t, message, extra))
317
161
 
318
162
    def accept_body(self, bytes):
319
163
        """Accept body data."""
320
 
        if self._command is None:
321
 
            # no active command object, so ignore the event.
322
 
            return
323
 
        self._run_handler_code(self._command.do_chunk, (bytes,), {})
324
 
        if 'hpss' in debug.debug_flags:
325
 
            self._trace('accept body',
326
 
                        '%d bytes' % (len(bytes),), bytes)
327
 
 
 
164
 
 
165
        # TODO: This should be overriden for each command that desired body data
 
166
        # to handle the right format of that data, i.e. plain bytes, a bundle,
 
167
        # etc.  The deserialisation into that format should be done in the
 
168
        # Protocol object.
 
169
 
 
170
        # default fallback is to accumulate bytes.
 
171
        self._body_bytes += bytes
 
172
        
328
173
    def end_of_body(self):
329
174
        """No more body data will be received."""
330
 
        self._run_handler_code(self._command.do_end, (), {})
 
175
        self._run_handler_code(self._command.do_body, (self._body_bytes,), {})
331
176
        # cannot read after this.
332
177
        self.finished_reading = True
333
 
        if 'hpss' in debug.debug_flags:
334
 
            self._trace('end of body', '', include_time=True)
 
178
 
 
179
    def dispatch_command(self, cmd, args):
 
180
        """Deprecated compatibility method.""" # XXX XXX
 
181
        try:
 
182
            command = self._commands.get(cmd)
 
183
        except LookupError:
 
184
            raise errors.SmartProtocolError("bad request %r" % (cmd,))
 
185
        self._command = command(self._backing_transport)
 
186
        self._run_handler_code(self._command.execute, args, {})
335
187
 
336
188
    def _run_handler_code(self, callable, args, kwargs):
337
189
        """Run some handler specific code 'callable'.
353
205
        # XXX: most of this error conversion is VFS-related, and thus ought to
354
206
        # be in SmartServerVFSRequestHandler somewhere.
355
207
        try:
356
 
            self._command.setup_jail()
357
 
            try:
358
 
                return callable(*args, **kwargs)
359
 
            finally:
360
 
                self._command.teardown_jail()
361
 
        except (KeyboardInterrupt, SystemExit):
362
 
            raise
363
 
        except Exception, err:
364
 
            err_struct = _translate_error(err)
365
 
            return FailedSmartServerResponse(err_struct)
366
 
 
367
 
    def headers_received(self, headers):
368
 
        # Just a no-op at the moment.
369
 
        if 'hpss' in debug.debug_flags:
370
 
            self._trace('headers', repr(headers))
371
 
 
372
 
    def args_received(self, args):
373
 
        cmd = args[0]
374
 
        args = args[1:]
375
 
        try:
376
 
            command = self._commands.get(cmd)
377
 
        except LookupError:
378
 
            if 'hpss' in debug.debug_flags:
379
 
                self._trace('hpss unknown request', 
380
 
                            cmd, repr(args)[1:-1])
381
 
            raise errors.UnknownSmartMethod(cmd)
382
 
        if 'hpss' in debug.debug_flags:
383
 
            from bzrlib.smart import vfs
384
 
            if issubclass(command, vfs.VfsRequest):
385
 
                action = 'hpss vfs req'
386
 
            else:
387
 
                action = 'hpss request'
388
 
            self._trace(action, 
389
 
                        '%s %s' % (cmd, repr(args)[1:-1]))
390
 
        self._command = command(
391
 
            self._backing_transport, self._root_client_path, self._jail_root)
392
 
        self._run_handler_code(self._command.execute, args, {})
393
 
 
394
 
    def end_received(self):
395
 
        if self._command is None:
396
 
            # no active command object, so ignore the event.
397
 
            return
398
 
        self._run_handler_code(self._command.do_end, (), {})
399
 
        if 'hpss' in debug.debug_flags:
400
 
            self._trace('end', '', include_time=True)
401
 
 
402
 
    def post_body_error_received(self, error_args):
403
 
        # Just a no-op at the moment.
404
 
        pass
405
 
 
406
 
 
407
 
def _translate_error(err):
408
 
    if isinstance(err, errors.NoSuchFile):
409
 
        return ('NoSuchFile', err.path)
410
 
    elif isinstance(err, errors.FileExists):
411
 
        return ('FileExists', err.path)
412
 
    elif isinstance(err, errors.DirectoryNotEmpty):
413
 
        return ('DirectoryNotEmpty', err.path)
414
 
    elif isinstance(err, errors.IncompatibleRepositories):
415
 
        return ('IncompatibleRepositories', str(err.source), str(err.target),
416
 
            str(err.details))
417
 
    elif isinstance(err, errors.ShortReadvError):
418
 
        return ('ShortReadvError', err.path, str(err.offset), str(err.length),
419
 
                str(err.actual))
420
 
    elif isinstance(err, errors.RevisionNotPresent):
421
 
        return ('RevisionNotPresent', err.revision_id, err.file_id)
422
 
    elif isinstance(err, errors.UnstackableRepositoryFormat):
423
 
        return (('UnstackableRepositoryFormat', str(err.format), err.url))
424
 
    elif isinstance(err, errors.UnstackableBranchFormat):
425
 
        return ('UnstackableBranchFormat', str(err.format), err.url)
426
 
    elif isinstance(err, errors.NotStacked):
427
 
        return ('NotStacked',)
428
 
    elif isinstance(err, errors.BzrCheckError):
429
 
        return ('BzrCheckError', err.msg)
430
 
    elif isinstance(err, UnicodeError):
431
 
        # If it is a DecodeError, than most likely we are starting
432
 
        # with a plain string
433
 
        str_or_unicode = err.object
434
 
        if isinstance(str_or_unicode, unicode):
435
 
            # XXX: UTF-8 might have \x01 (our protocol v1 and v2 seperator
436
 
            # byte) in it, so this encoding could cause broken responses.
437
 
            # Newer clients use protocol v3, so will be fine.
438
 
            val = 'u:' + str_or_unicode.encode('utf-8')
439
 
        else:
440
 
            val = 's:' + str_or_unicode.encode('base64')
441
 
        # This handles UnicodeEncodeError or UnicodeDecodeError
442
 
        return (err.__class__.__name__, err.encoding, val, str(err.start),
443
 
                str(err.end), err.reason)
444
 
    elif isinstance(err, errors.TransportNotPossible):
445
 
        if err.msg == "readonly transport":
446
 
            return ('ReadOnlyError', )
447
 
    elif isinstance(err, errors.ReadError):
448
 
        # cannot read the file
449
 
        return ('ReadError', err.path)
450
 
    elif isinstance(err, errors.PermissionDenied):
451
 
        return ('PermissionDenied', err.path, err.extra)
452
 
    elif isinstance(err, errors.TokenMismatch):
453
 
        return ('TokenMismatch', err.given_token, err.lock_token)
454
 
    elif isinstance(err, errors.LockContention):
455
 
        return ('LockContention',)
456
 
    elif isinstance(err, MemoryError):
457
 
        # GZ 2011-02-24: Copy bzrlib.trace -Dmem_dump functionality here?
458
 
        return ('MemoryError',)
459
 
    # Unserialisable error.  Log it, and return a generic error
460
 
    trace.log_exception_quietly()
461
 
    return ('error', trace._qualified_exception_name(err.__class__, True),
462
 
        str(err))
 
208
            return callable(*args, **kwargs)
 
209
        except errors.NoSuchFile, e:
 
210
            return FailedSmartServerResponse(('NoSuchFile', e.path))
 
211
        except errors.FileExists, e:
 
212
            return FailedSmartServerResponse(('FileExists', e.path))
 
213
        except errors.DirectoryNotEmpty, e:
 
214
            return FailedSmartServerResponse(('DirectoryNotEmpty', e.path))
 
215
        except errors.ShortReadvError, e:
 
216
            return FailedSmartServerResponse(('ShortReadvError',
 
217
                e.path, str(e.offset), str(e.length), str(e.actual)))
 
218
        except UnicodeError, e:
 
219
            # If it is a DecodeError, than most likely we are starting
 
220
            # with a plain string
 
221
            str_or_unicode = e.object
 
222
            if isinstance(str_or_unicode, unicode):
 
223
                # XXX: UTF-8 might have \x01 (our seperator byte) in it.  We
 
224
                # should escape it somehow.
 
225
                val = 'u:' + str_or_unicode.encode('utf-8')
 
226
            else:
 
227
                val = 's:' + str_or_unicode.encode('base64')
 
228
            # This handles UnicodeEncodeError or UnicodeDecodeError
 
229
            return FailedSmartServerResponse((e.__class__.__name__,
 
230
                    e.encoding, val, str(e.start), str(e.end), e.reason))
 
231
        except errors.TransportNotPossible, e:
 
232
            if e.msg == "readonly transport":
 
233
                return FailedSmartServerResponse(('ReadOnlyError', ))
 
234
            else:
 
235
                raise
463
236
 
464
237
 
465
238
class HelloRequest(SmartServerRequest):
476
249
 
477
250
    def do(self, path, revision_id):
478
251
        # open transport relative to our base
479
 
        t = self.transport_from_client_path(path)
 
252
        t = self._backing_transport.clone(path)
480
253
        control, extra_path = bzrdir.BzrDir.open_containing_from_transport(t)
481
254
        repo = control.open_repository()
482
255
        tmpf = tempfile.TemporaryFile()
483
256
        base_revision = revision.NULL_REVISION
484
 
        serializer.write_bundle(repo, revision_id, base_revision, tmpf)
 
257
        write_bundle(repo, revision_id, base_revision, tmpf)
485
258
        tmpf.seek(0)
486
259
        return SuccessfulSmartServerResponse((), tmpf.read())
487
260
 
497
270
        return SuccessfulSmartServerResponse((answer,))
498
271
 
499
272
 
500
 
# In the 'info' attribute, we store whether this request is 'safe' to retry if
501
 
# we get a disconnect while reading the response. It can have the values:
502
 
#   read    This is purely a read request, so retrying it is perfectly ok.
503
 
#   idem    An idempotent write request. Something like 'put' where if you put
504
 
#           the same bytes twice you end up with the same final bytes.
505
 
#   semi    This is a request that isn't strictly idempotent, but doesn't
506
 
#           result in corruption if it is retried. This is for things like
507
 
#           'lock' and 'unlock'. If you call lock, it updates the disk
508
 
#           structure. If you fail to read the response, you won't be able to
509
 
#           use the lock, because you don't have the lock token. Calling lock
510
 
#           again will fail, because the lock is already taken. However, we
511
 
#           can't tell if the server received our request or not. If it didn't,
512
 
#           then retrying the request is fine, as it will actually do what we
513
 
#           want. If it did, we will interrupt the current operation, but we
514
 
#           are no worse off than interrupting the current operation because of
515
 
#           a ConnectionReset.
516
 
#   semivfs Similar to semi, but specific to a Virtual FileSystem request.
517
 
#   stream  This is a request that takes a stream that cannot be restarted if
518
 
#           consumed. This request is 'safe' in that if we determine the
519
 
#           connection is closed before we consume the stream, we can try
520
 
#           again.
521
 
#   mutate  State is updated in a way that replaying that request results in a
522
 
#           different state. For example 'append' writes more bytes to a given
523
 
#           file. If append succeeds, it moves the file pointer.
524
273
request_handlers = registry.Registry()
525
274
request_handlers.register_lazy(
526
 
    'append', 'bzrlib.smart.vfs', 'AppendRequest', info='mutate')
527
 
request_handlers.register_lazy(
528
 
    'Branch.break_lock', 'bzrlib.smart.branch',
529
 
    'SmartServerBranchBreakLock', info='idem')
530
 
request_handlers.register_lazy(
531
 
    'Branch.get_config_file', 'bzrlib.smart.branch',
532
 
    'SmartServerBranchGetConfigFile', info='read')
533
 
request_handlers.register_lazy(
534
 
    'Branch.get_parent', 'bzrlib.smart.branch', 'SmartServerBranchGetParent',
535
 
    info='read')
536
 
request_handlers.register_lazy(
537
 
    'Branch.put_config_file', 'bzrlib.smart.branch',
538
 
    'SmartServerBranchPutConfigFile', info='idem')
539
 
request_handlers.register_lazy(
540
 
    'Branch.get_tags_bytes', 'bzrlib.smart.branch',
541
 
    'SmartServerBranchGetTagsBytes', info='read')
542
 
request_handlers.register_lazy(
543
 
    'Branch.set_tags_bytes', 'bzrlib.smart.branch',
544
 
    'SmartServerBranchSetTagsBytes', info='idem')
545
 
request_handlers.register_lazy(
546
 
    'Branch.heads_to_fetch', 'bzrlib.smart.branch',
547
 
    'SmartServerBranchHeadsToFetch', info='read')
548
 
request_handlers.register_lazy(
549
 
    'Branch.get_stacked_on_url', 'bzrlib.smart.branch',
550
 
    'SmartServerBranchRequestGetStackedOnURL', info='read')
551
 
request_handlers.register_lazy(
552
 
    'Branch.get_physical_lock_status', 'bzrlib.smart.branch',
553
 
    'SmartServerBranchRequestGetPhysicalLockStatus', info='read')
554
 
request_handlers.register_lazy(
555
 
    'Branch.last_revision_info', 'bzrlib.smart.branch',
556
 
    'SmartServerBranchRequestLastRevisionInfo', info='read')
557
 
request_handlers.register_lazy(
558
 
    'Branch.lock_write', 'bzrlib.smart.branch',
559
 
    'SmartServerBranchRequestLockWrite', info='semi')
560
 
request_handlers.register_lazy(
561
 
    'Branch.revision_history', 'bzrlib.smart.branch',
562
 
    'SmartServerRequestRevisionHistory', info='read')
563
 
request_handlers.register_lazy(
564
 
    'Branch.set_config_option', 'bzrlib.smart.branch',
565
 
    'SmartServerBranchRequestSetConfigOption', info='idem')
566
 
request_handlers.register_lazy(
567
 
    'Branch.set_config_option_dict', 'bzrlib.smart.branch',
568
 
    'SmartServerBranchRequestSetConfigOptionDict', info='idem')
569
 
request_handlers.register_lazy(
570
 
    'Branch.set_last_revision', 'bzrlib.smart.branch',
571
 
    'SmartServerBranchRequestSetLastRevision', info='idem')
572
 
request_handlers.register_lazy(
573
 
    'Branch.set_last_revision_info', 'bzrlib.smart.branch',
574
 
    'SmartServerBranchRequestSetLastRevisionInfo', info='idem')
575
 
request_handlers.register_lazy(
576
 
    'Branch.set_last_revision_ex', 'bzrlib.smart.branch',
577
 
    'SmartServerBranchRequestSetLastRevisionEx', info='idem')
578
 
request_handlers.register_lazy(
579
 
    'Branch.set_parent_location', 'bzrlib.smart.branch',
580
 
    'SmartServerBranchRequestSetParentLocation', info='idem')
581
 
request_handlers.register_lazy(
582
 
    'Branch.unlock', 'bzrlib.smart.branch',
583
 
    'SmartServerBranchRequestUnlock', info='semi')
584
 
request_handlers.register_lazy(
585
 
    'Branch.revision_id_to_revno', 'bzrlib.smart.branch',
586
 
    'SmartServerBranchRequestRevisionIdToRevno', info='read')
587
 
request_handlers.register_lazy(
588
 
    'BzrDir.checkout_metadir', 'bzrlib.smart.bzrdir',
589
 
    'SmartServerBzrDirRequestCheckoutMetaDir', info='read')
590
 
request_handlers.register_lazy(
591
 
    'BzrDir.cloning_metadir', 'bzrlib.smart.bzrdir',
592
 
    'SmartServerBzrDirRequestCloningMetaDir', info='read')
593
 
request_handlers.register_lazy(
594
 
    'BzrDir.create_branch', 'bzrlib.smart.bzrdir',
595
 
    'SmartServerRequestCreateBranch', info='semi')
596
 
request_handlers.register_lazy(
597
 
    'BzrDir.create_repository', 'bzrlib.smart.bzrdir',
598
 
    'SmartServerRequestCreateRepository', info='semi')
599
 
request_handlers.register_lazy(
600
 
    'BzrDir.find_repository', 'bzrlib.smart.bzrdir',
601
 
    'SmartServerRequestFindRepositoryV1', info='read')
602
 
request_handlers.register_lazy(
603
 
    'BzrDir.find_repositoryV2', 'bzrlib.smart.bzrdir',
604
 
    'SmartServerRequestFindRepositoryV2', info='read')
605
 
request_handlers.register_lazy(
606
 
    'BzrDir.find_repositoryV3', 'bzrlib.smart.bzrdir',
607
 
    'SmartServerRequestFindRepositoryV3', info='read')
608
 
request_handlers.register_lazy(
609
 
    'BzrDir.get_branches', 'bzrlib.smart.bzrdir',
610
 
    'SmartServerBzrDirRequestGetBranches', info='read')
611
 
request_handlers.register_lazy(
612
 
    'BzrDir.get_config_file', 'bzrlib.smart.bzrdir',
613
 
    'SmartServerBzrDirRequestConfigFile', info='read')
614
 
request_handlers.register_lazy(
615
 
    'BzrDir.destroy_branch', 'bzrlib.smart.bzrdir',
616
 
    'SmartServerBzrDirRequestDestroyBranch', info='semi')
617
 
request_handlers.register_lazy(
618
 
    'BzrDir.destroy_repository', 'bzrlib.smart.bzrdir',
619
 
    'SmartServerBzrDirRequestDestroyRepository', info='semi')
620
 
request_handlers.register_lazy(
621
 
    'BzrDir.has_workingtree', 'bzrlib.smart.bzrdir',
622
 
    'SmartServerBzrDirRequestHasWorkingTree', info='read')
623
 
request_handlers.register_lazy(
624
 
    'BzrDirFormat.initialize', 'bzrlib.smart.bzrdir',
625
 
    'SmartServerRequestInitializeBzrDir', info='semi')
626
 
request_handlers.register_lazy(
627
 
    'BzrDirFormat.initialize_ex_1.16', 'bzrlib.smart.bzrdir',
628
 
    'SmartServerRequestBzrDirInitializeEx', info='semi')
629
 
request_handlers.register_lazy(
630
 
    'BzrDir.open', 'bzrlib.smart.bzrdir', 'SmartServerRequestOpenBzrDir',
631
 
    info='read')
632
 
request_handlers.register_lazy(
633
 
    'BzrDir.open_2.1', 'bzrlib.smart.bzrdir',
634
 
    'SmartServerRequestOpenBzrDir_2_1', info='read')
635
 
request_handlers.register_lazy(
636
 
    'BzrDir.open_branch', 'bzrlib.smart.bzrdir',
637
 
    'SmartServerRequestOpenBranch', info='read')
638
 
request_handlers.register_lazy(
639
 
    'BzrDir.open_branchV2', 'bzrlib.smart.bzrdir',
640
 
    'SmartServerRequestOpenBranchV2', info='read')
641
 
request_handlers.register_lazy(
642
 
    'BzrDir.open_branchV3', 'bzrlib.smart.bzrdir',
643
 
    'SmartServerRequestOpenBranchV3', info='read')
644
 
request_handlers.register_lazy(
645
 
    'delete', 'bzrlib.smart.vfs', 'DeleteRequest', info='semivfs')
646
 
request_handlers.register_lazy(
647
 
    'get', 'bzrlib.smart.vfs', 'GetRequest', info='read')
648
 
request_handlers.register_lazy(
649
 
    'get_bundle', 'bzrlib.smart.request', 'GetBundleRequest', info='read')
650
 
request_handlers.register_lazy(
651
 
    'has', 'bzrlib.smart.vfs', 'HasRequest', info='read')
652
 
request_handlers.register_lazy(
653
 
    'hello', 'bzrlib.smart.request', 'HelloRequest', info='read')
654
 
request_handlers.register_lazy(
655
 
    'iter_files_recursive', 'bzrlib.smart.vfs', 'IterFilesRecursiveRequest',
656
 
    info='read')
657
 
request_handlers.register_lazy(
658
 
    'list_dir', 'bzrlib.smart.vfs', 'ListDirRequest', info='read')
659
 
request_handlers.register_lazy(
660
 
    'mkdir', 'bzrlib.smart.vfs', 'MkdirRequest', info='semivfs')
661
 
request_handlers.register_lazy(
662
 
    'move', 'bzrlib.smart.vfs', 'MoveRequest', info='semivfs')
663
 
request_handlers.register_lazy(
664
 
    'put', 'bzrlib.smart.vfs', 'PutRequest', info='idem')
665
 
request_handlers.register_lazy(
666
 
    'put_non_atomic', 'bzrlib.smart.vfs', 'PutNonAtomicRequest', info='idem')
667
 
request_handlers.register_lazy(
668
 
    'readv', 'bzrlib.smart.vfs', 'ReadvRequest', info='read')
669
 
request_handlers.register_lazy(
670
 
    'rename', 'bzrlib.smart.vfs', 'RenameRequest', info='semivfs')
671
 
request_handlers.register_lazy(
672
 
    'Repository.add_signature_text', 'bzrlib.smart.repository',
673
 
    'SmartServerRepositoryAddSignatureText', info='idem')
674
 
request_handlers.register_lazy(
675
 
    'Repository.all_revision_ids', 'bzrlib.smart.repository',
676
 
    'SmartServerRepositoryAllRevisionIds', info='read')
677
 
request_handlers.register_lazy(
678
 
    'PackRepository.autopack', 'bzrlib.smart.packrepository',
679
 
    'SmartServerPackRepositoryAutopack', info='idem')
680
 
request_handlers.register_lazy(
681
 
    'Repository.break_lock', 'bzrlib.smart.repository',
682
 
    'SmartServerRepositoryBreakLock', info='idem')
683
 
request_handlers.register_lazy(
684
 
    'Repository.gather_stats', 'bzrlib.smart.repository',
685
 
    'SmartServerRepositoryGatherStats', info='read')
686
 
request_handlers.register_lazy(
687
 
    'Repository.get_parent_map', 'bzrlib.smart.repository',
688
 
    'SmartServerRepositoryGetParentMap', info='read')
689
 
request_handlers.register_lazy(
690
 
    'Repository.get_revision_graph', 'bzrlib.smart.repository',
691
 
    'SmartServerRepositoryGetRevisionGraph', info='read')
692
 
request_handlers.register_lazy(
693
 
    'Repository.get_revision_signature_text', 'bzrlib.smart.repository',
694
 
    'SmartServerRepositoryGetRevisionSignatureText', info='read')
695
 
request_handlers.register_lazy(
696
 
    'Repository.has_revision', 'bzrlib.smart.repository',
697
 
    'SmartServerRequestHasRevision', info='read')
698
 
request_handlers.register_lazy(
699
 
    'Repository.has_signature_for_revision_id', 'bzrlib.smart.repository',
700
 
    'SmartServerRequestHasSignatureForRevisionId', info='read')
701
 
request_handlers.register_lazy(
702
 
    'Repository.insert_stream', 'bzrlib.smart.repository',
703
 
    'SmartServerRepositoryInsertStream', info='stream')
704
 
request_handlers.register_lazy(
705
 
    'Repository.insert_stream_1.19', 'bzrlib.smart.repository',
706
 
    'SmartServerRepositoryInsertStream_1_19', info='stream')
707
 
request_handlers.register_lazy(
708
 
    'Repository.insert_stream_locked', 'bzrlib.smart.repository',
709
 
    'SmartServerRepositoryInsertStreamLocked', info='stream')
710
 
request_handlers.register_lazy(
711
 
    'Repository.is_shared', 'bzrlib.smart.repository',
712
 
    'SmartServerRepositoryIsShared', info='read')
713
 
request_handlers.register_lazy(
714
 
    'Repository.iter_files_bytes', 'bzrlib.smart.repository',
715
 
    'SmartServerRepositoryIterFilesBytes', info='read')
716
 
request_handlers.register_lazy(
717
 
    'Repository.lock_write', 'bzrlib.smart.repository',
718
 
    'SmartServerRepositoryLockWrite', info='semi')
719
 
request_handlers.register_lazy(
720
 
    'Repository.make_working_trees', 'bzrlib.smart.repository',
721
 
    'SmartServerRepositoryMakeWorkingTrees', info='read')
722
 
request_handlers.register_lazy(
723
 
    'Repository.set_make_working_trees', 'bzrlib.smart.repository',
724
 
    'SmartServerRepositorySetMakeWorkingTrees', info='idem')
725
 
request_handlers.register_lazy(
726
 
    'Repository.unlock', 'bzrlib.smart.repository',
727
 
    'SmartServerRepositoryUnlock', info='semi')
728
 
request_handlers.register_lazy(
729
 
    'Repository.get_physical_lock_status', 'bzrlib.smart.repository',
730
 
    'SmartServerRepositoryGetPhysicalLockStatus', info='read')
731
 
request_handlers.register_lazy(
732
 
    'Repository.get_rev_id_for_revno', 'bzrlib.smart.repository',
733
 
    'SmartServerRepositoryGetRevIdForRevno', info='read')
734
 
request_handlers.register_lazy(
735
 
    'Repository.get_stream', 'bzrlib.smart.repository',
736
 
    'SmartServerRepositoryGetStream', info='read')
737
 
request_handlers.register_lazy(
738
 
    'Repository.get_stream_1.19', 'bzrlib.smart.repository',
739
 
    'SmartServerRepositoryGetStream_1_19', info='read')
740
 
request_handlers.register_lazy(
741
 
    'Repository.iter_revisions', 'bzrlib.smart.repository',
742
 
    'SmartServerRepositoryIterRevisions', info='read')
743
 
request_handlers.register_lazy(
744
 
    'Repository.pack', 'bzrlib.smart.repository',
745
 
    'SmartServerRepositoryPack', info='idem')
746
 
request_handlers.register_lazy(
747
 
    'Repository.start_write_group', 'bzrlib.smart.repository',
748
 
    'SmartServerRepositoryStartWriteGroup', info='semi')
749
 
request_handlers.register_lazy(
750
 
    'Repository.commit_write_group', 'bzrlib.smart.repository',
751
 
    'SmartServerRepositoryCommitWriteGroup', info='semi')
752
 
request_handlers.register_lazy(
753
 
    'Repository.abort_write_group', 'bzrlib.smart.repository',
754
 
    'SmartServerRepositoryAbortWriteGroup', info='semi')
755
 
request_handlers.register_lazy(
756
 
    'Repository.check_write_group', 'bzrlib.smart.repository',
757
 
    'SmartServerRepositoryCheckWriteGroup', info='read')
758
 
request_handlers.register_lazy(
759
 
    'Repository.reconcile', 'bzrlib.smart.repository',
760
 
    'SmartServerRepositoryReconcile', info='idem')
 
275
    'append', 'bzrlib.smart.vfs', 'AppendRequest')
 
276
request_handlers.register_lazy(
 
277
    'Branch.get_config_file', 'bzrlib.smart.branch', 'SmartServerBranchGetConfigFile')
 
278
request_handlers.register_lazy(
 
279
    'Branch.last_revision_info', 'bzrlib.smart.branch', 'SmartServerBranchRequestLastRevisionInfo')
 
280
request_handlers.register_lazy(
 
281
    'Branch.lock_write', 'bzrlib.smart.branch', 'SmartServerBranchRequestLockWrite')
 
282
request_handlers.register_lazy(
 
283
    'Branch.revision_history', 'bzrlib.smart.branch', 'SmartServerRequestRevisionHistory')
 
284
request_handlers.register_lazy(
 
285
    'Branch.set_last_revision', 'bzrlib.smart.branch', 'SmartServerBranchRequestSetLastRevision')
 
286
request_handlers.register_lazy(
 
287
    'Branch.unlock', 'bzrlib.smart.branch', 'SmartServerBranchRequestUnlock')
 
288
request_handlers.register_lazy(
 
289
    'BzrDir.find_repository', 'bzrlib.smart.bzrdir', 'SmartServerRequestFindRepositoryV1')
 
290
request_handlers.register_lazy(
 
291
    'BzrDir.find_repositoryV2', 'bzrlib.smart.bzrdir', 'SmartServerRequestFindRepositoryV2')
 
292
request_handlers.register_lazy(
 
293
    'BzrDirFormat.initialize', 'bzrlib.smart.bzrdir', 'SmartServerRequestInitializeBzrDir')
 
294
request_handlers.register_lazy(
 
295
    'BzrDir.open_branch', 'bzrlib.smart.bzrdir', 'SmartServerRequestOpenBranch')
 
296
request_handlers.register_lazy(
 
297
    'delete', 'bzrlib.smart.vfs', 'DeleteRequest')
 
298
request_handlers.register_lazy(
 
299
    'get', 'bzrlib.smart.vfs', 'GetRequest')
 
300
request_handlers.register_lazy(
 
301
    'get_bundle', 'bzrlib.smart.request', 'GetBundleRequest')
 
302
request_handlers.register_lazy(
 
303
    'has', 'bzrlib.smart.vfs', 'HasRequest')
 
304
request_handlers.register_lazy(
 
305
    'hello', 'bzrlib.smart.request', 'HelloRequest')
 
306
request_handlers.register_lazy(
 
307
    'iter_files_recursive', 'bzrlib.smart.vfs', 'IterFilesRecursiveRequest')
 
308
request_handlers.register_lazy(
 
309
    'list_dir', 'bzrlib.smart.vfs', 'ListDirRequest')
 
310
request_handlers.register_lazy(
 
311
    'mkdir', 'bzrlib.smart.vfs', 'MkdirRequest')
 
312
request_handlers.register_lazy(
 
313
    'move', 'bzrlib.smart.vfs', 'MoveRequest')
 
314
request_handlers.register_lazy(
 
315
    'put', 'bzrlib.smart.vfs', 'PutRequest')
 
316
request_handlers.register_lazy(
 
317
    'put_non_atomic', 'bzrlib.smart.vfs', 'PutNonAtomicRequest')
 
318
request_handlers.register_lazy(
 
319
    'readv', 'bzrlib.smart.vfs', 'ReadvRequest')
 
320
request_handlers.register_lazy(
 
321
    'rename', 'bzrlib.smart.vfs', 'RenameRequest')
 
322
request_handlers.register_lazy('Repository.gather_stats',
 
323
                               'bzrlib.smart.repository',
 
324
                               'SmartServerRepositoryGatherStats')
 
325
request_handlers.register_lazy('Repository.get_parent_map',
 
326
                               'bzrlib.smart.repository',
 
327
                               'SmartServerRepositoryGetParentMap')
 
328
request_handlers.register_lazy(
 
329
    'Repository.stream_knit_data_for_revisions',
 
330
    'bzrlib.smart.repository',
 
331
    'SmartServerRepositoryStreamKnitDataForRevisions')
 
332
request_handlers.register_lazy(
 
333
    'Repository.stream_revisions_chunked',
 
334
    'bzrlib.smart.repository',
 
335
    'SmartServerRepositoryStreamRevisionsChunked')
 
336
request_handlers.register_lazy(
 
337
    'Repository.get_revision_graph', 'bzrlib.smart.repository', 'SmartServerRepositoryGetRevisionGraph')
 
338
request_handlers.register_lazy(
 
339
    'Repository.has_revision', 'bzrlib.smart.repository', 'SmartServerRequestHasRevision')
 
340
request_handlers.register_lazy(
 
341
    'Repository.is_shared', 'bzrlib.smart.repository', 'SmartServerRepositoryIsShared')
 
342
request_handlers.register_lazy(
 
343
    'Repository.lock_write', 'bzrlib.smart.repository', 'SmartServerRepositoryLockWrite')
 
344
request_handlers.register_lazy(
 
345
    'Repository.unlock', 'bzrlib.smart.repository', 'SmartServerRepositoryUnlock')
761
346
request_handlers.register_lazy(
762
347
    'Repository.tarball', 'bzrlib.smart.repository',
763
 
    'SmartServerRepositoryTarball', info='read')
764
 
request_handlers.register_lazy(
765
 
    'VersionedFileRepository.get_serializer_format', 'bzrlib.smart.repository',
766
 
    'SmartServerRepositoryGetSerializerFormat', info='read')
767
 
request_handlers.register_lazy(
768
 
    'VersionedFileRepository.get_inventories', 'bzrlib.smart.repository',
769
 
    'SmartServerRepositoryGetInventories', info='read')
770
 
request_handlers.register_lazy(
771
 
    'rmdir', 'bzrlib.smart.vfs', 'RmdirRequest', info='semivfs')
772
 
request_handlers.register_lazy(
773
 
    'stat', 'bzrlib.smart.vfs', 'StatRequest', info='read')
774
 
request_handlers.register_lazy(
775
 
    'Transport.is_readonly', 'bzrlib.smart.request',
776
 
    'SmartServerIsReadonly', info='read')
 
348
    'SmartServerRepositoryTarball')
 
349
request_handlers.register_lazy(
 
350
    'rmdir', 'bzrlib.smart.vfs', 'RmdirRequest')
 
351
request_handlers.register_lazy(
 
352
    'stat', 'bzrlib.smart.vfs', 'StatRequest')
 
353
request_handlers.register_lazy(
 
354
    'Transport.is_readonly', 'bzrlib.smart.request', 'SmartServerIsReadonly')
 
355
request_handlers.register_lazy(
 
356
    'BzrDir.open', 'bzrlib.smart.bzrdir', 'SmartServerRequestOpenBzrDir')