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.
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.
27
from bzrlib.smart import request
30
def _deserialise_optional_mode(mode):
31
# XXX: FIXME this should be on the protocol object. Later protocol versions
32
# might serialise modes differently.
39
class HasRequest(request.SmartServerRequest):
41
def do(self, relpath):
42
r = self._backing_transport.has(relpath) and 'yes' or 'no'
43
return request.SmartServerResponse((r,))
46
class GetRequest(request.SmartServerRequest):
48
def do(self, relpath):
49
backing_bytes = self._backing_transport.get_bytes(relpath)
50
return request.SmartServerResponse(('ok',), backing_bytes)
53
class AppendRequest(request.SmartServerRequest):
55
def do(self, relpath, mode):
56
self._relpath = relpath
57
self._mode = _deserialise_optional_mode(mode)
59
def do_body(self, body_bytes):
60
old_length = self._backing_transport.append_bytes(
61
self._relpath, body_bytes, self._mode)
62
return request.SmartServerResponse(('appended', '%d' % old_length))
65
class DeleteRequest(request.SmartServerRequest):
67
def do(self, relpath):
68
self._backing_transport.delete(relpath)
69
return request.SmartServerResponse(('ok', ))
72
class IterFilesRecursive(request.SmartServerRequest):
74
def do(self, relpath):
75
transport = self._backing_transport.clone(relpath)
76
filenames = transport.iter_files_recursive()
77
return request.SmartServerResponse(('names',) + tuple(filenames))
80
class ListDirRequest(request.SmartServerRequest):
82
def do(self, relpath):
83
filenames = self._backing_transport.list_dir(relpath)
84
return request.SmartServerResponse(('names',) + tuple(filenames))
87
class MkdirCommand(request.SmartServerRequest):
89
def do(self, relpath, mode):
90
self._backing_transport.mkdir(relpath,
91
_deserialise_optional_mode(mode))
92
return request.SmartServerResponse(('ok',))
95
class MoveCommand(request.SmartServerRequest):
97
def do(self, rel_from, rel_to):
98
self._backing_transport.move(rel_from, rel_to)
99
return request.SmartServerResponse(('ok',))
102
class PutCommand(request.SmartServerRequest):
104
def do(self, relpath, mode):
105
self._relpath = relpath
106
self._mode = _deserialise_optional_mode(mode)
108
def do_body(self, body_bytes):
109
self._backing_transport.put_bytes(self._relpath, body_bytes, self._mode)
110
return request.SmartServerResponse(('ok',))
113
class PutNonAtomicCommand(request.SmartServerRequest):
115
def do(self, relpath, mode, create_parent, dir_mode):
116
self._relpath = relpath
117
self._dir_mode = _deserialise_optional_mode(dir_mode)
118
self._mode = _deserialise_optional_mode(mode)
119
# a boolean would be nicer XXX
120
self._create_parent = (create_parent == 'T')
122
def do_body(self, body_bytes):
123
self._backing_transport.put_bytes_non_atomic(self._relpath,
126
create_parent_dir=self._create_parent,
127
dir_mode=self._dir_mode)
128
return request.SmartServerResponse(('ok',))
131
class ReadvCommand(request.SmartServerRequest):
133
def do(self, relpath):
134
self._relpath = relpath
136
def do_body(self, body_bytes):
137
"""accept offsets for a readv request."""
138
offsets = self._deserialise_offsets(body_bytes)
139
backing_bytes = ''.join(bytes for offset, bytes in
140
self._backing_transport.readv(self._relpath, offsets))
141
return request.SmartServerResponse(('readv',), backing_bytes)
143
def _deserialise_offsets(self, text):
144
# XXX: FIXME this should be on the protocol object.
146
for line in text.split('\n'):
149
start, length = line.split(',')
150
offsets.append((int(start), int(length)))
154
class RenameCommand(request.SmartServerRequest):
156
def do(self, rel_from, rel_to):
157
self._backing_transport.rename(rel_from, rel_to)
158
return request.SmartServerResponse(('ok', ))
161
class RmdirCommand(request.SmartServerRequest):
163
def do(self, relpath):
164
self._backing_transport.rmdir(relpath)
165
return request.SmartServerResponse(('ok', ))
168
class StatCommand(request.SmartServerRequest):
170
def do(self, relpath):
171
stat = self._backing_transport.stat(relpath)
172
return request.SmartServerResponse(
173
('stat', str(stat.st_size), oct(stat.st_mode)))