~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/transport/memory.py

  • Committer: Martin Pool
  • Date: 2009-06-16 04:28:19 UTC
  • mto: This revision was merged to the branch mainline in revision 4464.
  • Revision ID: mbp@sourcefrog.net-20090616042819-adz0sq9ct1ls8rrl
Move tools.doc_generate into bzrlib

Show diffs side-by-side

added added

removed removed

Lines of Context:
12
12
#
13
13
# You should have received a copy of the GNU General Public License
14
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
 
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
16
 
17
17
"""Implementation of Transport that uses memory for its storage.
18
18
 
27
27
from cStringIO import StringIO
28
28
import warnings
29
29
 
30
 
from bzrlib.errors import TransportError, NoSuchFile, FileExists, LockError
 
30
from bzrlib.errors import (
 
31
    FileExists,
 
32
    LockError,
 
33
    InProcessTransport,
 
34
    NoSuchFile,
 
35
    TransportError,
 
36
    )
31
37
from bzrlib.trace import mutter
32
 
from bzrlib.transport import (Transport, register_transport, Server)
 
38
from bzrlib.transport import (
 
39
    AppendBasedFileStream,
 
40
    _file_streams,
 
41
    LateReadError,
 
42
    register_transport,
 
43
    Server,
 
44
    Transport,
 
45
    )
33
46
import bzrlib.urlutils as urlutils
34
47
 
35
48
 
117
130
            raise NoSuchFile(relpath)
118
131
        del self._files[_abspath]
119
132
 
 
133
    def external_url(self):
 
134
        """See bzrlib.transport.Transport.external_url."""
 
135
        # MemoryTransport's are only accessible in-process
 
136
        # so we raise here
 
137
        raise InProcessTransport(self)
 
138
 
120
139
    def get(self, relpath):
121
140
        """See Transport.get()."""
122
141
        _abspath = self._abspath(relpath)
123
142
        if not _abspath in self._files:
124
 
            raise NoSuchFile(relpath)
 
143
            if _abspath in self._dirs:
 
144
                return LateReadError(relpath)
 
145
            else:
 
146
                raise NoSuchFile(relpath)
125
147
        return StringIO(self._files[_abspath][0])
126
148
 
127
149
    def put_file(self, relpath, f, mode=None):
128
150
        """See Transport.put_file()."""
129
151
        _abspath = self._abspath(relpath)
130
152
        self._check_parent(_abspath)
131
 
        self._files[_abspath] = (f.read(), mode)
 
153
        bytes = f.read()
 
154
        if type(bytes) is not str:
 
155
            # Although not strictly correct, we raise UnicodeEncodeError to be
 
156
            # compatible with other transports.
 
157
            raise UnicodeEncodeError(
 
158
                'undefined', bytes, 0, 1,
 
159
                'put_file must be given a file of bytes, not unicode.')
 
160
        self._files[_abspath] = (bytes, mode)
 
161
        return len(bytes)
132
162
 
133
163
    def mkdir(self, relpath, mode=None):
134
164
        """See Transport.mkdir()."""
138
168
            raise FileExists(relpath)
139
169
        self._dirs[_abspath]=mode
140
170
 
 
171
    def open_write_stream(self, relpath, mode=None):
 
172
        """See Transport.open_write_stream."""
 
173
        self.put_bytes(relpath, "", mode)
 
174
        result = AppendBasedFileStream(self, relpath)
 
175
        _file_streams[self.abspath(relpath)] = result
 
176
        return result
 
177
 
141
178
    def listable(self):
142
179
        """See Transport.listable."""
143
180
        return True
146
183
        for file in self._files:
147
184
            if file.startswith(self._cwd):
148
185
                yield urlutils.escape(file[len(self._cwd):])
149
 
    
 
186
 
150
187
    def list_dir(self, relpath):
151
188
        """See Transport.list_dir()."""
152
189
        _abspath = self._abspath(relpath)
185
222
                    del container[path]
186
223
        do_renames(self._files)
187
224
        do_renames(self._dirs)
188
 
    
 
225
 
189
226
    def rmdir(self, relpath):
190
227
        """See Transport.rmdir."""
191
228
        _abspath = self._abspath(relpath)
192
229
        if _abspath in self._files:
193
230
            self._translate_error(IOError(errno.ENOTDIR, relpath), relpath)
194
231
        for path in self._files:
195
 
            if path.startswith(_abspath):
 
232
            if path.startswith(_abspath + '/'):
196
233
                self._translate_error(IOError(errno.ENOTEMPTY, relpath),
197
234
                                      relpath)
198
235
        for path in self._dirs:
199
 
            if path.startswith(_abspath) and path != _abspath:
 
236
            if path.startswith(_abspath + '/') and path != _abspath:
200
237
                self._translate_error(IOError(errno.ENOTEMPTY, relpath), relpath)
201
238
        if not _abspath in self._dirs:
202
239
            raise NoSuchFile(relpath)
206
243
        """See Transport.stat()."""
207
244
        _abspath = self._abspath(relpath)
208
245
        if _abspath in self._files:
209
 
            return MemoryStat(len(self._files[_abspath][0]), False, 
 
246
            return MemoryStat(len(self._files[_abspath][0]), False,
210
247
                              self._files[_abspath][1])
211
248
        elif _abspath in self._dirs:
212
249
            return MemoryStat(0, True, self._dirs[_abspath])
224
261
    def _abspath(self, relpath):
225
262
        """Generate an internal absolute path."""
226
263
        relpath = urlutils.unescape(relpath)
227
 
        if relpath.find('..') != -1:
228
 
            raise AssertionError('relpath contains ..')
229
 
        if relpath == '':
230
 
            return '/'
231
 
        if relpath[0] == '/':
 
264
        if relpath[:1] == '/':
232
265
            return relpath
233
 
        if relpath == '.':
234
 
            if (self._cwd == '/'):
235
 
                return self._cwd
236
 
            return self._cwd[:-1]
237
 
        if relpath.endswith('/'):
238
 
            relpath = relpath[:-1]
239
 
        if relpath.startswith('./'):
240
 
            relpath = relpath[2:]
241
 
        return self._cwd + relpath
 
266
        cwd_parts = self._cwd.split('/')
 
267
        rel_parts = relpath.split('/')
 
268
        r = []
 
269
        for i in cwd_parts + rel_parts:
 
270
            if i == '..':
 
271
                if not r:
 
272
                    raise ValueError("illegal relpath %r under %r"
 
273
                        % (relpath, self._cwd))
 
274
                r = r[:-1]
 
275
            elif i == '.' or i == '':
 
276
                pass
 
277
            else:
 
278
                r.append(i)
 
279
        return '/' + '/'.join(r)
242
280
 
243
281
 
244
282
class _MemoryLock(object):
245
283
    """This makes a lock."""
246
284
 
247
285
    def __init__(self, path, transport):
248
 
        assert isinstance(transport, MemoryTransport)
249
286
        self.path = path
250
287
        self.transport = transport
251
288
        if self.path in self.transport._locks: