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