~bzr-pqm/bzr/bzr.dev

2402.1.2 by Andrew Bennetts
Deal with review comments.
1
# Copyright (C) 2006, 2007 Canonical Ltd
2018.5.4 by Andrew Bennetts
Split smart server VFS logic out into a new file, and start using the command pattern in the SmartServerRequestHandler.
2
#
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
7
#
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
# GNU General Public License for more details.
12
#
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
17
"""VFS operations for the smart server.
18
19
This module defines the smart server methods that are low-level file operations
20
-- i.e. methods that operate directly on files and directories, rather than
21
higher-level concepts like branches and revisions.
2018.5.19 by Andrew Bennetts
Add docstrings to all the new modules, and a few other places.
22
23
These methods, plus 'hello' and 'get_bundle', are version 1 of the smart server
24
protocol, as implemented in bzr 0.11 and later.
2018.5.4 by Andrew Bennetts
Split smart server VFS logic out into a new file, and start using the command pattern in the SmartServerRequestHandler.
25
"""
26
2018.5.24 by Andrew Bennetts
Setting NO_SMART_VFS in environment will disable VFS methods in the smart server. (Robert Collins, John Arbash Meinel, Andrew Bennetts)
27
import os
28
29
from bzrlib import errors
2018.5.21 by Andrew Bennetts
Move bzrlib.transport.smart to bzrlib.smart
30
from bzrlib.smart import request
2018.5.4 by Andrew Bennetts
Split smart server VFS logic out into a new file, and start using the command pattern in the SmartServerRequestHandler.
31
32
33
def _deserialise_optional_mode(mode):
34
    # XXX: FIXME this should be on the protocol object.  Later protocol versions
35
    # might serialise modes differently.
36
    if mode == '':
37
        return None
38
    else:
39
        return int(mode)
40
41
2402.1.1 by Andrew Bennetts
Use the Command pattern for handling smart server commands.
42
def vfs_enabled():
43
    """Is the VFS enabled ?
44
2402.1.2 by Andrew Bennetts
Deal with review comments.
45
    the VFS is disabled when the BZR_NO_SMART_VFS environment variable is set.
2402.1.1 by Andrew Bennetts
Use the Command pattern for handling smart server commands.
46
47
    :return: True if it is enabled.
48
    """
2402.1.2 by Andrew Bennetts
Deal with review comments.
49
    return not 'BZR_NO_SMART_VFS' in os.environ
2402.1.1 by Andrew Bennetts
Use the Command pattern for handling smart server commands.
50
51
2018.5.24 by Andrew Bennetts
Setting NO_SMART_VFS in environment will disable VFS methods in the smart server. (Robert Collins, John Arbash Meinel, Andrew Bennetts)
52
class VfsRequest(request.SmartServerRequest):
53
    """Base class for VFS requests.
54
    
2402.1.1 by Andrew Bennetts
Use the Command pattern for handling smart server commands.
55
    VFS requests are disabled if vfs_enabled() returns False.
2018.5.24 by Andrew Bennetts
Setting NO_SMART_VFS in environment will disable VFS methods in the smart server. (Robert Collins, John Arbash Meinel, Andrew Bennetts)
56
    """
57
58
    def _check_enabled(self):
2402.1.1 by Andrew Bennetts
Use the Command pattern for handling smart server commands.
59
        if not vfs_enabled():
2018.5.24 by Andrew Bennetts
Setting NO_SMART_VFS in environment will disable VFS methods in the smart server. (Robert Collins, John Arbash Meinel, Andrew Bennetts)
60
            raise errors.DisabledMethod(self.__class__.__name__)
61
62
63
class HasRequest(VfsRequest):
2018.5.4 by Andrew Bennetts
Split smart server VFS logic out into a new file, and start using the command pattern in the SmartServerRequestHandler.
64
65
    def do(self, relpath):
66
        r = self._backing_transport.has(relpath) and 'yes' or 'no'
2432.4.5 by Robert Collins
Make using SuccessfulSmartServerResponse and FailedSmartServerResponse mandatory rather than optional in smart server logic.
67
        return request.SuccessfulSmartServerResponse((r,))
2018.5.4 by Andrew Bennetts
Split smart server VFS logic out into a new file, and start using the command pattern in the SmartServerRequestHandler.
68
69
2018.5.24 by Andrew Bennetts
Setting NO_SMART_VFS in environment will disable VFS methods in the smart server. (Robert Collins, John Arbash Meinel, Andrew Bennetts)
70
class GetRequest(VfsRequest):
2018.5.4 by Andrew Bennetts
Split smart server VFS logic out into a new file, and start using the command pattern in the SmartServerRequestHandler.
71
72
    def do(self, relpath):
2052.6.2 by Robert Collins
Merge bzr.dev.
73
        try:
74
            backing_bytes = self._backing_transport.get_bytes(relpath)
75
        except errors.ReadError:
76
            # cannot read the file
77
            return request.FailedSmartServerResponse(('ReadError', ))
3146.4.10 by Aaron Bentley
Add handling of PermissionDenied errors to smart protocol VFS layer
78
        except errors.PermissionDenied:
79
            return request.FailedSmartServerResponse(('PermissionDenied',))
2432.4.5 by Robert Collins
Make using SuccessfulSmartServerResponse and FailedSmartServerResponse mandatory rather than optional in smart server logic.
80
        return request.SuccessfulSmartServerResponse(('ok',), backing_bytes)
2018.5.4 by Andrew Bennetts
Split smart server VFS logic out into a new file, and start using the command pattern in the SmartServerRequestHandler.
81
82
2018.5.24 by Andrew Bennetts
Setting NO_SMART_VFS in environment will disable VFS methods in the smart server. (Robert Collins, John Arbash Meinel, Andrew Bennetts)
83
class AppendRequest(VfsRequest):
2018.5.4 by Andrew Bennetts
Split smart server VFS logic out into a new file, and start using the command pattern in the SmartServerRequestHandler.
84
85
    def do(self, relpath, mode):
86
        self._relpath = relpath
87
        self._mode = _deserialise_optional_mode(mode)
88
    
2018.5.5 by Andrew Bennetts
Pass body_bytes directly to SmartServerRequest.do_body
89
    def do_body(self, body_bytes):
2018.5.4 by Andrew Bennetts
Split smart server VFS logic out into a new file, and start using the command pattern in the SmartServerRequestHandler.
90
        old_length = self._backing_transport.append_bytes(
2018.5.5 by Andrew Bennetts
Pass body_bytes directly to SmartServerRequest.do_body
91
            self._relpath, body_bytes, self._mode)
2432.4.5 by Robert Collins
Make using SuccessfulSmartServerResponse and FailedSmartServerResponse mandatory rather than optional in smart server logic.
92
        return request.SuccessfulSmartServerResponse(('appended', '%d' % old_length))
2018.5.4 by Andrew Bennetts
Split smart server VFS logic out into a new file, and start using the command pattern in the SmartServerRequestHandler.
93
94
2018.5.24 by Andrew Bennetts
Setting NO_SMART_VFS in environment will disable VFS methods in the smart server. (Robert Collins, John Arbash Meinel, Andrew Bennetts)
95
class DeleteRequest(VfsRequest):
2018.5.4 by Andrew Bennetts
Split smart server VFS logic out into a new file, and start using the command pattern in the SmartServerRequestHandler.
96
97
    def do(self, relpath):
98
        self._backing_transport.delete(relpath)
2432.4.5 by Robert Collins
Make using SuccessfulSmartServerResponse and FailedSmartServerResponse mandatory rather than optional in smart server logic.
99
        return request.SuccessfulSmartServerResponse(('ok', ))
2018.5.4 by Andrew Bennetts
Split smart server VFS logic out into a new file, and start using the command pattern in the SmartServerRequestHandler.
100
101
2018.5.37 by Andrew Bennetts
Make sure all the request handlers in bzrlib/smart/vfs.py have consistent names.
102
class IterFilesRecursiveRequest(VfsRequest):
2018.5.4 by Andrew Bennetts
Split smart server VFS logic out into a new file, and start using the command pattern in the SmartServerRequestHandler.
103
104
    def do(self, relpath):
105
        transport = self._backing_transport.clone(relpath)
106
        filenames = transport.iter_files_recursive()
2432.4.5 by Robert Collins
Make using SuccessfulSmartServerResponse and FailedSmartServerResponse mandatory rather than optional in smart server logic.
107
        return request.SuccessfulSmartServerResponse(('names',) + tuple(filenames))
2018.5.4 by Andrew Bennetts
Split smart server VFS logic out into a new file, and start using the command pattern in the SmartServerRequestHandler.
108
109
2018.5.24 by Andrew Bennetts
Setting NO_SMART_VFS in environment will disable VFS methods in the smart server. (Robert Collins, John Arbash Meinel, Andrew Bennetts)
110
class ListDirRequest(VfsRequest):
2018.5.4 by Andrew Bennetts
Split smart server VFS logic out into a new file, and start using the command pattern in the SmartServerRequestHandler.
111
112
    def do(self, relpath):
113
        filenames = self._backing_transport.list_dir(relpath)
2432.4.5 by Robert Collins
Make using SuccessfulSmartServerResponse and FailedSmartServerResponse mandatory rather than optional in smart server logic.
114
        return request.SuccessfulSmartServerResponse(('names',) + tuple(filenames))
2018.5.4 by Andrew Bennetts
Split smart server VFS logic out into a new file, and start using the command pattern in the SmartServerRequestHandler.
115
116
2018.5.37 by Andrew Bennetts
Make sure all the request handlers in bzrlib/smart/vfs.py have consistent names.
117
class MkdirRequest(VfsRequest):
2018.5.4 by Andrew Bennetts
Split smart server VFS logic out into a new file, and start using the command pattern in the SmartServerRequestHandler.
118
119
    def do(self, relpath, mode):
120
        self._backing_transport.mkdir(relpath,
121
                                      _deserialise_optional_mode(mode))
2432.4.5 by Robert Collins
Make using SuccessfulSmartServerResponse and FailedSmartServerResponse mandatory rather than optional in smart server logic.
122
        return request.SuccessfulSmartServerResponse(('ok',))
2018.5.4 by Andrew Bennetts
Split smart server VFS logic out into a new file, and start using the command pattern in the SmartServerRequestHandler.
123
124
2018.5.37 by Andrew Bennetts
Make sure all the request handlers in bzrlib/smart/vfs.py have consistent names.
125
class MoveRequest(VfsRequest):
2018.5.4 by Andrew Bennetts
Split smart server VFS logic out into a new file, and start using the command pattern in the SmartServerRequestHandler.
126
127
    def do(self, rel_from, rel_to):
128
        self._backing_transport.move(rel_from, rel_to)
2432.4.5 by Robert Collins
Make using SuccessfulSmartServerResponse and FailedSmartServerResponse mandatory rather than optional in smart server logic.
129
        return request.SuccessfulSmartServerResponse(('ok',))
2018.5.4 by Andrew Bennetts
Split smart server VFS logic out into a new file, and start using the command pattern in the SmartServerRequestHandler.
130
131
2018.5.37 by Andrew Bennetts
Make sure all the request handlers in bzrlib/smart/vfs.py have consistent names.
132
class PutRequest(VfsRequest):
2018.5.4 by Andrew Bennetts
Split smart server VFS logic out into a new file, and start using the command pattern in the SmartServerRequestHandler.
133
134
    def do(self, relpath, mode):
135
        self._relpath = relpath
136
        self._mode = _deserialise_optional_mode(mode)
137
2018.5.5 by Andrew Bennetts
Pass body_bytes directly to SmartServerRequest.do_body
138
    def do_body(self, body_bytes):
139
        self._backing_transport.put_bytes(self._relpath, body_bytes, self._mode)
2432.4.5 by Robert Collins
Make using SuccessfulSmartServerResponse and FailedSmartServerResponse mandatory rather than optional in smart server logic.
140
        return request.SuccessfulSmartServerResponse(('ok',))
2018.5.4 by Andrew Bennetts
Split smart server VFS logic out into a new file, and start using the command pattern in the SmartServerRequestHandler.
141
142
2018.5.37 by Andrew Bennetts
Make sure all the request handlers in bzrlib/smart/vfs.py have consistent names.
143
class PutNonAtomicRequest(VfsRequest):
2018.5.4 by Andrew Bennetts
Split smart server VFS logic out into a new file, and start using the command pattern in the SmartServerRequestHandler.
144
145
    def do(self, relpath, mode, create_parent, dir_mode):
146
        self._relpath = relpath
147
        self._dir_mode = _deserialise_optional_mode(dir_mode)
148
        self._mode = _deserialise_optional_mode(mode)
149
        # a boolean would be nicer XXX
150
        self._create_parent = (create_parent == 'T')
151
2018.5.5 by Andrew Bennetts
Pass body_bytes directly to SmartServerRequest.do_body
152
    def do_body(self, body_bytes):
2018.5.4 by Andrew Bennetts
Split smart server VFS logic out into a new file, and start using the command pattern in the SmartServerRequestHandler.
153
        self._backing_transport.put_bytes_non_atomic(self._relpath,
2018.5.5 by Andrew Bennetts
Pass body_bytes directly to SmartServerRequest.do_body
154
                body_bytes,
2018.5.4 by Andrew Bennetts
Split smart server VFS logic out into a new file, and start using the command pattern in the SmartServerRequestHandler.
155
                mode=self._mode,
156
                create_parent_dir=self._create_parent,
157
                dir_mode=self._dir_mode)
2432.4.5 by Robert Collins
Make using SuccessfulSmartServerResponse and FailedSmartServerResponse mandatory rather than optional in smart server logic.
158
        return request.SuccessfulSmartServerResponse(('ok',))
2018.5.4 by Andrew Bennetts
Split smart server VFS logic out into a new file, and start using the command pattern in the SmartServerRequestHandler.
159
160
2018.5.37 by Andrew Bennetts
Make sure all the request handlers in bzrlib/smart/vfs.py have consistent names.
161
class ReadvRequest(VfsRequest):
2018.5.4 by Andrew Bennetts
Split smart server VFS logic out into a new file, and start using the command pattern in the SmartServerRequestHandler.
162
163
    def do(self, relpath):
164
        self._relpath = relpath
165
2018.5.5 by Andrew Bennetts
Pass body_bytes directly to SmartServerRequest.do_body
166
    def do_body(self, body_bytes):
2018.5.4 by Andrew Bennetts
Split smart server VFS logic out into a new file, and start using the command pattern in the SmartServerRequestHandler.
167
        """accept offsets for a readv request."""
2018.5.5 by Andrew Bennetts
Pass body_bytes directly to SmartServerRequest.do_body
168
        offsets = self._deserialise_offsets(body_bytes)
2018.5.4 by Andrew Bennetts
Split smart server VFS logic out into a new file, and start using the command pattern in the SmartServerRequestHandler.
169
        backing_bytes = ''.join(bytes for offset, bytes in
170
            self._backing_transport.readv(self._relpath, offsets))
2432.4.5 by Robert Collins
Make using SuccessfulSmartServerResponse and FailedSmartServerResponse mandatory rather than optional in smart server logic.
171
        return request.SuccessfulSmartServerResponse(('readv',), backing_bytes)
2018.5.4 by Andrew Bennetts
Split smart server VFS logic out into a new file, and start using the command pattern in the SmartServerRequestHandler.
172
173
    def _deserialise_offsets(self, text):
174
        # XXX: FIXME this should be on the protocol object.
175
        offsets = []
176
        for line in text.split('\n'):
177
            if not line:
178
                continue
179
            start, length = line.split(',')
180
            offsets.append((int(start), int(length)))
181
        return offsets
182
183
2018.5.37 by Andrew Bennetts
Make sure all the request handlers in bzrlib/smart/vfs.py have consistent names.
184
class RenameRequest(VfsRequest):
2018.5.4 by Andrew Bennetts
Split smart server VFS logic out into a new file, and start using the command pattern in the SmartServerRequestHandler.
185
186
    def do(self, rel_from, rel_to):
187
        self._backing_transport.rename(rel_from, rel_to)
2432.4.5 by Robert Collins
Make using SuccessfulSmartServerResponse and FailedSmartServerResponse mandatory rather than optional in smart server logic.
188
        return request.SuccessfulSmartServerResponse(('ok', ))
2018.5.4 by Andrew Bennetts
Split smart server VFS logic out into a new file, and start using the command pattern in the SmartServerRequestHandler.
189
190
2018.5.37 by Andrew Bennetts
Make sure all the request handlers in bzrlib/smart/vfs.py have consistent names.
191
class RmdirRequest(VfsRequest):
2018.5.4 by Andrew Bennetts
Split smart server VFS logic out into a new file, and start using the command pattern in the SmartServerRequestHandler.
192
193
    def do(self, relpath):
194
        self._backing_transport.rmdir(relpath)
2432.4.5 by Robert Collins
Make using SuccessfulSmartServerResponse and FailedSmartServerResponse mandatory rather than optional in smart server logic.
195
        return request.SuccessfulSmartServerResponse(('ok', ))
2018.5.4 by Andrew Bennetts
Split smart server VFS logic out into a new file, and start using the command pattern in the SmartServerRequestHandler.
196
197
2018.5.37 by Andrew Bennetts
Make sure all the request handlers in bzrlib/smart/vfs.py have consistent names.
198
class StatRequest(VfsRequest):
2018.5.4 by Andrew Bennetts
Split smart server VFS logic out into a new file, and start using the command pattern in the SmartServerRequestHandler.
199
200
    def do(self, relpath):
201
        stat = self._backing_transport.stat(relpath)
2432.4.5 by Robert Collins
Make using SuccessfulSmartServerResponse and FailedSmartServerResponse mandatory rather than optional in smart server logic.
202
        return request.SuccessfulSmartServerResponse(
2018.5.4 by Andrew Bennetts
Split smart server VFS logic out into a new file, and start using the command pattern in the SmartServerRequestHandler.
203
            ('stat', str(stat.st_size), oct(stat.st_mode)))
204