~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: 2009-01-13 05:14:24 UTC
  • mfrom: (3936.1.3 integration)
  • Revision ID: pqm@pqm.ubuntu.com-20090113051424-nrk3zkfe09h46i9y
(mbp) merge 1.11 and advance to 1.12

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
        backing_bytes = self._backing_transport.get_bytes(relpath)
 
76
        return request.SuccessfulSmartServerResponse(('ok',), backing_bytes)
 
77
 
 
78
 
 
79
class AppendRequest(VfsRequest):
 
80
 
 
81
    def do(self, relpath, mode):
 
82
        relpath = self.translate_client_path(relpath)
 
83
        self._relpath = relpath
 
84
        self._mode = _deserialise_optional_mode(mode)
 
85
    
 
86
    def do_body(self, body_bytes):
 
87
        old_length = self._backing_transport.append_bytes(
 
88
            self._relpath, body_bytes, self._mode)
 
89
        return request.SuccessfulSmartServerResponse(('appended', '%d' % old_length))
 
90
 
 
91
 
 
92
class DeleteRequest(VfsRequest):
 
93
 
 
94
    def do(self, relpath):
 
95
        relpath = self.translate_client_path(relpath)
 
96
        self._backing_transport.delete(relpath)
 
97
        return request.SuccessfulSmartServerResponse(('ok', ))
 
98
 
 
99
 
 
100
class IterFilesRecursiveRequest(VfsRequest):
 
101
 
 
102
    def do(self, relpath):
 
103
        if not relpath.endswith('/'):
 
104
            relpath += '/'
 
105
        relpath = self.translate_client_path(relpath)
 
106
        transport = self._backing_transport.clone(relpath)
 
107
        filenames = transport.iter_files_recursive()
 
108
        return request.SuccessfulSmartServerResponse(('names',) + tuple(filenames))
 
109
 
 
110
 
 
111
class ListDirRequest(VfsRequest):
 
112
 
 
113
    def do(self, relpath):
 
114
        if not relpath.endswith('/'):
 
115
            relpath += '/'
 
116
        relpath = self.translate_client_path(relpath)
 
117
        filenames = self._backing_transport.list_dir(relpath)
 
118
        return request.SuccessfulSmartServerResponse(('names',) + tuple(filenames))
 
119
 
 
120
 
 
121
class MkdirRequest(VfsRequest):
 
122
 
 
123
    def do(self, relpath, mode):
 
124
        relpath = self.translate_client_path(relpath)
 
125
        self._backing_transport.mkdir(relpath,
 
126
                                      _deserialise_optional_mode(mode))
 
127
        return request.SuccessfulSmartServerResponse(('ok',))
 
128
 
 
129
 
 
130
class MoveRequest(VfsRequest):
 
131
 
 
132
    def do(self, rel_from, rel_to):
 
133
        rel_from = self.translate_client_path(rel_from)
 
134
        rel_to = self.translate_client_path(rel_to)
 
135
        self._backing_transport.move(rel_from, rel_to)
 
136
        return request.SuccessfulSmartServerResponse(('ok',))
 
137
 
 
138
 
 
139
class PutRequest(VfsRequest):
 
140
 
 
141
    def do(self, relpath, mode):
 
142
        relpath = self.translate_client_path(relpath)
 
143
        self._relpath = relpath
 
144
        self._mode = _deserialise_optional_mode(mode)
 
145
 
 
146
    def do_body(self, body_bytes):
 
147
        self._backing_transport.put_bytes(self._relpath, body_bytes, self._mode)
 
148
        return request.SuccessfulSmartServerResponse(('ok',))
 
149
 
 
150
 
 
151
class PutNonAtomicRequest(VfsRequest):
 
152
 
 
153
    def do(self, relpath, mode, create_parent, dir_mode):
 
154
        relpath = self.translate_client_path(relpath)
 
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
 
 
161
    def do_body(self, body_bytes):
 
162
        self._backing_transport.put_bytes_non_atomic(self._relpath,
 
163
                body_bytes,
 
164
                mode=self._mode,
 
165
                create_parent_dir=self._create_parent,
 
166
                dir_mode=self._dir_mode)
 
167
        return request.SuccessfulSmartServerResponse(('ok',))
 
168
 
 
169
 
 
170
class ReadvRequest(VfsRequest):
 
171
 
 
172
    def do(self, relpath):
 
173
        relpath = self.translate_client_path(relpath)
 
174
        self._relpath = relpath
 
175
 
 
176
    def do_body(self, body_bytes):
 
177
        """accept offsets for a readv request."""
 
178
        offsets = self._deserialise_offsets(body_bytes)
 
179
        backing_bytes = ''.join(bytes for offset, bytes in
 
180
            self._backing_transport.readv(self._relpath, offsets))
 
181
        return request.SuccessfulSmartServerResponse(('readv',), backing_bytes)
 
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
 
 
194
class RenameRequest(VfsRequest):
 
195
 
 
196
    def do(self, rel_from, rel_to):
 
197
        rel_from = self.translate_client_path(rel_from)
 
198
        rel_to = self.translate_client_path(rel_to)
 
199
        self._backing_transport.rename(rel_from, rel_to)
 
200
        return request.SuccessfulSmartServerResponse(('ok', ))
 
201
 
 
202
 
 
203
class RmdirRequest(VfsRequest):
 
204
 
 
205
    def do(self, relpath):
 
206
        relpath = self.translate_client_path(relpath)
 
207
        self._backing_transport.rmdir(relpath)
 
208
        return request.SuccessfulSmartServerResponse(('ok', ))
 
209
 
 
210
 
 
211
class StatRequest(VfsRequest):
 
212
 
 
213
    def do(self, relpath):
 
214
        if not relpath.endswith('/'):
 
215
            relpath += '/'
 
216
        relpath = self.translate_client_path(relpath)
 
217
        stat = self._backing_transport.stat(relpath)
 
218
        return request.SuccessfulSmartServerResponse(
 
219
            ('stat', str(stat.st_size), oct(stat.st_mode)))
 
220