~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/smart/vfs.py

  • Committer: Robert Collins
  • Date: 2008-04-06 23:37:06 UTC
  • mto: This revision was merged to the branch mainline in revision 3340.
  • Revision ID: robertc@robertcollins.net-20080406233706-3md3w1c651a0pndm
Fix ReST table formatting in doc/developers/plugin-api.txt.

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