~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/smart/vfs.py

  • Committer: Robert Collins
  • Date: 2007-07-04 08:08:13 UTC
  • mfrom: (2572 +trunk)
  • mto: This revision was merged to the branch mainline in revision 2587.
  • Revision ID: robertc@robertcollins.net-20070704080813-wzebx0r88fvwj5rq
Merge bzr.dev.

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