/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
6609.2.1 by Vincent Ladeuil
Make all transport put_bytes() raises TypeError when given unicode strings rather than bytes.
1
# Copyright (C) 2005-2011, 2016 Canonical Ltd
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
2
#
1442.1.44 by Robert Collins
Many transport related tweaks:
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.
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
7
#
1442.1.44 by Robert Collins
Many transport related tweaks:
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.
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
12
#
1442.1.44 by Robert Collins
Many transport related tweaks:
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
4183.7.1 by Sabin Iacob
update FSF mailing address
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
1553.5.14 by Martin Pool
doc
16
17
"""Implementation of Transport that uses memory for its storage.
18
19
The contents of the transport will be lost when the object is discarded,
20
so this is primarily useful for testing.
21
"""
1442.1.44 by Robert Collins
Many transport related tweaks:
22
6855.4.5 by Jelmer Vernooij
Fix more bees, use with rather than try/finally for some files.
23
import contextlib
6997 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-f
24
from io import (
25
    BytesIO,
26
    )
7058.6.3 by Jelmer Vernooij
Fix tests.
27
import itertools
1442.1.44 by Robert Collins
Many transport related tweaks:
28
import os
29
import errno
7058.6.3 by Jelmer Vernooij
Fix tests.
30
from stat import S_IFREG, S_IFDIR, S_IFLNK, S_ISDIR
1442.1.44 by Robert Collins
Many transport related tweaks:
31
6624 by Jelmer Vernooij
Merge Python3 porting work ('py3 pokes')
32
from .. import (
5017.3.4 by Vincent Ladeuil
Move MemoryServer to bzrlib.tests.test_server
33
    transport,
4634.108.12 by John Arbash Meinel
Have MemoryTransport.tearDown unregister its transport.
34
    urlutils,
35
    )
6624 by Jelmer Vernooij
Merge Python3 porting work ('py3 pokes')
36
from ..errors import (
2634.1.1 by Robert Collins
(robertc) Reinstate the accidentally backed out external_url patch.
37
    FileExists,
38
    LockError,
39
    InProcessTransport,
40
    NoSuchFile,
7119.2.1 by Jelmer Vernooij
Support for symlinks in MemoryTransport.
41
    TransportNotPossible,
2634.1.1 by Robert Collins
(robertc) Reinstate the accidentally backed out external_url patch.
42
    )
6624 by Jelmer Vernooij
Merge Python3 porting work ('py3 pokes')
43
from ..transport import (
2671.3.6 by Robert Collins
Review feedback.
44
    AppendBasedFileStream,
2671.3.2 by Robert Collins
Start open_file_stream logic.
45
    _file_streams,
2052.6.1 by Robert Collins
``Transport.get`` has had its interface made more clear for ease of use.
46
    LateReadError,
47
    )
1442.1.44 by Robert Collins
Many transport related tweaks:
48
49
50
class MemoryStat(object):
51
7058.6.3 by Jelmer Vernooij
Fix tests.
52
    def __init__(self, size, kind, perms=None):
1442.1.44 by Robert Collins
Many transport related tweaks:
53
        self.st_size = size
7058.6.3 by Jelmer Vernooij
Fix tests.
54
        if not S_ISDIR(kind):
1553.5.65 by Martin Pool
MemoryTransport: Set better permissions on fake directory inodes
55
            if perms is None:
6619.3.14 by Jelmer Vernooij
Convert some octal numbers to new notations.
56
                perms = 0o644
7058.6.3 by Jelmer Vernooij
Fix tests.
57
            self.st_mode = kind | perms
58
        else:
1553.5.65 by Martin Pool
MemoryTransport: Set better permissions on fake directory inodes
59
            if perms is None:
6619.3.14 by Jelmer Vernooij
Convert some octal numbers to new notations.
60
                perms = 0o755
7058.6.3 by Jelmer Vernooij
Fix tests.
61
            self.st_mode = kind | perms
1442.1.44 by Robert Collins
Many transport related tweaks:
62
63
5017.3.4 by Vincent Ladeuil
Move MemoryServer to bzrlib.tests.test_server
64
class MemoryTransport(transport.Transport):
1534.4.9 by Robert Collins
Add a readonly decorator for transports.
65
    """This is an in memory file system for transient data storage."""
1442.1.44 by Robert Collins
Many transport related tweaks:
66
1530.1.3 by Robert Collins
transport implementations now tested consistently.
67
    def __init__(self, url=""):
1442.1.44 by Robert Collins
Many transport related tweaks:
68
        """Set the 'base' path where files will be stored."""
1530.1.3 by Robert Collins
transport implementations now tested consistently.
69
        if url == "":
1685.1.42 by John Arbash Meinel
A couple more fixes to make sure memory:/// works correctly.
70
            url = "memory:///"
1530.1.3 by Robert Collins
transport implementations now tested consistently.
71
        if url[-1] != '/':
72
            url = url + '/'
73
        super(MemoryTransport, self).__init__(url)
1910.16.2 by Andrew Bennetts
Reduce transport code duplication by creating a '_combine_paths' method to Transport.
74
        split = url.find(':') + 3
75
        self._scheme = url[:split]
76
        self._cwd = url[split:]
1553.5.16 by Martin Pool
MemoryTransport.rename() must raise exceptions on collision
77
        # dictionaries from absolute path to file mode
7058.6.6 by Jelmer Vernooij
Fix flake8ness.
78
        self._dirs = {'/': None}
7119.2.1 by Jelmer Vernooij
Support for symlinks in MemoryTransport.
79
        self._symlinks = {}
1442.1.44 by Robert Collins
Many transport related tweaks:
80
        self._files = {}
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
81
        self._locks = {}
1442.1.44 by Robert Collins
Many transport related tweaks:
82
83
    def clone(self, offset=None):
84
        """See Transport.clone()."""
6055.2.16 by Jelmer Vernooij
Move _combine_paths to URL.
85
        path = urlutils.URL._combine_paths(self._cwd, offset)
1910.16.2 by Andrew Bennetts
Reduce transport code duplication by creating a '_combine_paths' method to Transport.
86
        if len(path) == 0 or path[-1] != '/':
87
            path += '/'
88
        url = self._scheme + path
4547.2.2 by Andrew Bennetts
Add test for read_mergeable_from_transport raising NotABundle when TooManyRedirections happens.
89
        result = self.__class__(url)
1530.1.3 by Robert Collins
transport implementations now tested consistently.
90
        result._dirs = self._dirs
7119.2.1 by Jelmer Vernooij
Support for symlinks in MemoryTransport.
91
        result._symlinks = self._symlinks
1530.1.3 by Robert Collins
transport implementations now tested consistently.
92
        result._files = self._files
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
93
        result._locks = self._locks
1530.1.3 by Robert Collins
transport implementations now tested consistently.
94
        return result
1442.1.44 by Robert Collins
Many transport related tweaks:
95
96
    def abspath(self, relpath):
97
        """See Transport.abspath()."""
1636.1.1 by Robert Collins
Fix calling relpath() and abspath() on transports at their root.
98
        # while a little slow, this is sufficiently fast to not matter in our
99
        # current environment - XXX RBC 20060404 move the clone '..' handling
100
        # into here and call abspath from clone
101
        temp_t = self.clone(relpath)
1685.1.42 by John Arbash Meinel
A couple more fixes to make sure memory:/// works correctly.
102
        if temp_t.base.count('/') == 3:
1636.1.1 by Robert Collins
Fix calling relpath() and abspath() on transports at their root.
103
            return temp_t.base
104
        else:
105
            return temp_t.base[:-1]
1442.1.44 by Robert Collins
Many transport related tweaks:
106
1955.3.15 by John Arbash Meinel
Deprecate 'Transport.append' in favor of Transport.append_file or Transport.append_bytes
107
    def append_file(self, relpath, f, mode=None):
1955.3.16 by John Arbash Meinel
Switch over to Transport.append_bytes or append_files
108
        """See Transport.append_file()."""
7058.6.3 by Jelmer Vernooij
Fix tests.
109
        _abspath = self._resolve_symlinks(relpath)
1530.1.3 by Robert Collins
transport implementations now tested consistently.
110
        self._check_parent(_abspath)
6963.2.1 by Jelmer Vernooij
Fix more python3 tests.
111
        orig_content, orig_mode = self._files.get(_abspath, (b"", None))
1666.1.6 by Robert Collins
Make knit the default format.
112
        if mode is None:
113
            mode = orig_mode
114
        self._files[_abspath] = (orig_content + f.read(), mode)
1563.2.3 by Robert Collins
Change the return signature of transport.append and append_multi to return the length of the pre-append content.
115
        return len(orig_content)
1442.1.44 by Robert Collins
Many transport related tweaks:
116
1530.1.3 by Robert Collins
transport implementations now tested consistently.
117
    def _check_parent(self, _abspath):
118
        dir = os.path.dirname(_abspath)
119
        if dir != '/':
7183.3.1 by Martin
Fix E71* lint errors
120
            if dir not in self._dirs:
1530.1.3 by Robert Collins
transport implementations now tested consistently.
121
                raise NoSuchFile(_abspath)
1442.1.44 by Robert Collins
Many transport related tweaks:
122
123
    def has(self, relpath):
124
        """See Transport.has()."""
1530.1.3 by Robert Collins
transport implementations now tested consistently.
125
        _abspath = self._abspath(relpath)
7058.6.3 by Jelmer Vernooij
Fix tests.
126
        for container in (self._files, self._dirs, self._symlinks):
127
            if _abspath in container.keys():
128
                return True
129
        return False
1530.1.3 by Robert Collins
transport implementations now tested consistently.
130
131
    def delete(self, relpath):
132
        """See Transport.delete()."""
133
        _abspath = self._abspath(relpath)
7058.6.3 by Jelmer Vernooij
Fix tests.
134
        if _abspath in self._files:
135
            del self._files[_abspath]
136
        elif _abspath in self._symlinks:
137
            del self._symlinks[_abspath]
138
        else:
1530.1.3 by Robert Collins
transport implementations now tested consistently.
139
            raise NoSuchFile(relpath)
1442.1.44 by Robert Collins
Many transport related tweaks:
140
2634.1.1 by Robert Collins
(robertc) Reinstate the accidentally backed out external_url patch.
141
    def external_url(self):
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
142
        """See breezy.transport.Transport.external_url."""
2634.1.1 by Robert Collins
(robertc) Reinstate the accidentally backed out external_url patch.
143
        # MemoryTransport's are only accessible in-process
144
        # so we raise here
145
        raise InProcessTransport(self)
146
2164.2.15 by Vincent Ladeuil
Http redirections are not followed by default. Do not use hints
147
    def get(self, relpath):
1442.1.44 by Robert Collins
Many transport related tweaks:
148
        """See Transport.get()."""
7058.6.3 by Jelmer Vernooij
Fix tests.
149
        _abspath = self._resolve_symlinks(relpath)
7058.6.6 by Jelmer Vernooij
Fix flake8ness.
150
        if _abspath not in self._files:
2052.6.1 by Robert Collins
``Transport.get`` has had its interface made more clear for ease of use.
151
            if _abspath in self._dirs:
152
                return LateReadError(relpath)
153
            else:
154
                raise NoSuchFile(relpath)
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
155
        return BytesIO(self._files[_abspath][0])
1442.1.44 by Robert Collins
Many transport related tweaks:
156
1955.3.6 by John Arbash Meinel
Lots of deprecation warnings, but no errors
157
    def put_file(self, relpath, f, mode=None):
158
        """See Transport.put_file()."""
7058.6.3 by Jelmer Vernooij
Fix tests.
159
        _abspath = self._resolve_symlinks(relpath)
1530.1.3 by Robert Collins
transport implementations now tested consistently.
160
        self._check_parent(_abspath)
6609.2.1 by Vincent Ladeuil
Make all transport put_bytes() raises TypeError when given unicode strings rather than bytes.
161
        raw_bytes = f.read()
162
        self._files[_abspath] = (raw_bytes, mode)
163
        return len(raw_bytes)
1442.1.44 by Robert Collins
Many transport related tweaks:
164
7058.6.3 by Jelmer Vernooij
Fix tests.
165
    def symlink(self, source, target):
166
        _abspath = self._resolve_symlinks(target)
167
        self._check_parent(_abspath)
168
        self._symlinks[_abspath] = self._abspath(source)
169
1185.58.4 by John Arbash Meinel
Added permission checking to Branch, and propogated that change into the stores.
170
    def mkdir(self, relpath, mode=None):
1442.1.44 by Robert Collins
Many transport related tweaks:
171
        """See Transport.mkdir()."""
7058.6.3 by Jelmer Vernooij
Fix tests.
172
        _abspath = self._resolve_symlinks(relpath)
1530.1.3 by Robert Collins
transport implementations now tested consistently.
173
        self._check_parent(_abspath)
174
        if _abspath in self._dirs:
1442.1.44 by Robert Collins
Many transport related tweaks:
175
            raise FileExists(relpath)
7143.15.2 by Jelmer Vernooij
Run autopep8.
176
        self._dirs[_abspath] = mode
1442.1.44 by Robert Collins
Many transport related tweaks:
177
2671.3.9 by Robert Collins
Review feedback and fix VFat emulated transports to not claim to have unix permissions.
178
    def open_write_stream(self, relpath, mode=None):
179
        """See Transport.open_write_stream."""
6684.1.3 by Martin
Changes across many modules working towards Python 3 support
180
        self.put_bytes(relpath, b"", mode)
2671.3.6 by Robert Collins
Review feedback.
181
        result = AppendBasedFileStream(self, relpath)
182
        _file_streams[self.abspath(relpath)] = result
183
        return result
2671.3.2 by Robert Collins
Start open_file_stream logic.
184
1442.1.44 by Robert Collins
Many transport related tweaks:
185
    def listable(self):
186
        """See Transport.listable."""
187
        return True
188
189
    def iter_files_recursive(self):
7058.6.3 by Jelmer Vernooij
Fix tests.
190
        for file in itertools.chain(self._files, self._symlinks):
1530.1.3 by Robert Collins
transport implementations now tested consistently.
191
            if file.startswith(self._cwd):
1959.2.4 by John Arbash Meinel
MemoryTransport.iter_files_recursive() was not returning escaped paths
192
                yield urlutils.escape(file[len(self._cwd):])
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
193
1530.1.3 by Robert Collins
transport implementations now tested consistently.
194
    def list_dir(self, relpath):
195
        """See Transport.list_dir()."""
7058.6.3 by Jelmer Vernooij
Fix tests.
196
        _abspath = self._resolve_symlinks(relpath)
1530.1.3 by Robert Collins
transport implementations now tested consistently.
197
        if _abspath != '/' and _abspath not in self._dirs:
198
            raise NoSuchFile(relpath)
199
        result = []
2120.3.1 by John Arbash Meinel
Fix MemoryTransport.list_dir() implementation, and update tests
200
201
        if not _abspath.endswith('/'):
202
            _abspath += '/'
203
7058.6.3 by Jelmer Vernooij
Fix tests.
204
        for path_group in self._files, self._dirs, self._symlinks:
2120.3.1 by John Arbash Meinel
Fix MemoryTransport.list_dir() implementation, and update tests
205
            for path in path_group:
206
                if path.startswith(_abspath):
207
                    trailing = path[len(_abspath):]
208
                    if trailing and '/' not in trailing:
6631.3.1 by Martin
Run 2to3 map fixer and refactor after
209
                        result.append(urlutils.escape(trailing))
210
        return result
1553.5.16 by Martin Pool
MemoryTransport.rename() must raise exceptions on collision
211
212
    def rename(self, rel_from, rel_to):
213
        """Rename a file or directory; fail if the destination exists"""
7058.6.3 by Jelmer Vernooij
Fix tests.
214
        abs_from = self._resolve_symlinks(rel_from)
215
        abs_to = self._resolve_symlinks(rel_to)
7008.1.1 by Vincent Ladeuil
Fix breezy.tests.per_transport.TransportTests.test_rename_dir_nonempty(MemoryTransport,MemoryServer) for python3.
216
1553.5.16 by Martin Pool
MemoryTransport.rename() must raise exceptions on collision
217
        def replace(x):
218
            if x == abs_from:
219
                x = abs_to
220
            elif x.startswith(abs_from + '/'):
221
                x = abs_to + x[len(abs_from):]
222
            return x
7008.1.1 by Vincent Ladeuil
Fix breezy.tests.per_transport.TransportTests.test_rename_dir_nonempty(MemoryTransport,MemoryServer) for python3.
223
1553.5.16 by Martin Pool
MemoryTransport.rename() must raise exceptions on collision
224
        def do_renames(container):
7008.1.1 by Vincent Ladeuil
Fix breezy.tests.per_transport.TransportTests.test_rename_dir_nonempty(MemoryTransport,MemoryServer) for python3.
225
            renames = []
1553.5.16 by Martin Pool
MemoryTransport.rename() must raise exceptions on collision
226
            for path in container:
227
                new_path = replace(path)
228
                if new_path != path:
229
                    if new_path in container:
230
                        raise FileExists(new_path)
7008.1.1 by Vincent Ladeuil
Fix breezy.tests.per_transport.TransportTests.test_rename_dir_nonempty(MemoryTransport,MemoryServer) for python3.
231
                    renames.append((path, new_path))
232
            for path, new_path in renames:
233
                container[new_path] = container[path]
234
                del container[path]
235
236
        # If we modify the existing dicts, we're not atomic anymore and may
237
        # fail differently depending on dict order. So work on copy, fail on
238
        # error on only replace dicts if all goes well.
239
        renamed_files = self._files.copy()
7058.6.3 by Jelmer Vernooij
Fix tests.
240
        renamed_symlinks = self._symlinks.copy()
7008.1.1 by Vincent Ladeuil
Fix breezy.tests.per_transport.TransportTests.test_rename_dir_nonempty(MemoryTransport,MemoryServer) for python3.
241
        renamed_dirs = self._dirs.copy()
242
        do_renames(renamed_files)
7058.6.3 by Jelmer Vernooij
Fix tests.
243
        do_renames(renamed_symlinks)
7008.1.1 by Vincent Ladeuil
Fix breezy.tests.per_transport.TransportTests.test_rename_dir_nonempty(MemoryTransport,MemoryServer) for python3.
244
        do_renames(renamed_dirs)
245
        # We may have been cloned so modify in place
246
        self._files.clear()
247
        self._files.update(renamed_files)
7058.6.3 by Jelmer Vernooij
Fix tests.
248
        self._symlinks.clear()
249
        self._symlinks.update(renamed_symlinks)
7008.1.1 by Vincent Ladeuil
Fix breezy.tests.per_transport.TransportTests.test_rename_dir_nonempty(MemoryTransport,MemoryServer) for python3.
250
        self._dirs.clear()
251
        self._dirs.update(renamed_dirs)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
252
1534.4.15 by Robert Collins
Remove shutil dependency in upgrade - create a delete_tree method for transports.
253
    def rmdir(self, relpath):
254
        """See Transport.rmdir."""
7058.6.3 by Jelmer Vernooij
Fix tests.
255
        _abspath = self._resolve_symlinks(relpath)
1534.4.15 by Robert Collins
Remove shutil dependency in upgrade - create a delete_tree method for transports.
256
        if _abspath in self._files:
257
            self._translate_error(IOError(errno.ENOTDIR, relpath), relpath)
7058.6.3 by Jelmer Vernooij
Fix tests.
258
        for path in itertools.chain(self._files, self._symlinks):
2338.5.1 by Andrew Bennetts
Fix bug in MemoryTransport.rmdir.
259
            if path.startswith(_abspath + '/'):
1553.5.15 by Martin Pool
MemoryTransport should indicate ENOTEMPTY on rmdir of nonempty, same as unix
260
                self._translate_error(IOError(errno.ENOTEMPTY, relpath),
261
                                      relpath)
1534.4.15 by Robert Collins
Remove shutil dependency in upgrade - create a delete_tree method for transports.
262
        for path in self._dirs:
2338.5.1 by Andrew Bennetts
Fix bug in MemoryTransport.rmdir.
263
            if path.startswith(_abspath + '/') and path != _abspath:
7143.15.2 by Jelmer Vernooij
Run autopep8.
264
                self._translate_error(
265
                    IOError(errno.ENOTEMPTY, relpath), relpath)
7183.3.1 by Martin
Fix E71* lint errors
266
        if _abspath not in self._dirs:
1534.4.15 by Robert Collins
Remove shutil dependency in upgrade - create a delete_tree method for transports.
267
            raise NoSuchFile(relpath)
268
        del self._dirs[_abspath]
269
1442.1.44 by Robert Collins
Many transport related tweaks:
270
    def stat(self, relpath):
271
        """See Transport.stat()."""
1530.1.3 by Robert Collins
transport implementations now tested consistently.
272
        _abspath = self._abspath(relpath)
7058.6.3 by Jelmer Vernooij
Fix tests.
273
        if _abspath in self._files.keys():
274
            return MemoryStat(len(self._files[_abspath][0]), S_IFREG,
1530.1.15 by Robert Collins
Move put mode tests into test_transport_implementation.
275
                              self._files[_abspath][1])
7058.6.3 by Jelmer Vernooij
Fix tests.
276
        elif _abspath in self._dirs.keys():
277
            return MemoryStat(0, S_IFDIR, self._dirs[_abspath])
278
        elif _abspath in self._symlinks.keys():
279
            return MemoryStat(0, S_IFLNK)
1530.1.3 by Robert Collins
transport implementations now tested consistently.
280
        else:
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
281
            raise NoSuchFile(_abspath)
282
283
    def lock_read(self, relpath):
284
        """See Transport.lock_read()."""
285
        return _MemoryLock(self._abspath(relpath), self)
286
287
    def lock_write(self, relpath):
288
        """See Transport.lock_write()."""
289
        return _MemoryLock(self._abspath(relpath), self)
1530.1.3 by Robert Collins
transport implementations now tested consistently.
290
7058.6.3 by Jelmer Vernooij
Fix tests.
291
    def _resolve_symlinks(self, relpath):
292
        path = self._abspath(relpath)
293
        while path in self._symlinks.keys():
294
            path = self._symlinks[path]
295
        return path
296
1530.1.3 by Robert Collins
transport implementations now tested consistently.
297
    def _abspath(self, relpath):
298
        """Generate an internal absolute path."""
1685.1.45 by John Arbash Meinel
Moved url functions into bzrlib.urlutils
299
        relpath = urlutils.unescape(relpath)
3211.6.1 by James Henstridge
* Remove relpath='' special case in MemoryTransport._abspath(), which
300
        if relpath[:1] == '/':
1910.15.1 by Andrew Bennetts
More tests for abspath and clone behaviour
301
            return relpath
2940.3.1 by mbp at sourcefrog
MemoryTransport._abspath: fix handling of '..' and other strangeness
302
        cwd_parts = self._cwd.split('/')
303
        rel_parts = relpath.split('/')
304
        r = []
305
        for i in cwd_parts + rel_parts:
306
            if i == '..':
307
                if not r:
308
                    raise ValueError("illegal relpath %r under %r"
7143.15.2 by Jelmer Vernooij
Run autopep8.
309
                                     % (relpath, self._cwd))
2940.3.1 by mbp at sourcefrog
MemoryTransport._abspath: fix handling of '..' and other strangeness
310
                r = r[:-1]
311
            elif i == '.' or i == '':
312
                pass
313
            else:
314
                r.append(i)
7119.2.1 by Jelmer Vernooij
Support for symlinks in MemoryTransport.
315
                r = self._symlinks.get('/'.join(r), r)
2940.3.1 by mbp at sourcefrog
MemoryTransport._abspath: fix handling of '..' and other strangeness
316
        return '/' + '/'.join(r)
1530.1.3 by Robert Collins
transport implementations now tested consistently.
317
7119.2.1 by Jelmer Vernooij
Support for symlinks in MemoryTransport.
318
    def symlink(self, source, link_name):
319
        """Create a symlink pointing to source named link_name."""
320
        _abspath = self._abspath(link_name)
321
        self._check_parent(_abspath)
322
        self._symlinks[_abspath] = source.split('/')
323
324
    def readlink(self, link_name):
325
        _abspath = self._abspath(link_name)
7119.2.3 by Jelmer Vernooij
Add test for readlink.
326
        try:
327
            return '/'.join(self._symlinks[_abspath])
328
        except KeyError:
329
            raise NoSuchFile(link_name)
7119.2.1 by Jelmer Vernooij
Support for symlinks in MemoryTransport.
330
1530.1.3 by Robert Collins
transport implementations now tested consistently.
331
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
332
class _MemoryLock(object):
333
    """This makes a lock."""
334
335
    def __init__(self, path, transport):
336
        self.path = path
337
        self.transport = transport
338
        if self.path in self.transport._locks:
339
            raise LockError('File %r already locked' % (self.path,))
340
        self.transport._locks[self.path] = self
341
342
    def unlock(self):
343
        del self.transport._locks[self.path]
344
        self.transport = None
345
346
5017.3.45 by Vincent Ladeuil
Move MemoryServer back into bzrlib.transport.memory as it's needed as soon as a MemoryTransport is used. Add a NEWS entry.
347
class MemoryServer(transport.Server):
348
    """Server for the MemoryTransport for testing with."""
349
350
    def start_server(self):
7143.15.2 by Jelmer Vernooij
Run autopep8.
351
        self._dirs = {'/': None}
5017.3.45 by Vincent Ladeuil
Move MemoryServer back into bzrlib.transport.memory as it's needed as soon as a MemoryTransport is used. Add a NEWS entry.
352
        self._files = {}
7058.6.3 by Jelmer Vernooij
Fix tests.
353
        self._symlinks = {}
5017.3.45 by Vincent Ladeuil
Move MemoryServer back into bzrlib.transport.memory as it's needed as soon as a MemoryTransport is used. Add a NEWS entry.
354
        self._locks = {}
355
        self._scheme = "memory+%s:///" % id(self)
7143.15.2 by Jelmer Vernooij
Run autopep8.
356
5017.3.45 by Vincent Ladeuil
Move MemoryServer back into bzrlib.transport.memory as it's needed as soon as a MemoryTransport is used. Add a NEWS entry.
357
        def memory_factory(url):
6624 by Jelmer Vernooij
Merge Python3 porting work ('py3 pokes')
358
            from . import memory
5017.3.45 by Vincent Ladeuil
Move MemoryServer back into bzrlib.transport.memory as it's needed as soon as a MemoryTransport is used. Add a NEWS entry.
359
            result = memory.MemoryTransport(url)
360
            result._dirs = self._dirs
361
            result._files = self._files
7058.6.3 by Jelmer Vernooij
Fix tests.
362
            result._symlinks = self._symlinks
5017.3.45 by Vincent Ladeuil
Move MemoryServer back into bzrlib.transport.memory as it's needed as soon as a MemoryTransport is used. Add a NEWS entry.
363
            result._locks = self._locks
364
            return result
365
        self._memory_factory = memory_factory
366
        transport.register_transport(self._scheme, self._memory_factory)
367
368
    def stop_server(self):
369
        # unregister this server
370
        transport.unregister_transport(self._scheme, self._memory_factory)
371
372
    def get_url(self):
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
373
        """See breezy.transport.Server.get_url."""
5017.3.45 by Vincent Ladeuil
Move MemoryServer back into bzrlib.transport.memory as it's needed as soon as a MemoryTransport is used. Add a NEWS entry.
374
        return self._scheme
375
376
    def get_bogus_url(self):
377
        raise NotImplementedError
378
379
1530.1.11 by Robert Collins
Push the transport permutations list into each transport module allowing for automatic testing of new modules that are registered as transports.
380
def get_test_permutations():
381
    """Return the permutations to be used in testing."""
5017.3.45 by Vincent Ladeuil
Move MemoryServer back into bzrlib.transport.memory as it's needed as soon as a MemoryTransport is used. Add a NEWS entry.
382
    return [(MemoryTransport, MemoryServer),
1530.1.11 by Robert Collins
Push the transport permutations list into each transport module allowing for automatic testing of new modules that are registered as transports.
383
            ]