~bzr-pqm/bzr/bzr.dev

1553.5.13 by Martin Pool
New Transport.rename that mustn't overwrite
1
# Copyright (C) 2005, 2006 Canonical Ltd
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
2
#
1185.11.19 by John Arbash Meinel
Testing put and append, also testing agaist file-like objects as well as strings.
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
#
1185.11.19 by John Arbash Meinel
Testing put and append, also testing agaist file-like objects as well as strings.
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
#
1185.11.19 by John Arbash Meinel
Testing put and append, also testing agaist file-like objects as well as strings.
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
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
1185.16.72 by Martin Pool
[merge] from robert and fix up tests
16
17
"""Transport for the local filesystem.
18
1755.1.3 by Robert Collins
Fix regression in LocalTransport to allow merging.
19
This is a fairly thin wrapper on regular file IO.
20
"""
907.1.1 by John Arbash Meinel
Reworking the Branch and Store code to support an abstracted filesystem layer.
21
1442.1.42 by Robert Collins
rebuild ScratchBranch on top of ScratchTransport
22
import os
23
import shutil
1608.2.5 by Martin Pool
Add Transport.supports_unix_modebits, so tests can
24
import sys
1755.3.7 by John Arbash Meinel
Clean up and write tests for permissions. Now we use fstat which should be cheap, and lets us check the permissions and the file size
25
from stat import ST_MODE, S_ISDIR, ST_SIZE, S_IMODE
1442.1.42 by Robert Collins
rebuild ScratchBranch on top of ScratchTransport
26
import tempfile
27
1755.3.7 by John Arbash Meinel
Clean up and write tests for permissions. Now we use fstat which should be cheap, and lets us check the permissions and the file size
28
from bzrlib import (
29
    osutils,
30
    urlutils,
31
    )
32
from bzrlib.osutils import (abspath, realpath, normpath, pathjoin, rename,
1685.1.52 by John Arbash Meinel
[merge] bzr.dev 1704
33
                            check_legal_path, rmtree)
1685.1.9 by John Arbash Meinel
Updated LocalTransport so that it's base is now a URL rather than a local path. This helps consistency with all other functions. To do so, I added local_abspath() which returns the local path, and local_path_to/from_url
34
from bzrlib.symbol_versioning import warn
1685.1.45 by John Arbash Meinel
Moved url functions into bzrlib.urlutils
35
from bzrlib.trace import mutter
36
from bzrlib.transport import Transport, Server
1755.3.7 by John Arbash Meinel
Clean up and write tests for permissions. Now we use fstat which should be cheap, and lets us check the permissions and the file size
37
38
39
_append_flags = os.O_CREAT | os.O_APPEND | os.O_WRONLY | osutils.O_BINARY
907.1.1 by John Arbash Meinel
Reworking the Branch and Store code to support an abstracted filesystem layer.
40
1442.1.42 by Robert Collins
rebuild ScratchBranch on top of ScratchTransport
41
907.1.1 by John Arbash Meinel
Reworking the Branch and Store code to support an abstracted filesystem layer.
42
class LocalTransport(Transport):
43
    """This is the transport agent for local filesystem access."""
44
45
    def __init__(self, base):
46
        """Set the base path where files will be stored."""
1685.1.9 by John Arbash Meinel
Updated LocalTransport so that it's base is now a URL rather than a local path. This helps consistency with all other functions. To do so, I added local_abspath() which returns the local path, and local_path_to/from_url
47
        if not base.startswith('file://'):
48
            warn("Instantiating LocalTransport with a filesystem path"
49
                " is deprecated as of bzr 0.8."
50
                " Please use bzrlib.transport.get_transport()"
51
                " or pass in a file:// url.",
52
                 DeprecationWarning,
53
                 stacklevel=2
54
                 )
1685.1.45 by John Arbash Meinel
Moved url functions into bzrlib.urlutils
55
            base = urlutils.local_path_to_url(base)
1530.1.3 by Robert Collins
transport implementations now tested consistently.
56
        if base[-1] != '/':
57
            base = base + '/'
58
        super(LocalTransport, self).__init__(base)
1685.1.45 by John Arbash Meinel
Moved url functions into bzrlib.urlutils
59
        self._local_base = urlutils.local_path_from_url(base)
1755.3.7 by John Arbash Meinel
Clean up and write tests for permissions. Now we use fstat which should be cheap, and lets us check the permissions and the file size
60
        self._get_default_modes()
61
62
    def _get_default_modes(self):
63
        """Figure out what the default file and directory modes are"""
64
        umask = osutils.get_umask()
65
        self._default_file_mode = 0666 & ~umask
66
        self._default_dir_mode = 0777 & ~umask
907.1.1 by John Arbash Meinel
Reworking the Branch and Store code to support an abstracted filesystem layer.
67
907.1.32 by John Arbash Meinel
Renaming is_remote to should_cache as it is more appropriate.
68
    def should_cache(self):
907.1.22 by John Arbash Meinel
Fixed some encoding issues, added is_remote function for Transport objects.
69
        return False
70
907.1.2 by John Arbash Meinel
Working on making Branch() do all of it's work over a Transport.
71
    def clone(self, offset=None):
72
        """Return a new LocalTransport with root at self.base + offset
73
        Because the local filesystem does not require a connection, 
74
        we can just return a new object.
75
        """
76
        if offset is None:
77
            return LocalTransport(self.base)
78
        else:
79
            return LocalTransport(self.abspath(offset))
80
1725.2.1 by Robert Collins
Make LocalTransport faster by not normpathing every internal path translation.
81
    def _abspath(self, relative_reference):
82
        """Return a path for use in os calls.
83
84
        Several assumptions are made:
85
         - relative_reference does not contain '..'
86
         - relative_reference is url escaped.
87
        """
1755.1.3 by Robert Collins
Fix regression in LocalTransport to allow merging.
88
        if relative_reference in ('.', ''):
89
            return self._local_base
1755.1.2 by Robert Collins
(robertc, ab)Merge some commit and fetch tuning steps.
90
        return self._local_base + urlutils.unescape(relative_reference)
1725.2.1 by Robert Collins
Make LocalTransport faster by not normpathing every internal path translation.
91
907.1.8 by John Arbash Meinel
Changed the format for abspath. Updated branch to use a hidden _transport
92
    def abspath(self, relpath):
1636.1.1 by Robert Collins
Fix calling relpath() and abspath() on transports at their root.
93
        """Return the full url to the given relative URL."""
1725.2.1 by Robert Collins
Make LocalTransport faster by not normpathing every internal path translation.
94
        # TODO: url escape the result. RBC 20060523.
1185.12.70 by Aaron Bentley
Removed b
95
        assert isinstance(relpath, basestring), (type(relpath), relpath)
1685.1.12 by John Arbash Meinel
Some more work to get LocalTransport to only support URLs
96
        # jam 20060426 Using normpath on the real path, because that ensures
97
        #       proper handling of stuff like
1685.1.45 by John Arbash Meinel
Moved url functions into bzrlib.urlutils
98
        path = normpath(pathjoin(self._local_base, urlutils.unescape(relpath)))
99
        return urlutils.local_path_to_url(path)
1685.1.9 by John Arbash Meinel
Updated LocalTransport so that it's base is now a URL rather than a local path. This helps consistency with all other functions. To do so, I added local_abspath() which returns the local path, and local_path_to/from_url
100
101
    def local_abspath(self, relpath):
102
        """Transform the given relative path URL into the actual path on disk
103
104
        This function only exists for the LocalTransport, since it is
105
        the only one that has direct local access.
106
        This is mostly for stuff like WorkingTree which needs to know
107
        the local working directory.
1725.2.9 by Robert Collins
Merge current head.
108
        
109
        This function is quite expensive: it calls realpath which resolves
110
        symlinks.
1685.1.9 by John Arbash Meinel
Updated LocalTransport so that it's base is now a URL rather than a local path. This helps consistency with all other functions. To do so, I added local_abspath() which returns the local path, and local_path_to/from_url
111
        """
112
        absurl = self.abspath(relpath)
113
        # mutter(u'relpath %s => base: %s, absurl %s', relpath, self.base, absurl)
1685.1.45 by John Arbash Meinel
Moved url functions into bzrlib.urlutils
114
        return urlutils.local_path_from_url(absurl)
907.1.1 by John Arbash Meinel
Reworking the Branch and Store code to support an abstracted filesystem layer.
115
907.1.24 by John Arbash Meinel
Remote functionality work.
116
    def relpath(self, abspath):
117
        """Return the local path portion from a given absolute path.
118
        """
1442.1.64 by Robert Collins
Branch.open_containing now returns a tuple (Branch, relative-path).
119
        if abspath is None:
1185.33.66 by Martin Pool
[patch] use unicode literals for all hardcoded paths (Alexander Belchenko)
120
            abspath = u'.'
1551.2.53 by abentley
Strip trailing slashes in a platform-sensible way
121
1685.1.45 by John Arbash Meinel
Moved url functions into bzrlib.urlutils
122
        return urlutils.file_relpath(
123
            urlutils.strip_trailing_slash(self.base), 
124
            urlutils.strip_trailing_slash(abspath))
907.1.24 by John Arbash Meinel
Remote functionality work.
125
907.1.1 by John Arbash Meinel
Reworking the Branch and Store code to support an abstracted filesystem layer.
126
    def has(self, relpath):
1725.2.1 by Robert Collins
Make LocalTransport faster by not normpathing every internal path translation.
127
        return os.access(self._abspath(relpath), os.F_OK)
907.1.1 by John Arbash Meinel
Reworking the Branch and Store code to support an abstracted filesystem layer.
128
907.1.50 by John Arbash Meinel
Removed encode/decode from Transport.put/get, added more exceptions that can be thrown.
129
    def get(self, relpath):
907.1.1 by John Arbash Meinel
Reworking the Branch and Store code to support an abstracted filesystem layer.
130
        """Get the file at the given relative path.
907.1.20 by John Arbash Meinel
Removed Transport.open(), making get + put encode/decode to utf-8
131
132
        :param relpath: The relative path to the file
133
        """
907.1.48 by John Arbash Meinel
Updated LocalTransport by passing it through the transport_test suite, and got it to pass.
134
        try:
1725.2.1 by Robert Collins
Make LocalTransport faster by not normpathing every internal path translation.
135
            path = self._abspath(relpath)
907.1.50 by John Arbash Meinel
Removed encode/decode from Transport.put/get, added more exceptions that can be thrown.
136
            return open(path, 'rb')
1185.31.44 by John Arbash Meinel
Cleaned up Exceptions for all transports.
137
        except (IOError, OSError),e:
138
            self._translate_error(e, path)
907.1.20 by John Arbash Meinel
Removed Transport.open(), making get + put encode/decode to utf-8
139
1755.3.7 by John Arbash Meinel
Clean up and write tests for permissions. Now we use fstat which should be cheap, and lets us check the permissions and the file size
140
    def put(self, relpath, f, mode=None):
907.1.20 by John Arbash Meinel
Removed Transport.open(), making get + put encode/decode to utf-8
141
        """Copy the file-like or string object into the location.
142
143
        :param relpath: Location to put the contents, relative to base.
144
        :param f:       File-like or string object.
145
        """
907.1.1 by John Arbash Meinel
Reworking the Branch and Store code to support an abstracted filesystem layer.
146
        from bzrlib.atomicfile import AtomicFile
147
1755.3.3 by Robert Collins
allow None == 0666 for mode.
148
        if mode is None:
1755.3.7 by John Arbash Meinel
Clean up and write tests for permissions. Now we use fstat which should be cheap, and lets us check the permissions and the file size
149
            mode = self._default_file_mode
1185.31.44 by John Arbash Meinel
Cleaned up Exceptions for all transports.
150
        path = relpath
907.1.48 by John Arbash Meinel
Updated LocalTransport by passing it through the transport_test suite, and got it to pass.
151
        try:
1725.2.1 by Robert Collins
Make LocalTransport faster by not normpathing every internal path translation.
152
            path = self._abspath(relpath)
1551.2.56 by Aaron Bentley
Better illegal pathname check for Windows
153
            check_legal_path(path)
1185.58.2 by John Arbash Meinel
Added mode to the appropriate transport functions, and tests to make sure they work.
154
            fp = AtomicFile(path, 'wb', new_mode=mode)
1185.31.44 by John Arbash Meinel
Cleaned up Exceptions for all transports.
155
        except (IOError, OSError),e:
156
            self._translate_error(e, path)
907.1.2 by John Arbash Meinel
Working on making Branch() do all of it's work over a Transport.
157
        try:
158
            self._pump(f, fp)
159
            fp.commit()
160
        finally:
161
            fp.close()
162
1442.1.44 by Robert Collins
Many transport related tweaks:
163
    def iter_files_recursive(self):
164
        """Iter the relative paths of files in the transports sub-tree."""
1185.33.66 by Martin Pool
[patch] use unicode literals for all hardcoded paths (Alexander Belchenko)
165
        queue = list(self.list_dir(u'.'))
1442.1.44 by Robert Collins
Many transport related tweaks:
166
        while queue:
1608.1.1 by Martin Pool
[patch] LocalTransport.list_dir should return url-quoted strings (ddaa)
167
            relpath = queue.pop(0)
1442.1.44 by Robert Collins
Many transport related tweaks:
168
            st = self.stat(relpath)
169
            if S_ISDIR(st[ST_MODE]):
170
                for i, basename in enumerate(self.list_dir(relpath)):
171
                    queue.insert(i, relpath+'/'+basename)
172
            else:
173
                yield relpath
174
1185.58.2 by John Arbash Meinel
Added mode to the appropriate transport functions, and tests to make sure they work.
175
    def mkdir(self, relpath, mode=None):
907.1.2 by John Arbash Meinel
Working on making Branch() do all of it's work over a Transport.
176
        """Create a directory at the given path."""
1185.31.44 by John Arbash Meinel
Cleaned up Exceptions for all transports.
177
        path = relpath
907.1.48 by John Arbash Meinel
Updated LocalTransport by passing it through the transport_test suite, and got it to pass.
178
        try:
1755.3.7 by John Arbash Meinel
Clean up and write tests for permissions. Now we use fstat which should be cheap, and lets us check the permissions and the file size
179
            if mode is None:
180
                local_mode = self._default_dir_mode
181
            else:
182
                local_mode = mode
1725.2.1 by Robert Collins
Make LocalTransport faster by not normpathing every internal path translation.
183
            path = self._abspath(relpath)
1755.3.7 by John Arbash Meinel
Clean up and write tests for permissions. Now we use fstat which should be cheap, and lets us check the permissions and the file size
184
            os.mkdir(path, local_mode)
1185.58.2 by John Arbash Meinel
Added mode to the appropriate transport functions, and tests to make sure they work.
185
            if mode is not None:
1755.3.7 by John Arbash Meinel
Clean up and write tests for permissions. Now we use fstat which should be cheap, and lets us check the permissions and the file size
186
                # It is probably faster to just do the chmod, rather than
187
                # doing a stat, and then trying to compare
1185.58.2 by John Arbash Meinel
Added mode to the appropriate transport functions, and tests to make sure they work.
188
                os.chmod(path, mode)
1185.31.44 by John Arbash Meinel
Cleaned up Exceptions for all transports.
189
        except (IOError, OSError),e:
190
            self._translate_error(e, path)
907.1.2 by John Arbash Meinel
Working on making Branch() do all of it's work over a Transport.
191
1755.3.7 by John Arbash Meinel
Clean up and write tests for permissions. Now we use fstat which should be cheap, and lets us check the permissions and the file size
192
    def append(self, relpath, f, mode=None):
1725.2.1 by Robert Collins
Make LocalTransport faster by not normpathing every internal path translation.
193
        """Append the text in the file-like object into the final location."""
194
        abspath = self._abspath(relpath)
1755.3.3 by Robert Collins
allow None == 0666 for mode.
195
        if mode is None:
1755.3.7 by John Arbash Meinel
Clean up and write tests for permissions. Now we use fstat which should be cheap, and lets us check the permissions and the file size
196
            local_mode = self._default_file_mode
197
        else:
198
            local_mode = mode
1530.1.4 by Robert Collins
integrate Memory tests into transport interface tests.
199
        try:
1755.3.7 by John Arbash Meinel
Clean up and write tests for permissions. Now we use fstat which should be cheap, and lets us check the permissions and the file size
200
            fd = os.open(abspath, _append_flags, local_mode)
1530.1.4 by Robert Collins
integrate Memory tests into transport interface tests.
201
        except (IOError, OSError),e:
202
            self._translate_error(e, relpath)
1755.3.1 by Robert Collins
Tune the time to build our kernel_like tree : make LocalTransport.put faster, AtomicFile faster, LocalTransport.append faster.
203
        try:
1755.3.7 by John Arbash Meinel
Clean up and write tests for permissions. Now we use fstat which should be cheap, and lets us check the permissions and the file size
204
            st = os.fstat(fd)
205
            result = st.st_size
206
            if mode is not None and mode != S_IMODE(st.st_mode):
207
                # Because of umask, we may still need to chmod the file.
208
                # But in the general case, we won't have to
209
                os.chmod(abspath, mode)
1755.3.1 by Robert Collins
Tune the time to build our kernel_like tree : make LocalTransport.put faster, AtomicFile faster, LocalTransport.append faster.
210
            # TODO: make a raw FD version of _pump ?
211
            self._pump_to_fd(f, fd)
1711.7.25 by John Arbash Meinel
try/finally to close files, _KnitData was keeping a handle to a file it never used again, and using transport.rename() when it wanted transport.move()
212
        finally:
1755.3.1 by Robert Collins
Tune the time to build our kernel_like tree : make LocalTransport.put faster, AtomicFile faster, LocalTransport.append faster.
213
            os.close(fd)
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.
214
        return result
907.1.1 by John Arbash Meinel
Reworking the Branch and Store code to support an abstracted filesystem layer.
215
1755.3.1 by Robert Collins
Tune the time to build our kernel_like tree : make LocalTransport.put faster, AtomicFile faster, LocalTransport.append faster.
216
    def _pump_to_fd(self, fromfile, to_fd):
217
        """Copy contents of one file to another."""
218
        BUFSIZE = 32768
219
        while True:
220
            b = fromfile.read(BUFSIZE)
221
            if not b:
222
                break
223
            os.write(to_fd, b)
224
907.1.1 by John Arbash Meinel
Reworking the Branch and Store code to support an abstracted filesystem layer.
225
    def copy(self, rel_from, rel_to):
226
        """Copy the item at rel_from to the location at rel_to"""
1725.2.1 by Robert Collins
Make LocalTransport faster by not normpathing every internal path translation.
227
        path_from = self._abspath(rel_from)
228
        path_to = self._abspath(rel_to)
907.1.48 by John Arbash Meinel
Updated LocalTransport by passing it through the transport_test suite, and got it to pass.
229
        try:
230
            shutil.copy(path_from, path_to)
1185.31.44 by John Arbash Meinel
Cleaned up Exceptions for all transports.
231
        except (IOError, OSError),e:
232
            # TODO: What about path_to?
233
            self._translate_error(e, path_from)
907.1.1 by John Arbash Meinel
Reworking the Branch and Store code to support an abstracted filesystem layer.
234
1553.5.13 by Martin Pool
New Transport.rename that mustn't overwrite
235
    def rename(self, rel_from, rel_to):
1725.2.1 by Robert Collins
Make LocalTransport faster by not normpathing every internal path translation.
236
        path_from = self._abspath(rel_from)
1553.5.13 by Martin Pool
New Transport.rename that mustn't overwrite
237
        try:
238
            # *don't* call bzrlib.osutils.rename, because we want to 
239
            # detect errors on rename
1725.2.1 by Robert Collins
Make LocalTransport faster by not normpathing every internal path translation.
240
            os.rename(path_from, self._abspath(rel_to))
1553.5.13 by Martin Pool
New Transport.rename that mustn't overwrite
241
        except (IOError, OSError),e:
242
            # TODO: What about path_to?
243
            self._translate_error(e, path_from)
244
907.1.1 by John Arbash Meinel
Reworking the Branch and Store code to support an abstracted filesystem layer.
245
    def move(self, rel_from, rel_to):
246
        """Move the item at rel_from to the location at rel_to"""
1725.2.1 by Robert Collins
Make LocalTransport faster by not normpathing every internal path translation.
247
        path_from = self._abspath(rel_from)
248
        path_to = self._abspath(rel_to)
907.1.1 by John Arbash Meinel
Reworking the Branch and Store code to support an abstracted filesystem layer.
249
907.1.48 by John Arbash Meinel
Updated LocalTransport by passing it through the transport_test suite, and got it to pass.
250
        try:
1553.5.13 by Martin Pool
New Transport.rename that mustn't overwrite
251
            # this version will delete the destination if necessary
1185.31.58 by John Arbash Meinel
Updating for new transport tests so that they pass on win32
252
            rename(path_from, path_to)
1185.31.44 by John Arbash Meinel
Cleaned up Exceptions for all transports.
253
        except (IOError, OSError),e:
254
            # TODO: What about path_to?
255
            self._translate_error(e, path_from)
907.1.1 by John Arbash Meinel
Reworking the Branch and Store code to support an abstracted filesystem layer.
256
257
    def delete(self, relpath):
258
        """Delete the item at relpath"""
1185.31.44 by John Arbash Meinel
Cleaned up Exceptions for all transports.
259
        path = relpath
907.1.48 by John Arbash Meinel
Updated LocalTransport by passing it through the transport_test suite, and got it to pass.
260
        try:
1725.2.1 by Robert Collins
Make LocalTransport faster by not normpathing every internal path translation.
261
            path = self._abspath(relpath)
1185.31.44 by John Arbash Meinel
Cleaned up Exceptions for all transports.
262
            os.remove(path)
263
        except (IOError, OSError),e:
264
            self._translate_error(e, path)
907.1.1 by John Arbash Meinel
Reworking the Branch and Store code to support an abstracted filesystem layer.
265
1185.58.2 by John Arbash Meinel
Added mode to the appropriate transport functions, and tests to make sure they work.
266
    def copy_to(self, relpaths, other, mode=None, pb=None):
907.1.28 by John Arbash Meinel
Added pb to function that were missing, implemented a basic double-dispatch copy_to function.
267
        """Copy a set of entries from self into another Transport.
268
269
        :param relpaths: A list/generator of entries to be copied.
270
        """
271
        if isinstance(other, LocalTransport):
272
            # Both from & to are on the local filesystem
273
            # Unfortunately, I can't think of anything faster than just
274
            # copying them across, one by one :(
275
            total = self._get_total(relpaths)
276
            count = 0
277
            for path in relpaths:
278
                self._update_pb(pb, 'copy-to', count, total)
1185.16.158 by John Arbash Meinel
Added a test that copy_to raises NoSuchFile when a directory is missing (not IOError)
279
                try:
1725.2.1 by Robert Collins
Make LocalTransport faster by not normpathing every internal path translation.
280
                    mypath = self._abspath(path)
281
                    otherpath = other._abspath(path)
1185.58.2 by John Arbash Meinel
Added mode to the appropriate transport functions, and tests to make sure they work.
282
                    shutil.copy(mypath, otherpath)
283
                    if mode is not None:
284
                        os.chmod(otherpath, mode)
1185.31.44 by John Arbash Meinel
Cleaned up Exceptions for all transports.
285
                except (IOError, OSError),e:
286
                    self._translate_error(e, path)
907.1.28 by John Arbash Meinel
Added pb to function that were missing, implemented a basic double-dispatch copy_to function.
287
                count += 1
288
            return count
289
        else:
1185.58.2 by John Arbash Meinel
Added mode to the appropriate transport functions, and tests to make sure they work.
290
            return super(LocalTransport, self).copy_to(relpaths, other, mode=mode, pb=pb)
907.1.28 by John Arbash Meinel
Added pb to function that were missing, implemented a basic double-dispatch copy_to function.
291
1400.1.1 by Robert Collins
implement a basic test for the ui branch command from http servers
292
    def listable(self):
293
        """See Transport.listable."""
294
        return True
907.1.28 by John Arbash Meinel
Added pb to function that were missing, implemented a basic double-dispatch copy_to function.
295
907.1.2 by John Arbash Meinel
Working on making Branch() do all of it's work over a Transport.
296
    def list_dir(self, relpath):
297
        """Return a list of all files at the given location.
298
        WARNING: many transports do not support this, so trying avoid using
299
        it if at all possible.
300
        """
1725.2.1 by Robert Collins
Make LocalTransport faster by not normpathing every internal path translation.
301
        path = self._abspath(relpath)
907.1.48 by John Arbash Meinel
Updated LocalTransport by passing it through the transport_test suite, and got it to pass.
302
        try:
1685.1.45 by John Arbash Meinel
Moved url functions into bzrlib.urlutils
303
            return [urlutils.escape(entry) for entry in os.listdir(path)]
1607.1.3 by Robert Collins
Apply David Allouches list_dir quoting fix.
304
        except (IOError, OSError), e:
1185.31.44 by John Arbash Meinel
Cleaned up Exceptions for all transports.
305
            self._translate_error(e, path)
907.1.2 by John Arbash Meinel
Working on making Branch() do all of it's work over a Transport.
306
307
    def stat(self, relpath):
308
        """Return the stat information for a file.
309
        """
1185.31.44 by John Arbash Meinel
Cleaned up Exceptions for all transports.
310
        path = relpath
907.1.48 by John Arbash Meinel
Updated LocalTransport by passing it through the transport_test suite, and got it to pass.
311
        try:
1725.2.1 by Robert Collins
Make LocalTransport faster by not normpathing every internal path translation.
312
            path = self._abspath(relpath)
1185.31.44 by John Arbash Meinel
Cleaned up Exceptions for all transports.
313
            return os.stat(path)
314
        except (IOError, OSError),e:
315
            self._translate_error(e, path)
907.1.2 by John Arbash Meinel
Working on making Branch() do all of it's work over a Transport.
316
907.1.24 by John Arbash Meinel
Remote functionality work.
317
    def lock_read(self, relpath):
318
        """Lock the given file for shared (read) access.
319
        :return: A lock object, which should be passed to Transport.unlock()
320
        """
321
        from bzrlib.lock import ReadLock
1185.65.29 by Robert Collins
Implement final review suggestions.
322
        path = relpath
323
        try:
1725.2.1 by Robert Collins
Make LocalTransport faster by not normpathing every internal path translation.
324
            path = self._abspath(relpath)
1185.65.29 by Robert Collins
Implement final review suggestions.
325
            return ReadLock(path)
326
        except (IOError, OSError), e:
327
            self._translate_error(e, path)
907.1.24 by John Arbash Meinel
Remote functionality work.
328
329
    def lock_write(self, relpath):
330
        """Lock the given file for exclusive (write) access.
331
        WARNING: many transports do not support this, so trying avoid using it
332
333
        :return: A lock object, which should be passed to Transport.unlock()
334
        """
335
        from bzrlib.lock import WriteLock
1725.2.1 by Robert Collins
Make LocalTransport faster by not normpathing every internal path translation.
336
        return WriteLock(self._abspath(relpath))
907.1.24 by John Arbash Meinel
Remote functionality work.
337
1534.4.15 by Robert Collins
Remove shutil dependency in upgrade - create a delete_tree method for transports.
338
    def rmdir(self, relpath):
339
        """See Transport.rmdir."""
340
        path = relpath
341
        try:
1725.2.1 by Robert Collins
Make LocalTransport faster by not normpathing every internal path translation.
342
            path = self._abspath(relpath)
1534.4.15 by Robert Collins
Remove shutil dependency in upgrade - create a delete_tree method for transports.
343
            os.rmdir(path)
344
        except (IOError, OSError),e:
345
            self._translate_error(e, path)
1442.1.41 by Robert Collins
move duplicate scratch logic into a scratch transport
346
1608.2.7 by Martin Pool
Rename supports_unix_modebits to _can_roundtrip_unix_modebits for clarity
347
    def _can_roundtrip_unix_modebits(self):
1608.2.5 by Martin Pool
Add Transport.supports_unix_modebits, so tests can
348
        if sys.platform == 'win32':
349
            # anyone else?
350
            return False
351
        else:
352
            return True
353
354
1530.1.3 by Robert Collins
transport implementations now tested consistently.
355
class LocalRelpathServer(Server):
1530.1.1 by Robert Collins
Minimal infrastructure to test TransportTestProviderAdapter.
356
    """A pretend server for local transports, using relpaths."""
357
1530.1.3 by Robert Collins
transport implementations now tested consistently.
358
    def get_url(self):
359
        """See Transport.Server.get_url."""
360
        return "."
361
362
363
class LocalAbspathServer(Server):
1530.1.1 by Robert Collins
Minimal infrastructure to test TransportTestProviderAdapter.
364
    """A pretend server for local transports, using absolute paths."""
365
1530.1.3 by Robert Collins
transport implementations now tested consistently.
366
    def get_url(self):
367
        """See Transport.Server.get_url."""
368
        return os.path.abspath("")
369
370
371
class LocalURLServer(Server):
1530.1.1 by Robert Collins
Minimal infrastructure to test TransportTestProviderAdapter.
372
    """A pretend server for local transports, using file:// urls."""
1530.1.3 by Robert Collins
transport implementations now tested consistently.
373
374
    def get_url(self):
375
        """See Transport.Server.get_url."""
1685.1.45 by John Arbash Meinel
Moved url functions into bzrlib.urlutils
376
        return urlutils.local_path_to_url('')
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.
377
378
379
def get_test_permutations():
380
    """Return the permutations to be used in testing."""
381
    return [(LocalTransport, LocalRelpathServer),
382
            (LocalTransport, LocalAbspathServer),
383
            (LocalTransport, LocalURLServer),
384
            ]