~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
4183.7.1 by Sabin Iacob
update FSF mailing address
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
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.
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.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
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):
2692.1.5 by Andrew Bennetts
Add translate_client_path calls to bzrlib/smart/vfs.py
66
        relpath = self.translate_client_path(relpath)
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.
67
        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.
68
        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.
69
70
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)
71
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.
72
73
    def do(self, relpath):
2692.1.5 by Andrew Bennetts
Add translate_client_path calls to bzrlib/smart/vfs.py
74
        relpath = self.translate_client_path(relpath)
3779.3.1 by Andrew Bennetts
Move encoding/decoding logic of PermissionDenied and ReadError so that it happens for all RPCs.
75
        backing_bytes = self._backing_transport.get_bytes(relpath)
2432.4.5 by Robert Collins
Make using SuccessfulSmartServerResponse and FailedSmartServerResponse mandatory rather than optional in smart server logic.
76
        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.
77
78
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)
79
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.
80
81
    def do(self, relpath, mode):
2692.1.5 by Andrew Bennetts
Add translate_client_path calls to bzrlib/smart/vfs.py
82
        relpath = self.translate_client_path(relpath)
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.
83
        self._relpath = relpath
84
        self._mode = _deserialise_optional_mode(mode)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
85
2018.5.5 by Andrew Bennetts
Pass body_bytes directly to SmartServerRequest.do_body
86
    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.
87
        old_length = self._backing_transport.append_bytes(
2018.5.5 by Andrew Bennetts
Pass body_bytes directly to SmartServerRequest.do_body
88
            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.
89
        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.
90
91
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)
92
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.
93
94
    def do(self, relpath):
2692.1.5 by Andrew Bennetts
Add translate_client_path calls to bzrlib/smart/vfs.py
95
        relpath = self.translate_client_path(relpath)
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
        self._backing_transport.delete(relpath)
2432.4.5 by Robert Collins
Make using SuccessfulSmartServerResponse and FailedSmartServerResponse mandatory rather than optional in smart server logic.
97
        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.
98
99
2018.5.37 by Andrew Bennetts
Make sure all the request handlers in bzrlib/smart/vfs.py have consistent names.
100
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.
101
102
    def do(self, relpath):
2692.1.11 by Andrew Bennetts
Improve test coverage by making SmartTCPServer_for_testing by default create a server that does not serve the backing transport's root at its own root. This mirrors the way most HTTP smart servers are configured.
103
        if not relpath.endswith('/'):
104
            relpath += '/'
2692.1.5 by Andrew Bennetts
Add translate_client_path calls to bzrlib/smart/vfs.py
105
        relpath = self.translate_client_path(relpath)
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.
106
        transport = self._backing_transport.clone(relpath)
107
        filenames = transport.iter_files_recursive()
2432.4.5 by Robert Collins
Make using SuccessfulSmartServerResponse and FailedSmartServerResponse mandatory rather than optional in smart server logic.
108
        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.
109
110
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)
111
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.
112
113
    def do(self, relpath):
2692.1.11 by Andrew Bennetts
Improve test coverage by making SmartTCPServer_for_testing by default create a server that does not serve the backing transport's root at its own root. This mirrors the way most HTTP smart servers are configured.
114
        if not relpath.endswith('/'):
115
            relpath += '/'
2692.1.5 by Andrew Bennetts
Add translate_client_path calls to bzrlib/smart/vfs.py
116
        relpath = self.translate_client_path(relpath)
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.
117
        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.
118
        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.
119
120
2018.5.37 by Andrew Bennetts
Make sure all the request handlers in bzrlib/smart/vfs.py have consistent names.
121
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.
122
123
    def do(self, relpath, mode):
2692.1.5 by Andrew Bennetts
Add translate_client_path calls to bzrlib/smart/vfs.py
124
        relpath = self.translate_client_path(relpath)
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.
125
        self._backing_transport.mkdir(relpath,
126
                                      _deserialise_optional_mode(mode))
2432.4.5 by Robert Collins
Make using SuccessfulSmartServerResponse and FailedSmartServerResponse mandatory rather than optional in smart server logic.
127
        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.
128
129
2018.5.37 by Andrew Bennetts
Make sure all the request handlers in bzrlib/smart/vfs.py have consistent names.
130
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.
131
132
    def do(self, rel_from, rel_to):
2692.1.5 by Andrew Bennetts
Add translate_client_path calls to bzrlib/smart/vfs.py
133
        rel_from = self.translate_client_path(rel_from)
134
        rel_to = self.translate_client_path(rel_to)
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.
135
        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.
136
        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.
137
138
2018.5.37 by Andrew Bennetts
Make sure all the request handlers in bzrlib/smart/vfs.py have consistent names.
139
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.
140
141
    def do(self, relpath, mode):
2692.1.5 by Andrew Bennetts
Add translate_client_path calls to bzrlib/smart/vfs.py
142
        relpath = self.translate_client_path(relpath)
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.
143
        self._relpath = relpath
144
        self._mode = _deserialise_optional_mode(mode)
145
2018.5.5 by Andrew Bennetts
Pass body_bytes directly to SmartServerRequest.do_body
146
    def do_body(self, body_bytes):
147
        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.
148
        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.
149
150
2018.5.37 by Andrew Bennetts
Make sure all the request handlers in bzrlib/smart/vfs.py have consistent names.
151
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.
152
153
    def do(self, relpath, mode, create_parent, dir_mode):
2692.1.5 by Andrew Bennetts
Add translate_client_path calls to bzrlib/smart/vfs.py
154
        relpath = self.translate_client_path(relpath)
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
        self._relpath = relpath
156
        self._dir_mode = _deserialise_optional_mode(dir_mode)
157
        self._mode = _deserialise_optional_mode(mode)
158
        # a boolean would be nicer XXX
159
        self._create_parent = (create_parent == 'T')
160
2018.5.5 by Andrew Bennetts
Pass body_bytes directly to SmartServerRequest.do_body
161
    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.
162
        self._backing_transport.put_bytes_non_atomic(self._relpath,
2018.5.5 by Andrew Bennetts
Pass body_bytes directly to SmartServerRequest.do_body
163
                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.
164
                mode=self._mode,
165
                create_parent_dir=self._create_parent,
166
                dir_mode=self._dir_mode)
2432.4.5 by Robert Collins
Make using SuccessfulSmartServerResponse and FailedSmartServerResponse mandatory rather than optional in smart server logic.
167
        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.
168
169
2018.5.37 by Andrew Bennetts
Make sure all the request handlers in bzrlib/smart/vfs.py have consistent names.
170
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.
171
172
    def do(self, relpath):
2692.1.5 by Andrew Bennetts
Add translate_client_path calls to bzrlib/smart/vfs.py
173
        relpath = self.translate_client_path(relpath)
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.
174
        self._relpath = relpath
175
2018.5.5 by Andrew Bennetts
Pass body_bytes directly to SmartServerRequest.do_body
176
    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.
177
        """accept offsets for a readv request."""
2018.5.5 by Andrew Bennetts
Pass body_bytes directly to SmartServerRequest.do_body
178
        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.
179
        backing_bytes = ''.join(bytes for offset, bytes in
180
            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.
181
        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.
182
183
    def _deserialise_offsets(self, text):
184
        # XXX: FIXME this should be on the protocol object.
185
        offsets = []
186
        for line in text.split('\n'):
187
            if not line:
188
                continue
189
            start, length = line.split(',')
190
            offsets.append((int(start), int(length)))
191
        return offsets
192
193
2018.5.37 by Andrew Bennetts
Make sure all the request handlers in bzrlib/smart/vfs.py have consistent names.
194
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.
195
196
    def do(self, rel_from, rel_to):
2692.1.5 by Andrew Bennetts
Add translate_client_path calls to bzrlib/smart/vfs.py
197
        rel_from = self.translate_client_path(rel_from)
198
        rel_to = self.translate_client_path(rel_to)
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
        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.
200
        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.
201
202
2018.5.37 by Andrew Bennetts
Make sure all the request handlers in bzrlib/smart/vfs.py have consistent names.
203
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.
204
205
    def do(self, relpath):
2692.1.5 by Andrew Bennetts
Add translate_client_path calls to bzrlib/smart/vfs.py
206
        relpath = self.translate_client_path(relpath)
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.
207
        self._backing_transport.rmdir(relpath)
2432.4.5 by Robert Collins
Make using SuccessfulSmartServerResponse and FailedSmartServerResponse mandatory rather than optional in smart server logic.
208
        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.
209
210
2018.5.37 by Andrew Bennetts
Make sure all the request handlers in bzrlib/smart/vfs.py have consistent names.
211
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.
212
213
    def do(self, relpath):
2692.1.11 by Andrew Bennetts
Improve test coverage by making SmartTCPServer_for_testing by default create a server that does not serve the backing transport's root at its own root. This mirrors the way most HTTP smart servers are configured.
214
        if not relpath.endswith('/'):
215
            relpath += '/'
2692.1.5 by Andrew Bennetts
Add translate_client_path calls to bzrlib/smart/vfs.py
216
        relpath = self.translate_client_path(relpath)
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.
217
        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.
218
        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.
219
            ('stat', str(stat.st_size), oct(stat.st_mode)))
220