~bzr-pqm/bzr/bzr.dev

4763.2.4 by John Arbash Meinel
merge bzr.2.1 in preparation for NEWS entry.
1
# Copyright (C) 2006-2010 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
4760.2.3 by Michael Hudson
handle different escaping of vfs paths
30
from bzrlib import urlutils
2018.5.21 by Andrew Bennetts
Move bzrlib.transport.smart to bzrlib.smart
31
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.
32
33
34
def _deserialise_optional_mode(mode):
35
    # XXX: FIXME this should be on the protocol object.  Later protocol versions
36
    # might serialise modes differently.
37
    if mode == '':
38
        return None
39
    else:
40
        return int(mode)
41
42
2402.1.1 by Andrew Bennetts
Use the Command pattern for handling smart server commands.
43
def vfs_enabled():
44
    """Is the VFS enabled ?
45
2402.1.2 by Andrew Bennetts
Deal with review comments.
46
    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.
47
48
    :return: True if it is enabled.
49
    """
2402.1.2 by Andrew Bennetts
Deal with review comments.
50
    return not 'BZR_NO_SMART_VFS' in os.environ
2402.1.1 by Andrew Bennetts
Use the Command pattern for handling smart server commands.
51
52
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)
53
class VfsRequest(request.SmartServerRequest):
54
    """Base class for VFS requests.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
55
2402.1.1 by Andrew Bennetts
Use the Command pattern for handling smart server commands.
56
    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)
57
    """
58
59
    def _check_enabled(self):
2402.1.1 by Andrew Bennetts
Use the Command pattern for handling smart server commands.
60
        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)
61
            raise errors.DisabledMethod(self.__class__.__name__)
62
4760.2.3 by Michael Hudson
handle different escaping of vfs paths
63
    def translate_client_path(self, relpath):
64
        # VFS requests are made with escaped paths so the escaping done in
65
        # SmartServerRequest.translate_client_path leads to double escaping.
66
        # Remove it here -- the fact that the result is still escaped means
67
        # that the str() will not fail on valid input.
68
        x = request.SmartServerRequest.translate_client_path(self, relpath)
69
        return str(urlutils.unescape(x))
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
72
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.
73
74
    def do(self, relpath):
2692.1.5 by Andrew Bennetts
Add translate_client_path calls to bzrlib/smart/vfs.py
75
        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.
76
        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.
77
        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.
78
79
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)
80
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.
81
82
    def do(self, relpath):
2692.1.5 by Andrew Bennetts
Add translate_client_path calls to bzrlib/smart/vfs.py
83
        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.
84
        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.
85
        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.
86
87
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)
88
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.
89
90
    def do(self, relpath, mode):
2692.1.5 by Andrew Bennetts
Add translate_client_path calls to bzrlib/smart/vfs.py
91
        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.
92
        self._relpath = relpath
93
        self._mode = _deserialise_optional_mode(mode)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
94
2018.5.5 by Andrew Bennetts
Pass body_bytes directly to SmartServerRequest.do_body
95
    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.
96
        old_length = self._backing_transport.append_bytes(
2018.5.5 by Andrew Bennetts
Pass body_bytes directly to SmartServerRequest.do_body
97
            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.
98
        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.
99
100
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)
101
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.
102
103
    def do(self, relpath):
2692.1.5 by Andrew Bennetts
Add translate_client_path calls to bzrlib/smart/vfs.py
104
        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.
105
        self._backing_transport.delete(relpath)
2432.4.5 by Robert Collins
Make using SuccessfulSmartServerResponse and FailedSmartServerResponse mandatory rather than optional in smart server logic.
106
        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.
107
108
2018.5.37 by Andrew Bennetts
Make sure all the request handlers in bzrlib/smart/vfs.py have consistent names.
109
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.
110
111
    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.
112
        if not relpath.endswith('/'):
113
            relpath += '/'
2692.1.5 by Andrew Bennetts
Add translate_client_path calls to bzrlib/smart/vfs.py
114
        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.
115
        transport = self._backing_transport.clone(relpath)
116
        filenames = transport.iter_files_recursive()
2432.4.5 by Robert Collins
Make using SuccessfulSmartServerResponse and FailedSmartServerResponse mandatory rather than optional in smart server logic.
117
        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.
118
119
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)
120
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.
121
122
    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.
123
        if not relpath.endswith('/'):
124
            relpath += '/'
2692.1.5 by Andrew Bennetts
Add translate_client_path calls to bzrlib/smart/vfs.py
125
        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.
126
        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.
127
        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.
128
129
2018.5.37 by Andrew Bennetts
Make sure all the request handlers in bzrlib/smart/vfs.py have consistent names.
130
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.
131
132
    def do(self, relpath, mode):
2692.1.5 by Andrew Bennetts
Add translate_client_path calls to bzrlib/smart/vfs.py
133
        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.
134
        self._backing_transport.mkdir(relpath,
135
                                      _deserialise_optional_mode(mode))
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 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.
140
141
    def do(self, rel_from, rel_to):
2692.1.5 by Andrew Bennetts
Add translate_client_path calls to bzrlib/smart/vfs.py
142
        rel_from = self.translate_client_path(rel_from)
143
        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.
144
        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.
145
        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.
146
147
2018.5.37 by Andrew Bennetts
Make sure all the request handlers in bzrlib/smart/vfs.py have consistent names.
148
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.
149
150
    def do(self, relpath, mode):
2692.1.5 by Andrew Bennetts
Add translate_client_path calls to bzrlib/smart/vfs.py
151
        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.
152
        self._relpath = relpath
153
        self._mode = _deserialise_optional_mode(mode)
154
2018.5.5 by Andrew Bennetts
Pass body_bytes directly to SmartServerRequest.do_body
155
    def do_body(self, body_bytes):
156
        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.
157
        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.
158
159
2018.5.37 by Andrew Bennetts
Make sure all the request handlers in bzrlib/smart/vfs.py have consistent names.
160
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.
161
162
    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
163
        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.
164
        self._relpath = relpath
165
        self._dir_mode = _deserialise_optional_mode(dir_mode)
166
        self._mode = _deserialise_optional_mode(mode)
167
        # a boolean would be nicer XXX
168
        self._create_parent = (create_parent == 'T')
169
2018.5.5 by Andrew Bennetts
Pass body_bytes directly to SmartServerRequest.do_body
170
    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.
171
        self._backing_transport.put_bytes_non_atomic(self._relpath,
2018.5.5 by Andrew Bennetts
Pass body_bytes directly to SmartServerRequest.do_body
172
                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.
173
                mode=self._mode,
174
                create_parent_dir=self._create_parent,
175
                dir_mode=self._dir_mode)
2432.4.5 by Robert Collins
Make using SuccessfulSmartServerResponse and FailedSmartServerResponse mandatory rather than optional in smart server logic.
176
        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.
177
178
2018.5.37 by Andrew Bennetts
Make sure all the request handlers in bzrlib/smart/vfs.py have consistent names.
179
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.
180
181
    def do(self, relpath):
2692.1.5 by Andrew Bennetts
Add translate_client_path calls to bzrlib/smart/vfs.py
182
        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.
183
        self._relpath = relpath
184
2018.5.5 by Andrew Bennetts
Pass body_bytes directly to SmartServerRequest.do_body
185
    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.
186
        """accept offsets for a readv request."""
2018.5.5 by Andrew Bennetts
Pass body_bytes directly to SmartServerRequest.do_body
187
        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.
188
        backing_bytes = ''.join(bytes for offset, bytes in
189
            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.
190
        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.
191
192
    def _deserialise_offsets(self, text):
193
        # XXX: FIXME this should be on the protocol object.
194
        offsets = []
195
        for line in text.split('\n'):
196
            if not line:
197
                continue
198
            start, length = line.split(',')
199
            offsets.append((int(start), int(length)))
200
        return offsets
201
202
2018.5.37 by Andrew Bennetts
Make sure all the request handlers in bzrlib/smart/vfs.py have consistent names.
203
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.
204
205
    def do(self, rel_from, rel_to):
2692.1.5 by Andrew Bennetts
Add translate_client_path calls to bzrlib/smart/vfs.py
206
        rel_from = self.translate_client_path(rel_from)
207
        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.
208
        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.
209
        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.
210
211
2018.5.37 by Andrew Bennetts
Make sure all the request handlers in bzrlib/smart/vfs.py have consistent names.
212
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.
213
214
    def do(self, relpath):
2692.1.5 by Andrew Bennetts
Add translate_client_path calls to bzrlib/smart/vfs.py
215
        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.
216
        self._backing_transport.rmdir(relpath)
2432.4.5 by Robert Collins
Make using SuccessfulSmartServerResponse and FailedSmartServerResponse mandatory rather than optional in smart server logic.
217
        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.
218
219
2018.5.37 by Andrew Bennetts
Make sure all the request handlers in bzrlib/smart/vfs.py have consistent names.
220
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.
221
222
    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.
223
        if not relpath.endswith('/'):
224
            relpath += '/'
2692.1.5 by Andrew Bennetts
Add translate_client_path calls to bzrlib/smart/vfs.py
225
        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.
226
        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.
227
        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.
228
            ('stat', str(stat.st_size), oct(stat.st_mode)))
229