~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/smart/vfs.py

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2008-09-03 08:32:49 UTC
  • mfrom: (1739.2.13 integration)
  • Revision ID: pqm@pqm.ubuntu.com-20080903083249-e76ygekseh1peidm
Fix typo in ReadDirFeature.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Copyright (C) 2006, 2007 Canonical Ltd
 
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.
 
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.
 
25
"""
 
26
 
 
27
import os
 
28
 
 
29
from bzrlib import errors
 
30
from bzrlib.smart import request
 
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
 
 
42
def vfs_enabled():
 
43
    """Is the VFS enabled ?
 
44
 
 
45
    the VFS is disabled when the BZR_NO_SMART_VFS environment variable is set.
 
46
 
 
47
    :return: True if it is enabled.
 
48
    """
 
49
    return not 'BZR_NO_SMART_VFS' in os.environ
 
50
 
 
51
 
 
52
class VfsRequest(request.SmartServerRequest):
 
53
    """Base class for VFS requests.
 
54
    
 
55
    VFS requests are disabled if vfs_enabled() returns False.
 
56
    """
 
57
 
 
58
    def _check_enabled(self):
 
59
        if not vfs_enabled():
 
60
            raise errors.DisabledMethod(self.__class__.__name__)
 
61
 
 
62
 
 
63
class HasRequest(VfsRequest):
 
64
 
 
65
    def do(self, relpath):
 
66
        relpath = self.translate_client_path(relpath)
 
67
        r = self._backing_transport.has(relpath) and 'yes' or 'no'
 
68
        return request.SuccessfulSmartServerResponse((r,))
 
69
 
 
70
 
 
71
class GetRequest(VfsRequest):
 
72
 
 
73
    def do(self, relpath):
 
74
        relpath = self.translate_client_path(relpath)
 
75
        try:
 
76
            backing_bytes = self._backing_transport.get_bytes(relpath)
 
77
        except errors.ReadError:
 
78
            # cannot read the file
 
79
            return request.FailedSmartServerResponse(('ReadError', ))
 
80
        except errors.PermissionDenied:
 
81
            return request.FailedSmartServerResponse(('PermissionDenied',))
 
82
        return request.SuccessfulSmartServerResponse(('ok',), backing_bytes)
 
83
 
 
84
 
 
85
class AppendRequest(VfsRequest):
 
86
 
 
87
    def do(self, relpath, mode):
 
88
        relpath = self.translate_client_path(relpath)
 
89
        self._relpath = relpath
 
90
        self._mode = _deserialise_optional_mode(mode)
 
91
    
 
92
    def do_body(self, body_bytes):
 
93
        old_length = self._backing_transport.append_bytes(
 
94
            self._relpath, body_bytes, self._mode)
 
95
        return request.SuccessfulSmartServerResponse(('appended', '%d' % old_length))
 
96
 
 
97
 
 
98
class DeleteRequest(VfsRequest):
 
99
 
 
100
    def do(self, relpath):
 
101
        relpath = self.translate_client_path(relpath)
 
102
        self._backing_transport.delete(relpath)
 
103
        return request.SuccessfulSmartServerResponse(('ok', ))
 
104
 
 
105
 
 
106
class IterFilesRecursiveRequest(VfsRequest):
 
107
 
 
108
    def do(self, relpath):
 
109
        if not relpath.endswith('/'):
 
110
            relpath += '/'
 
111
        relpath = self.translate_client_path(relpath)
 
112
        transport = self._backing_transport.clone(relpath)
 
113
        filenames = transport.iter_files_recursive()
 
114
        return request.SuccessfulSmartServerResponse(('names',) + tuple(filenames))
 
115
 
 
116
 
 
117
class ListDirRequest(VfsRequest):
 
118
 
 
119
    def do(self, relpath):
 
120
        if not relpath.endswith('/'):
 
121
            relpath += '/'
 
122
        relpath = self.translate_client_path(relpath)
 
123
        filenames = self._backing_transport.list_dir(relpath)
 
124
        return request.SuccessfulSmartServerResponse(('names',) + tuple(filenames))
 
125
 
 
126
 
 
127
class MkdirRequest(VfsRequest):
 
128
 
 
129
    def do(self, relpath, mode):
 
130
        relpath = self.translate_client_path(relpath)
 
131
        self._backing_transport.mkdir(relpath,
 
132
                                      _deserialise_optional_mode(mode))
 
133
        return request.SuccessfulSmartServerResponse(('ok',))
 
134
 
 
135
 
 
136
class MoveRequest(VfsRequest):
 
137
 
 
138
    def do(self, rel_from, rel_to):
 
139
        rel_from = self.translate_client_path(rel_from)
 
140
        rel_to = self.translate_client_path(rel_to)
 
141
        self._backing_transport.move(rel_from, rel_to)
 
142
        return request.SuccessfulSmartServerResponse(('ok',))
 
143
 
 
144
 
 
145
class PutRequest(VfsRequest):
 
146
 
 
147
    def do(self, relpath, mode):
 
148
        relpath = self.translate_client_path(relpath)
 
149
        self._relpath = relpath
 
150
        self._mode = _deserialise_optional_mode(mode)
 
151
 
 
152
    def do_body(self, body_bytes):
 
153
        self._backing_transport.put_bytes(self._relpath, body_bytes, self._mode)
 
154
        return request.SuccessfulSmartServerResponse(('ok',))
 
155
 
 
156
 
 
157
class PutNonAtomicRequest(VfsRequest):
 
158
 
 
159
    def do(self, relpath, mode, create_parent, dir_mode):
 
160
        relpath = self.translate_client_path(relpath)
 
161
        self._relpath = relpath
 
162
        self._dir_mode = _deserialise_optional_mode(dir_mode)
 
163
        self._mode = _deserialise_optional_mode(mode)
 
164
        # a boolean would be nicer XXX
 
165
        self._create_parent = (create_parent == 'T')
 
166
 
 
167
    def do_body(self, body_bytes):
 
168
        self._backing_transport.put_bytes_non_atomic(self._relpath,
 
169
                body_bytes,
 
170
                mode=self._mode,
 
171
                create_parent_dir=self._create_parent,
 
172
                dir_mode=self._dir_mode)
 
173
        return request.SuccessfulSmartServerResponse(('ok',))
 
174
 
 
175
 
 
176
class ReadvRequest(VfsRequest):
 
177
 
 
178
    def do(self, relpath):
 
179
        relpath = self.translate_client_path(relpath)
 
180
        self._relpath = relpath
 
181
 
 
182
    def do_body(self, body_bytes):
 
183
        """accept offsets for a readv request."""
 
184
        offsets = self._deserialise_offsets(body_bytes)
 
185
        backing_bytes = ''.join(bytes for offset, bytes in
 
186
            self._backing_transport.readv(self._relpath, offsets))
 
187
        return request.SuccessfulSmartServerResponse(('readv',), backing_bytes)
 
188
 
 
189
    def _deserialise_offsets(self, text):
 
190
        # XXX: FIXME this should be on the protocol object.
 
191
        offsets = []
 
192
        for line in text.split('\n'):
 
193
            if not line:
 
194
                continue
 
195
            start, length = line.split(',')
 
196
            offsets.append((int(start), int(length)))
 
197
        return offsets
 
198
 
 
199
 
 
200
class RenameRequest(VfsRequest):
 
201
 
 
202
    def do(self, rel_from, rel_to):
 
203
        rel_from = self.translate_client_path(rel_from)
 
204
        rel_to = self.translate_client_path(rel_to)
 
205
        self._backing_transport.rename(rel_from, rel_to)
 
206
        return request.SuccessfulSmartServerResponse(('ok', ))
 
207
 
 
208
 
 
209
class RmdirRequest(VfsRequest):
 
210
 
 
211
    def do(self, relpath):
 
212
        relpath = self.translate_client_path(relpath)
 
213
        self._backing_transport.rmdir(relpath)
 
214
        return request.SuccessfulSmartServerResponse(('ok', ))
 
215
 
 
216
 
 
217
class StatRequest(VfsRequest):
 
218
 
 
219
    def do(self, relpath):
 
220
        if not relpath.endswith('/'):
 
221
            relpath += '/'
 
222
        relpath = self.translate_client_path(relpath)
 
223
        stat = self._backing_transport.stat(relpath)
 
224
        return request.SuccessfulSmartServerResponse(
 
225
            ('stat', str(stat.st_size), oct(stat.st_mode)))
 
226