~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/transport/memory.py

  • Committer: Patch Queue Manager
  • Date: 2015-09-30 16:43:21 UTC
  • mfrom: (6603.2.2 fix-keep-dirty)
  • Revision ID: pqm@pqm.ubuntu.com-20150930164321-ct2v2qnmvimqt8qf
(vila) Avoid associating dirty patch headers with the previous file in the
 patch. (Colin Watson)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005, 2006 Canonical Ltd
 
1
# Copyright (C) 2005-2010 Canonical Ltd
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
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
 
20
20
so this is primarily useful for testing.
21
21
"""
22
22
 
 
23
from __future__ import absolute_import
 
24
 
23
25
import os
24
26
import errno
25
 
import re
26
27
from stat import S_IFREG, S_IFDIR
27
28
from cStringIO import StringIO
28
 
import warnings
29
29
 
30
 
from bzrlib.errors import TransportError, NoSuchFile, FileExists, LockError
31
 
from bzrlib.trace import mutter
32
 
from bzrlib.transport import (Transport, register_transport, Server)
33
 
import bzrlib.urlutils as urlutils
 
30
from bzrlib import (
 
31
    transport,
 
32
    urlutils,
 
33
    )
 
34
from bzrlib.errors import (
 
35
    FileExists,
 
36
    LockError,
 
37
    InProcessTransport,
 
38
    NoSuchFile,
 
39
    )
 
40
from bzrlib.transport import (
 
41
    AppendBasedFileStream,
 
42
    _file_streams,
 
43
    LateReadError,
 
44
    )
34
45
 
35
46
 
36
47
 
48
59
            self.st_mode = S_IFDIR | perms
49
60
 
50
61
 
51
 
class MemoryTransport(Transport):
 
62
class MemoryTransport(transport.Transport):
52
63
    """This is an in memory file system for transient data storage."""
53
64
 
54
65
    def __init__(self, url=""):
68
79
 
69
80
    def clone(self, offset=None):
70
81
        """See Transport.clone()."""
71
 
        path = self._combine_paths(self._cwd, offset)
 
82
        path = urlutils.URL._combine_paths(self._cwd, offset)
72
83
        if len(path) == 0 or path[-1] != '/':
73
84
            path += '/'
74
85
        url = self._scheme + path
75
 
        result = MemoryTransport(url)
 
86
        result = self.__class__(url)
76
87
        result._dirs = self._dirs
77
88
        result._files = self._files
78
89
        result._locks = self._locks
117
128
            raise NoSuchFile(relpath)
118
129
        del self._files[_abspath]
119
130
 
 
131
    def external_url(self):
 
132
        """See bzrlib.transport.Transport.external_url."""
 
133
        # MemoryTransport's are only accessible in-process
 
134
        # so we raise here
 
135
        raise InProcessTransport(self)
 
136
 
120
137
    def get(self, relpath):
121
138
        """See Transport.get()."""
122
139
        _abspath = self._abspath(relpath)
123
140
        if not _abspath in self._files:
124
 
            raise NoSuchFile(relpath)
 
141
            if _abspath in self._dirs:
 
142
                return LateReadError(relpath)
 
143
            else:
 
144
                raise NoSuchFile(relpath)
125
145
        return StringIO(self._files[_abspath][0])
126
146
 
127
147
    def put_file(self, relpath, f, mode=None):
128
148
        """See Transport.put_file()."""
129
149
        _abspath = self._abspath(relpath)
130
150
        self._check_parent(_abspath)
131
 
        self._files[_abspath] = (f.read(), mode)
 
151
        bytes = f.read()
 
152
        if type(bytes) is not str:
 
153
            # Although not strictly correct, we raise UnicodeEncodeError to be
 
154
            # compatible with other transports.
 
155
            raise UnicodeEncodeError(
 
156
                'undefined', bytes, 0, 1,
 
157
                'put_file must be given a file of bytes, not unicode.')
 
158
        self._files[_abspath] = (bytes, mode)
 
159
        return len(bytes)
132
160
 
133
161
    def mkdir(self, relpath, mode=None):
134
162
        """See Transport.mkdir()."""
138
166
            raise FileExists(relpath)
139
167
        self._dirs[_abspath]=mode
140
168
 
 
169
    def open_write_stream(self, relpath, mode=None):
 
170
        """See Transport.open_write_stream."""
 
171
        self.put_bytes(relpath, "", mode)
 
172
        result = AppendBasedFileStream(self, relpath)
 
173
        _file_streams[self.abspath(relpath)] = result
 
174
        return result
 
175
 
141
176
    def listable(self):
142
177
        """See Transport.listable."""
143
178
        return True
146
181
        for file in self._files:
147
182
            if file.startswith(self._cwd):
148
183
                yield urlutils.escape(file[len(self._cwd):])
149
 
    
 
184
 
150
185
    def list_dir(self, relpath):
151
186
        """See Transport.list_dir()."""
152
187
        _abspath = self._abspath(relpath)
185
220
                    del container[path]
186
221
        do_renames(self._files)
187
222
        do_renames(self._dirs)
188
 
    
 
223
 
189
224
    def rmdir(self, relpath):
190
225
        """See Transport.rmdir."""
191
226
        _abspath = self._abspath(relpath)
206
241
        """See Transport.stat()."""
207
242
        _abspath = self._abspath(relpath)
208
243
        if _abspath in self._files:
209
 
            return MemoryStat(len(self._files[_abspath][0]), False, 
 
244
            return MemoryStat(len(self._files[_abspath][0]), False,
210
245
                              self._files[_abspath][1])
211
246
        elif _abspath in self._dirs:
212
247
            return MemoryStat(0, True, self._dirs[_abspath])
224
259
    def _abspath(self, relpath):
225
260
        """Generate an internal absolute path."""
226
261
        relpath = urlutils.unescape(relpath)
227
 
        if relpath.find('..') != -1:
228
 
            raise AssertionError('relpath contains ..')
229
 
        if relpath == '':
230
 
            return '/'
231
 
        if relpath[0] == '/':
 
262
        if relpath[:1] == '/':
232
263
            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
 
264
        cwd_parts = self._cwd.split('/')
 
265
        rel_parts = relpath.split('/')
 
266
        r = []
 
267
        for i in cwd_parts + rel_parts:
 
268
            if i == '..':
 
269
                if not r:
 
270
                    raise ValueError("illegal relpath %r under %r"
 
271
                        % (relpath, self._cwd))
 
272
                r = r[:-1]
 
273
            elif i == '.' or i == '':
 
274
                pass
 
275
            else:
 
276
                r.append(i)
 
277
        return '/' + '/'.join(r)
242
278
 
243
279
 
244
280
class _MemoryLock(object):
245
281
    """This makes a lock."""
246
282
 
247
283
    def __init__(self, path, transport):
248
 
        assert isinstance(transport, MemoryTransport)
249
284
        self.path = path
250
285
        self.transport = transport
251
286
        if self.path in self.transport._locks:
252
287
            raise LockError('File %r already locked' % (self.path,))
253
288
        self.transport._locks[self.path] = self
254
289
 
255
 
    def __del__(self):
256
 
        # Should this warn, or actually try to cleanup?
257
 
        if self.transport:
258
 
            warnings.warn("MemoryLock %r not explicitly unlocked" % (self.path,))
259
 
            self.unlock()
260
 
 
261
290
    def unlock(self):
262
291
        del self.transport._locks[self.path]
263
292
        self.transport = None
264
293
 
265
294
 
266
 
class MemoryServer(Server):
 
295
class MemoryServer(transport.Server):
267
296
    """Server for the MemoryTransport for testing with."""
268
297
 
269
 
    def setUp(self):
270
 
        """See bzrlib.transport.Server.setUp."""
 
298
    def start_server(self):
271
299
        self._dirs = {'/':None}
272
300
        self._files = {}
273
301
        self._locks = {}
274
302
        self._scheme = "memory+%s:///" % id(self)
275
303
        def memory_factory(url):
276
 
            result = MemoryTransport(url)
 
304
            from bzrlib.transport import memory
 
305
            result = memory.MemoryTransport(url)
277
306
            result._dirs = self._dirs
278
307
            result._files = self._files
279
308
            result._locks = self._locks
280
309
            return result
281
 
        register_transport(self._scheme, memory_factory)
 
310
        self._memory_factory = memory_factory
 
311
        transport.register_transport(self._scheme, self._memory_factory)
282
312
 
283
 
    def tearDown(self):
284
 
        """See bzrlib.transport.Server.tearDown."""
 
313
    def stop_server(self):
285
314
        # unregister this server
 
315
        transport.unregister_transport(self._scheme, self._memory_factory)
286
316
 
287
317
    def get_url(self):
288
318
        """See bzrlib.transport.Server.get_url."""
289
319
        return self._scheme
290
320
 
 
321
    def get_bogus_url(self):
 
322
        raise NotImplementedError
 
323
 
291
324
 
292
325
def get_test_permutations():
293
326
    """Return the permutations to be used in testing."""