~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/smart/vfs.py

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