~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/transport/memory.py

  • Committer: Michael Ellerman
  • Date: 2005-12-10 22:11:13 UTC
  • mto: This revision was merged to the branch mainline in revision 1528.
  • Revision ID: michael@ellerman.id.au-20051210221113-99ca561aaab4661e
Simplify handling of DivergedBranches in cmd_pull()

Show diffs side-by-side

added added

removed removed

Lines of Context:
15
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
16
"""Implementation of Transport that uses memory for its storage."""
17
17
 
18
 
from copy import copy
19
18
import os
20
19
import errno
21
 
from stat import *
22
20
from cStringIO import StringIO
23
21
 
24
22
from bzrlib.trace import mutter
25
23
from bzrlib.errors import TransportError, NoSuchFile, FileExists
26
 
from bzrlib.transport import Transport, register_transport, Server
 
24
from bzrlib.transport import Transport
27
25
 
28
26
class MemoryStat(object):
29
27
 
30
 
    def __init__(self, size, is_dir, perms):
 
28
    def __init__(self, size):
31
29
        self.st_size = size
32
 
        if perms is None:
33
 
            perms = 0644
34
 
        if not is_dir:
35
 
            self.st_mode = S_IFREG | perms
36
 
        else:
37
 
            self.st_mode = S_IFDIR | perms
38
30
 
39
31
 
40
32
class MemoryTransport(Transport):
41
33
    """This is the transport agent for local filesystem access."""
42
34
 
43
 
    def __init__(self, url=""):
 
35
    def __init__(self):
44
36
        """Set the 'base' path where files will be stored."""
45
 
        if url == "":
46
 
            url = "memory:/"
47
 
        if url[-1] != '/':
48
 
            url = url + '/'
49
 
        super(MemoryTransport, self).__init__(url)
50
 
        self._cwd = url[url.find(':') + 1:]
51
 
        self._dirs = {}
 
37
        super(MemoryTransport, self).__init__('in-memory:')
 
38
        self._dirs = set()
52
39
        self._files = {}
53
40
 
54
41
    def clone(self, offset=None):
55
42
        """See Transport.clone()."""
56
 
        if offset is None:
57
 
            return copy(self)
58
 
        segments = offset.split('/')
59
 
        cwdsegments = self._cwd.split('/')[:-1]
60
 
        while len(segments):
61
 
            segment = segments.pop(0)
62
 
            if segment == '.':
63
 
                continue
64
 
            if segment == '..':
65
 
                if len(cwdsegments) > 1:
66
 
                    cwdsegments.pop()
67
 
                continue
68
 
            cwdsegments.append(segment)
69
 
        url = self.base[:self.base.find(':') + 1] + '/'.join(cwdsegments) + '/'
70
 
        result = MemoryTransport(url)
71
 
        result._dirs = self._dirs
72
 
        result._files = self._files
73
 
        return result
 
43
        return self
74
44
 
75
45
    def abspath(self, relpath):
76
46
        """See Transport.abspath()."""
77
 
        return self.base[:-1] + self._abspath(relpath)
 
47
        return self.base + relpath
78
48
 
79
49
    def append(self, relpath, f):
80
50
        """See Transport.append()."""
81
 
        _abspath = self._abspath(relpath)
82
 
        self._check_parent(_abspath)
83
 
        orig_content, orig_mode = self._files.get(_abspath, ("", None))
84
 
        self._files[_abspath] = (orig_content + f.read(), orig_mode)
 
51
        self._check_parent(relpath)
 
52
        self._files[relpath] = self._files.get(relpath, "") + f.read()
85
53
 
86
 
    def _check_parent(self, _abspath):
87
 
        dir = os.path.dirname(_abspath)
88
 
        if dir != '/':
 
54
    def _check_parent(self, relpath):
 
55
        dir = os.path.dirname(relpath)
 
56
        if dir != '':
89
57
            if not dir in self._dirs:
90
 
                raise NoSuchFile(_abspath)
 
58
                raise NoSuchFile(relpath)
91
59
 
92
60
    def has(self, relpath):
93
61
        """See Transport.has()."""
94
 
        _abspath = self._abspath(relpath)
95
 
        return _abspath in self._files or _abspath in self._dirs
96
 
 
97
 
    def delete(self, relpath):
98
 
        """See Transport.delete()."""
99
 
        _abspath = self._abspath(relpath)
100
 
        if not _abspath in self._files:
101
 
            raise NoSuchFile(relpath)
102
 
        del self._files[_abspath]
 
62
        return relpath in self._files
103
63
 
104
64
    def get(self, relpath):
105
65
        """See Transport.get()."""
106
 
        _abspath = self._abspath(relpath)
107
 
        if not _abspath in self._files:
 
66
        if not relpath in self._files:
108
67
            raise NoSuchFile(relpath)
109
 
        return StringIO(self._files[_abspath][0])
 
68
        return StringIO(self._files[relpath])
110
69
 
111
 
    def put(self, relpath, f, mode=None):
 
70
    def put(self, relpath, f):
112
71
        """See Transport.put()."""
113
 
        _abspath = self._abspath(relpath)
114
 
        self._check_parent(_abspath)
115
 
        self._files[_abspath] = (f.read(), mode)
 
72
        self._check_parent(relpath)
 
73
        self._files[relpath] = f.read()
116
74
 
117
 
    def mkdir(self, relpath, mode=None):
 
75
    def mkdir(self, relpath):
118
76
        """See Transport.mkdir()."""
119
 
        _abspath = self._abspath(relpath)
120
 
        self._check_parent(_abspath)
121
 
        if _abspath in self._dirs:
 
77
        self._check_parent(relpath)
 
78
        if relpath in self._dirs:
122
79
            raise FileExists(relpath)
123
 
        self._dirs[_abspath]=mode
 
80
        self._dirs.add(relpath)
124
81
 
125
82
    def listable(self):
126
83
        """See Transport.listable."""
127
84
        return True
128
85
 
129
86
    def iter_files_recursive(self):
130
 
        for file in self._files:
131
 
            if file.startswith(self._cwd):
132
 
                yield file[len(self._cwd):]
 
87
        return iter(self._files)
133
88
    
134
 
    def list_dir(self, relpath):
135
 
        """See Transport.list_dir()."""
136
 
        _abspath = self._abspath(relpath)
137
 
        if _abspath != '/' and _abspath not in self._dirs:
138
 
            raise NoSuchFile(relpath)
139
 
        result = []
140
 
        for path in self._files:
141
 
            if (path.startswith(_abspath) and 
142
 
                path[len(_abspath) + 1:].find('/') == -1 and
143
 
                len(path) > len(_abspath)):
144
 
                result.append(path[len(_abspath) + 1:])
145
 
        for path in self._dirs:
146
 
            if (path.startswith(_abspath) and 
147
 
                path[len(_abspath) + 1:].find('/') == -1 and
148
 
                len(path) > len(_abspath)):
149
 
                result.append(path[len(_abspath) + 1:])
150
 
        return result
 
89
#    def list_dir(self, relpath):
 
90
#    TODO if needed
151
91
    
152
92
    def stat(self, relpath):
153
93
        """See Transport.stat()."""
154
 
        _abspath = self._abspath(relpath)
155
 
        if _abspath in self._files:
156
 
            return MemoryStat(len(self._files[_abspath][0]), False, 
157
 
                              self._files[_abspath][1])
158
 
        elif _abspath == '':
159
 
            return MemoryStat(0, True, None)
160
 
        elif _abspath in self._dirs:
161
 
            return MemoryStat(0, True, self._dirs[_abspath])
162
 
        else:
163
 
            raise NoSuchFile(relpath)
 
94
        return MemoryStat(len(self._files[relpath]))
164
95
 
165
96
#    def lock_read(self, relpath):
166
97
#   TODO if needed
167
98
#
168
99
#    def lock_write(self, relpath):
169
100
#   TODO if needed
170
 
 
171
 
    def _abspath(self, relpath):
172
 
        """Generate an internal absolute path."""
173
 
        if relpath.find('..') != -1:
174
 
            raise AssertionError('relpath contains ..')
175
 
        if relpath == '.':
176
 
            return self._cwd[:-1]
177
 
        if relpath.endswith('/'):
178
 
            relpath = relpath[:-1]
179
 
        return self._cwd + relpath
180
 
 
181
 
 
182
 
class MemoryServer(Server):
183
 
    """Server for the MemoryTransport for testing with."""
184
 
 
185
 
    def setUp(self):
186
 
        """See bzrlib.transport.Server.setUp."""
187
 
        self._scheme = "memory+%s:" % id(self)
188
 
        register_transport(self._scheme, MemoryTransport)
189
 
 
190
 
    def tearDown(self):
191
 
        """See bzrlib.transport.Server.tearDown."""
192
 
        # unregister this server
193
 
 
194
 
    def get_url(self):
195
 
        """See bzrlib.transport.Server.get_url."""
196
 
        return self._scheme
197
 
 
198
 
 
199
 
def get_test_permutations():
200
 
    """Return the permutations to be used in testing."""
201
 
    return [(MemoryTransport, MemoryServer),
202
 
            ]