/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/smart/vfs.py

  • Committer: Vincent Ladeuil
  • Date: 2012-01-18 14:09:19 UTC
  • mto: This revision was merged to the branch mainline in revision 6468.
  • Revision ID: v.ladeuil+lp@free.fr-20120118140919-rlvdrhpc0nq1lbwi
Change set/remove to require a lock for the branch config files.

This means that tests (or any plugin for that matter) do not requires an
explicit lock on the branch anymore to change a single option. This also
means the optimisation becomes "opt-in" and as such won't be as
spectacular as it may be and/or harder to get right (nothing fails
anymore).

This reduces the diff by ~300 lines.

Code/tests that were updating more than one config option is still taking
a lock to at least avoid some IOs and demonstrate the benefits through
the decreased number of hpss calls.

The duplication between BranchStack and BranchOnlyStack will be removed
once the same sharing is in place for local config files, at which point
the Stack class itself may be able to host the changes.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Copyright (C) 2006-2010 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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
from __future__ import absolute_import
 
28
 
 
29
import os
 
30
 
 
31
from bzrlib import errors
 
32
from bzrlib import urlutils
 
33
from bzrlib.smart import request
 
34
 
 
35
 
 
36
def _deserialise_optional_mode(mode):
 
37
    # XXX: FIXME this should be on the protocol object.  Later protocol versions
 
38
    # might serialise modes differently.
 
39
    if mode == '':
 
40
        return None
 
41
    else:
 
42
        return int(mode)
 
43
 
 
44
 
 
45
def vfs_enabled():
 
46
    """Is the VFS enabled ?
 
47
 
 
48
    the VFS is disabled when the BZR_NO_SMART_VFS environment variable is set.
 
49
 
 
50
    :return: True if it is enabled.
 
51
    """
 
52
    return not 'BZR_NO_SMART_VFS' in os.environ
 
53
 
 
54
 
 
55
class VfsRequest(request.SmartServerRequest):
 
56
    """Base class for VFS requests.
 
57
 
 
58
    VFS requests are disabled if vfs_enabled() returns False.
 
59
    """
 
60
 
 
61
    def _check_enabled(self):
 
62
        if not vfs_enabled():
 
63
            raise errors.DisabledMethod(self.__class__.__name__)
 
64
 
 
65
    def translate_client_path(self, relpath):
 
66
        # VFS requests are made with escaped paths so the escaping done in
 
67
        # SmartServerRequest.translate_client_path leads to double escaping.
 
68
        # Remove it here -- the fact that the result is still escaped means
 
69
        # that the str() will not fail on valid input.
 
70
        x = request.SmartServerRequest.translate_client_path(self, relpath)
 
71
        return str(urlutils.unescape(x))
 
72
 
 
73
 
 
74
class HasRequest(VfsRequest):
 
75
 
 
76
    def do(self, relpath):
 
77
        relpath = self.translate_client_path(relpath)
 
78
        r = self._backing_transport.has(relpath) and 'yes' or 'no'
 
79
        return request.SuccessfulSmartServerResponse((r,))
 
80
 
 
81
 
 
82
class GetRequest(VfsRequest):
 
83
 
 
84
    def do(self, relpath):
 
85
        relpath = self.translate_client_path(relpath)
 
86
        backing_bytes = self._backing_transport.get_bytes(relpath)
 
87
        return request.SuccessfulSmartServerResponse(('ok',), backing_bytes)
 
88
 
 
89
 
 
90
class AppendRequest(VfsRequest):
 
91
 
 
92
    def do(self, relpath, mode):
 
93
        relpath = self.translate_client_path(relpath)
 
94
        self._relpath = relpath
 
95
        self._mode = _deserialise_optional_mode(mode)
 
96
 
 
97
    def do_body(self, body_bytes):
 
98
        old_length = self._backing_transport.append_bytes(
 
99
            self._relpath, body_bytes, self._mode)
 
100
        return request.SuccessfulSmartServerResponse(('appended', '%d' % old_length))
 
101
 
 
102
 
 
103
class DeleteRequest(VfsRequest):
 
104
 
 
105
    def do(self, relpath):
 
106
        relpath = self.translate_client_path(relpath)
 
107
        self._backing_transport.delete(relpath)
 
108
        return request.SuccessfulSmartServerResponse(('ok', ))
 
109
 
 
110
 
 
111
class IterFilesRecursiveRequest(VfsRequest):
 
112
 
 
113
    def do(self, relpath):
 
114
        if not relpath.endswith('/'):
 
115
            relpath += '/'
 
116
        relpath = self.translate_client_path(relpath)
 
117
        transport = self._backing_transport.clone(relpath)
 
118
        filenames = transport.iter_files_recursive()
 
119
        return request.SuccessfulSmartServerResponse(('names',) + tuple(filenames))
 
120
 
 
121
 
 
122
class ListDirRequest(VfsRequest):
 
123
 
 
124
    def do(self, relpath):
 
125
        if not relpath.endswith('/'):
 
126
            relpath += '/'
 
127
        relpath = self.translate_client_path(relpath)
 
128
        filenames = self._backing_transport.list_dir(relpath)
 
129
        return request.SuccessfulSmartServerResponse(('names',) + tuple(filenames))
 
130
 
 
131
 
 
132
class MkdirRequest(VfsRequest):
 
133
 
 
134
    def do(self, relpath, mode):
 
135
        relpath = self.translate_client_path(relpath)
 
136
        self._backing_transport.mkdir(relpath,
 
137
                                      _deserialise_optional_mode(mode))
 
138
        return request.SuccessfulSmartServerResponse(('ok',))
 
139
 
 
140
 
 
141
class MoveRequest(VfsRequest):
 
142
 
 
143
    def do(self, rel_from, rel_to):
 
144
        rel_from = self.translate_client_path(rel_from)
 
145
        rel_to = self.translate_client_path(rel_to)
 
146
        self._backing_transport.move(rel_from, rel_to)
 
147
        return request.SuccessfulSmartServerResponse(('ok',))
 
148
 
 
149
 
 
150
class PutRequest(VfsRequest):
 
151
 
 
152
    def do(self, relpath, mode):
 
153
        relpath = self.translate_client_path(relpath)
 
154
        self._relpath = relpath
 
155
        self._mode = _deserialise_optional_mode(mode)
 
156
 
 
157
    def do_body(self, body_bytes):
 
158
        self._backing_transport.put_bytes(self._relpath, body_bytes, self._mode)
 
159
        return request.SuccessfulSmartServerResponse(('ok',))
 
160
 
 
161
 
 
162
class PutNonAtomicRequest(VfsRequest):
 
163
 
 
164
    def do(self, relpath, mode, create_parent, dir_mode):
 
165
        relpath = self.translate_client_path(relpath)
 
166
        self._relpath = relpath
 
167
        self._dir_mode = _deserialise_optional_mode(dir_mode)
 
168
        self._mode = _deserialise_optional_mode(mode)
 
169
        # a boolean would be nicer XXX
 
170
        self._create_parent = (create_parent == 'T')
 
171
 
 
172
    def do_body(self, body_bytes):
 
173
        self._backing_transport.put_bytes_non_atomic(self._relpath,
 
174
                body_bytes,
 
175
                mode=self._mode,
 
176
                create_parent_dir=self._create_parent,
 
177
                dir_mode=self._dir_mode)
 
178
        return request.SuccessfulSmartServerResponse(('ok',))
 
179
 
 
180
 
 
181
class ReadvRequest(VfsRequest):
 
182
 
 
183
    def do(self, relpath):
 
184
        relpath = self.translate_client_path(relpath)
 
185
        self._relpath = relpath
 
186
 
 
187
    def do_body(self, body_bytes):
 
188
        """accept offsets for a readv request."""
 
189
        offsets = self._deserialise_offsets(body_bytes)
 
190
        backing_bytes = ''.join(bytes for offset, bytes in
 
191
            self._backing_transport.readv(self._relpath, offsets))
 
192
        return request.SuccessfulSmartServerResponse(('readv',), backing_bytes)
 
193
 
 
194
    def _deserialise_offsets(self, text):
 
195
        # XXX: FIXME this should be on the protocol object.
 
196
        offsets = []
 
197
        for line in text.split('\n'):
 
198
            if not line:
 
199
                continue
 
200
            start, length = line.split(',')
 
201
            offsets.append((int(start), int(length)))
 
202
        return offsets
 
203
 
 
204
 
 
205
class RenameRequest(VfsRequest):
 
206
 
 
207
    def do(self, rel_from, rel_to):
 
208
        rel_from = self.translate_client_path(rel_from)
 
209
        rel_to = self.translate_client_path(rel_to)
 
210
        self._backing_transport.rename(rel_from, rel_to)
 
211
        return request.SuccessfulSmartServerResponse(('ok', ))
 
212
 
 
213
 
 
214
class RmdirRequest(VfsRequest):
 
215
 
 
216
    def do(self, relpath):
 
217
        relpath = self.translate_client_path(relpath)
 
218
        self._backing_transport.rmdir(relpath)
 
219
        return request.SuccessfulSmartServerResponse(('ok', ))
 
220
 
 
221
 
 
222
class StatRequest(VfsRequest):
 
223
 
 
224
    def do(self, relpath):
 
225
        if not relpath.endswith('/'):
 
226
            relpath += '/'
 
227
        relpath = self.translate_client_path(relpath)
 
228
        stat = self._backing_transport.stat(relpath)
 
229
        return request.SuccessfulSmartServerResponse(
 
230
            ('stat', str(stat.st_size), oct(stat.st_mode)))
 
231