~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/transport/memory.py

Optimize Tree._iter_changes with specific file_ids

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
# Copyright (C) 2005, 2006 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
5
5
# the Free Software Foundation; either version 2 of the License, or
6
6
# (at your option) any later version.
7
 
 
 
7
#
8
8
# This program is distributed in the hope that it will be useful,
9
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
11
# GNU General Public License for more details.
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
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20
20
so this is primarily useful for testing.
21
21
"""
22
22
 
23
 
from copy import copy
24
23
import os
25
24
import errno
26
25
import re
59
58
        if url[-1] != '/':
60
59
            url = url + '/'
61
60
        super(MemoryTransport, self).__init__(url)
62
 
        self._cwd = url[url.find(':') + 3:]
 
61
        split = url.find(':') + 3
 
62
        self._scheme = url[:split]
 
63
        self._cwd = url[split:]
63
64
        # dictionaries from absolute path to file mode
64
65
        self._dirs = {'/':None}
65
66
        self._files = {}
67
68
 
68
69
    def clone(self, offset=None):
69
70
        """See Transport.clone()."""
70
 
        if offset is None or offset == '':
71
 
            return copy(self)
72
 
        segments = offset.split('/')
73
 
        cwdsegments = self._cwd.split('/')[:-1]
74
 
        while len(segments):
75
 
            segment = segments.pop(0)
76
 
            if segment == '.':
77
 
                continue
78
 
            if segment == '..':
79
 
                if len(cwdsegments) > 1:
80
 
                    cwdsegments.pop()
81
 
                continue
82
 
            cwdsegments.append(segment)
83
 
        url = self.base[:self.base.find(':') + 3] + '/'.join(cwdsegments) + '/'
 
71
        path = self._combine_paths(self._cwd, offset)
 
72
        if len(path) == 0 or path[-1] != '/':
 
73
            path += '/'
 
74
        url = self._scheme + path
84
75
        result = MemoryTransport(url)
85
76
        result._dirs = self._dirs
86
77
        result._files = self._files
98
89
        else:
99
90
            return temp_t.base[:-1]
100
91
 
101
 
    def append(self, relpath, f, mode=None):
102
 
        """See Transport.append()."""
 
92
    def append_file(self, relpath, f, mode=None):
 
93
        """See Transport.append_file()."""
103
94
        _abspath = self._abspath(relpath)
104
95
        self._check_parent(_abspath)
105
96
        orig_content, orig_mode = self._files.get(_abspath, ("", None))
117
108
    def has(self, relpath):
118
109
        """See Transport.has()."""
119
110
        _abspath = self._abspath(relpath)
120
 
        return _abspath in self._files or _abspath in self._dirs
 
111
        return (_abspath in self._files) or (_abspath in self._dirs)
121
112
 
122
113
    def delete(self, relpath):
123
114
        """See Transport.delete()."""
133
124
            raise NoSuchFile(relpath)
134
125
        return StringIO(self._files[_abspath][0])
135
126
 
136
 
    def put(self, relpath, f, mode=None):
137
 
        """See Transport.put()."""
 
127
    def put_file(self, relpath, f, mode=None):
 
128
        """See Transport.put_file()."""
138
129
        _abspath = self._abspath(relpath)
139
130
        self._check_parent(_abspath)
140
131
        self._files[_abspath] = (f.read(), mode)
154
145
    def iter_files_recursive(self):
155
146
        for file in self._files:
156
147
            if file.startswith(self._cwd):
157
 
                yield file[len(self._cwd):]
 
148
                yield urlutils.escape(file[len(self._cwd):])
158
149
    
159
150
    def list_dir(self, relpath):
160
151
        """See Transport.list_dir()."""
162
153
        if _abspath != '/' and _abspath not in self._dirs:
163
154
            raise NoSuchFile(relpath)
164
155
        result = []
165
 
        for path in self._files:
166
 
            if (path.startswith(_abspath) and 
167
 
                path[len(_abspath) + 1:].find('/') == -1 and
168
 
                len(path) > len(_abspath)):
169
 
                result.append(path[len(_abspath) + 1:])
170
 
        for path in self._dirs:
171
 
            if (path.startswith(_abspath) and 
172
 
                path[len(_abspath) + 1:].find('/') == -1 and
173
 
                len(path) > len(_abspath) and
174
 
                path[len(_abspath)] == '/'):
175
 
                result.append(path[len(_abspath) + 1:])
176
 
        return result
 
156
 
 
157
        if not _abspath.endswith('/'):
 
158
            _abspath += '/'
 
159
 
 
160
        for path_group in self._files, self._dirs:
 
161
            for path in path_group:
 
162
                if path.startswith(_abspath):
 
163
                    trailing = path[len(_abspath):]
 
164
                    if trailing and '/' not in trailing:
 
165
                        result.append(trailing)
 
166
        return map(urlutils.escape, result)
177
167
 
178
168
    def rename(self, rel_from, rel_to):
179
169
        """Rename a file or directory; fail if the destination exists"""
236
226
        relpath = urlutils.unescape(relpath)
237
227
        if relpath.find('..') != -1:
238
228
            raise AssertionError('relpath contains ..')
 
229
        if relpath == '':
 
230
            return '/'
 
231
        if relpath[0] == '/':
 
232
            return relpath
239
233
        if relpath == '.':
240
234
            if (self._cwd == '/'):
241
235
                return self._cwd