1
# Copyright (C) 2006 Canonical Ltd
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.
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.
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
17
"""VFS operations for the smart server.
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.
24
from bzrlib.transport.smart import protocol, request
29
def register_command(command):
30
vfs_commands[command.method] = command
33
def _deserialise_optional_mode(mode):
34
# XXX: FIXME this should be on the protocol object. Later protocol versions
35
# might serialise modes differently.
42
class HasRequest(request.SmartServerRequest):
46
def do(self, relpath):
47
r = self._backing_transport.has(relpath) and 'yes' or 'no'
48
return protocol.SmartServerResponse((r,))
49
register_command(HasRequest)
52
class GetRequest(request.SmartServerRequest):
56
def do(self, relpath):
57
backing_bytes = self._backing_transport.get_bytes(relpath)
58
return protocol.SmartServerResponse(('ok',), backing_bytes)
59
register_command(GetRequest)
62
class AppendRequest(request.SmartServerRequest):
66
def do(self, relpath, mode):
67
self._relpath = relpath
68
self._mode = _deserialise_optional_mode(mode)
70
def do_body(self, body_bytes):
71
old_length = self._backing_transport.append_bytes(
72
self._relpath, body_bytes, self._mode)
73
return protocol.SmartServerResponse(('appended', '%d' % old_length))
75
register_command(AppendRequest)
78
class DeleteRequest(request.SmartServerRequest):
82
def do(self, relpath):
83
self._backing_transport.delete(relpath)
84
return protocol.SmartServerResponse(('ok', ))
85
register_command(DeleteRequest)
88
class IterFilesRecursive(request.SmartServerRequest):
90
method = 'iter_files_recursive'
92
def do(self, relpath):
93
transport = self._backing_transport.clone(relpath)
94
filenames = transport.iter_files_recursive()
95
return protocol.SmartServerResponse(('names',) + tuple(filenames))
96
register_command(IterFilesRecursive)
99
class ListDirRequest(request.SmartServerRequest):
103
def do(self, relpath):
104
filenames = self._backing_transport.list_dir(relpath)
105
return protocol.SmartServerResponse(('names',) + tuple(filenames))
106
register_command(ListDirRequest)
109
class MkdirCommand(request.SmartServerRequest):
113
def do(self, relpath, mode):
114
self._backing_transport.mkdir(relpath,
115
_deserialise_optional_mode(mode))
116
return protocol.SmartServerResponse(('ok',))
117
register_command(MkdirCommand)
120
class MoveCommand(request.SmartServerRequest):
124
def do(self, rel_from, rel_to):
125
self._backing_transport.move(rel_from, rel_to)
126
return protocol.SmartServerResponse(('ok',))
127
register_command(MoveCommand)
130
class PutCommand(request.SmartServerRequest):
134
def do(self, relpath, mode):
135
self._relpath = relpath
136
self._mode = _deserialise_optional_mode(mode)
138
def do_body(self, body_bytes):
139
self._backing_transport.put_bytes(self._relpath, body_bytes, self._mode)
140
return protocol.SmartServerResponse(('ok',))
141
register_command(PutCommand)
144
class PutNonAtomicCommand(request.SmartServerRequest):
146
method = 'put_non_atomic'
148
def do(self, relpath, mode, create_parent, dir_mode):
149
self._relpath = relpath
150
self._dir_mode = _deserialise_optional_mode(dir_mode)
151
self._mode = _deserialise_optional_mode(mode)
152
# a boolean would be nicer XXX
153
self._create_parent = (create_parent == 'T')
155
def do_body(self, body_bytes):
156
self._backing_transport.put_bytes_non_atomic(self._relpath,
159
create_parent_dir=self._create_parent,
160
dir_mode=self._dir_mode)
161
return protocol.SmartServerResponse(('ok',))
162
register_command(PutNonAtomicCommand)
165
class ReadvCommand(request.SmartServerRequest):
169
def do(self, relpath):
170
self._relpath = relpath
172
def do_body(self, body_bytes):
173
"""accept offsets for a readv request."""
174
offsets = self._deserialise_offsets(body_bytes)
175
backing_bytes = ''.join(bytes for offset, bytes in
176
self._backing_transport.readv(self._relpath, offsets))
177
return protocol.SmartServerResponse(('readv',), backing_bytes)
179
def _deserialise_offsets(self, text):
180
# XXX: FIXME this should be on the protocol object.
182
for line in text.split('\n'):
185
start, length = line.split(',')
186
offsets.append((int(start), int(length)))
188
register_command(ReadvCommand)
191
class RenameCommand(request.SmartServerRequest):
195
def do(self, rel_from, rel_to):
196
self._backing_transport.rename(rel_from, rel_to)
197
return protocol.SmartServerResponse(('ok', ))
198
register_command(RenameCommand)
201
class RmdirCommand(request.SmartServerRequest):
205
def do(self, relpath):
206
self._backing_transport.rmdir(relpath)
207
return protocol.SmartServerResponse(('ok', ))
208
register_command(RmdirCommand)
211
class StatCommand(request.SmartServerRequest):
215
def do(self, relpath):
216
stat = self._backing_transport.stat(relpath)
217
return protocol.SmartServerResponse(
218
('stat', str(stat.st_size), oct(stat.st_mode)))
219
register_command(StatCommand)
221
request.version_one_commands.update(vfs_commands)