/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/smart/vfs.py

  • Committer: Andrew Bennetts
  • Date: 2007-12-13 22:22:58 UTC
  • mto: This revision was merged to the branch mainline in revision 3320.
  • Revision ID: andrew.bennetts@canonical.com-20071213222258-mh7mq5gtxqn4yceb
All WSGI tests passing, and manual testing works too.

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
        return request.SuccessfulSmartServerResponse(('ok',), backing_bytes)
 
81
 
 
82
 
 
83
class AppendRequest(VfsRequest):
 
84
 
 
85
    def do(self, relpath, mode):
 
86
        relpath = self.translate_client_path(relpath)
 
87
        self._relpath = relpath
 
88
        self._mode = _deserialise_optional_mode(mode)
 
89
    
 
90
    def do_body(self, body_bytes):
 
91
        old_length = self._backing_transport.append_bytes(
 
92
            self._relpath, body_bytes, self._mode)
 
93
        return request.SuccessfulSmartServerResponse(('appended', '%d' % old_length))
 
94
 
 
95
 
 
96
class DeleteRequest(VfsRequest):
 
97
 
 
98
    def do(self, relpath):
 
99
        relpath = self.translate_client_path(relpath)
 
100
        self._backing_transport.delete(relpath)
 
101
        return request.SuccessfulSmartServerResponse(('ok', ))
 
102
 
 
103
 
 
104
class IterFilesRecursiveRequest(VfsRequest):
 
105
 
 
106
    def do(self, relpath):
 
107
        if not relpath.endswith('/'):
 
108
            relpath += '/'
 
109
        relpath = self.translate_client_path(relpath)
 
110
        transport = self._backing_transport.clone(relpath)
 
111
        filenames = transport.iter_files_recursive()
 
112
        return request.SuccessfulSmartServerResponse(('names',) + tuple(filenames))
 
113
 
 
114
 
 
115
class ListDirRequest(VfsRequest):
 
116
 
 
117
    def do(self, relpath):
 
118
        if not relpath.endswith('/'):
 
119
            relpath += '/'
 
120
        relpath = self.translate_client_path(relpath)
 
121
        filenames = self._backing_transport.list_dir(relpath)
 
122
        return request.SuccessfulSmartServerResponse(('names',) + tuple(filenames))
 
123
 
 
124
 
 
125
class MkdirRequest(VfsRequest):
 
126
 
 
127
    def do(self, relpath, mode):
 
128
        relpath = self.translate_client_path(relpath)
 
129
        self._backing_transport.mkdir(relpath,
 
130
                                      _deserialise_optional_mode(mode))
 
131
        return request.SuccessfulSmartServerResponse(('ok',))
 
132
 
 
133
 
 
134
class MoveRequest(VfsRequest):
 
135
 
 
136
    def do(self, rel_from, rel_to):
 
137
        rel_from = self.translate_client_path(rel_from)
 
138
        rel_to = self.translate_client_path(rel_to)
 
139
        self._backing_transport.move(rel_from, rel_to)
 
140
        return request.SuccessfulSmartServerResponse(('ok',))
 
141
 
 
142
 
 
143
class PutRequest(VfsRequest):
 
144
 
 
145
    def do(self, relpath, mode):
 
146
        relpath = self.translate_client_path(relpath)
 
147
        self._relpath = relpath
 
148
        self._mode = _deserialise_optional_mode(mode)
 
149
 
 
150
    def do_body(self, body_bytes):
 
151
        self._backing_transport.put_bytes(self._relpath, body_bytes, self._mode)
 
152
        return request.SuccessfulSmartServerResponse(('ok',))
 
153
 
 
154
 
 
155
class PutNonAtomicRequest(VfsRequest):
 
156
 
 
157
    def do(self, relpath, mode, create_parent, dir_mode):
 
158
        relpath = self.translate_client_path(relpath)
 
159
        self._relpath = relpath
 
160
        self._dir_mode = _deserialise_optional_mode(dir_mode)
 
161
        self._mode = _deserialise_optional_mode(mode)
 
162
        # a boolean would be nicer XXX
 
163
        self._create_parent = (create_parent == 'T')
 
164
 
 
165
    def do_body(self, body_bytes):
 
166
        self._backing_transport.put_bytes_non_atomic(self._relpath,
 
167
                body_bytes,
 
168
                mode=self._mode,
 
169
                create_parent_dir=self._create_parent,
 
170
                dir_mode=self._dir_mode)
 
171
        return request.SuccessfulSmartServerResponse(('ok',))
 
172
 
 
173
 
 
174
class ReadvRequest(VfsRequest):
 
175
 
 
176
    def do(self, relpath):
 
177
        relpath = self.translate_client_path(relpath)
 
178
        self._relpath = relpath
 
179
 
 
180
    def do_body(self, body_bytes):
 
181
        """accept offsets for a readv request."""
 
182
        offsets = self._deserialise_offsets(body_bytes)
 
183
        backing_bytes = ''.join(bytes for offset, bytes in
 
184
            self._backing_transport.readv(self._relpath, offsets))
 
185
        return request.SuccessfulSmartServerResponse(('readv',), backing_bytes)
 
186
 
 
187
    def _deserialise_offsets(self, text):
 
188
        # XXX: FIXME this should be on the protocol object.
 
189
        offsets = []
 
190
        for line in text.split('\n'):
 
191
            if not line:
 
192
                continue
 
193
            start, length = line.split(',')
 
194
            offsets.append((int(start), int(length)))
 
195
        return offsets
 
196
 
 
197
 
 
198
class RenameRequest(VfsRequest):
 
199
 
 
200
    def do(self, rel_from, rel_to):
 
201
        rel_from = self.translate_client_path(rel_from)
 
202
        rel_to = self.translate_client_path(rel_to)
 
203
        self._backing_transport.rename(rel_from, rel_to)
 
204
        return request.SuccessfulSmartServerResponse(('ok', ))
 
205
 
 
206
 
 
207
class RmdirRequest(VfsRequest):
 
208
 
 
209
    def do(self, relpath):
 
210
        relpath = self.translate_client_path(relpath)
 
211
        self._backing_transport.rmdir(relpath)
 
212
        return request.SuccessfulSmartServerResponse(('ok', ))
 
213
 
 
214
 
 
215
class StatRequest(VfsRequest):
 
216
 
 
217
    def do(self, relpath):
 
218
        if not relpath.endswith('/'):
 
219
            relpath += '/'
 
220
        relpath = self.translate_client_path(relpath)
 
221
        stat = self._backing_transport.stat(relpath)
 
222
        return request.SuccessfulSmartServerResponse(
 
223
            ('stat', str(stat.st_size), oct(stat.st_mode)))
 
224