~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/transport/local.py

[merge] from robert and fix up tests

Show diffs side-by-side

added added

removed removed

Lines of Context:
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
16
 
"""Implementation of Transport for the local filesystem.
17
 
"""
18
 
 
 
16
 
 
17
"""Transport for the local filesystem.
 
18
 
 
19
This is a fairly thin wrapper on regular file IO."""
 
20
 
 
21
import os
 
22
import errno
 
23
import shutil
 
24
from stat import ST_MODE, S_ISDIR, ST_SIZE
 
25
import tempfile
 
26
 
 
27
from bzrlib.trace import mutter
19
28
from bzrlib.transport import Transport, register_transport, \
20
29
    TransportError, NoSuchFile, FileExists
21
30
from bzrlib.osutils import abspath
22
 
import os, errno
23
31
 
24
32
class LocalTransportError(TransportError):
25
33
    pass
26
34
 
 
35
 
27
36
class LocalTransport(Transport):
28
37
    """This is the transport agent for local filesystem access."""
29
38
 
61
70
        """Return the local path portion from a given absolute path.
62
71
        """
63
72
        from bzrlib.osutils import relpath
 
73
        if abspath is None:
 
74
            abspath = '.'
64
75
        return relpath(self.base, abspath)
65
76
 
66
77
    def has(self, relpath):
79
90
                raise NoSuchFile('File or directory %r does not exist' % path, orig_error=e)
80
91
            raise LocalTransportError(orig_error=e)
81
92
 
82
 
    def get_partial(self, relpath, start, length=None):
83
 
        """Get just part of a file.
84
 
 
85
 
        :param relpath: Path to the file, relative to base
86
 
        :param start: The starting position to read from
87
 
        :param length: The length to read. A length of None indicates
88
 
                       read to the end of the file.
89
 
        :return: A file-like object containing at least the specified bytes.
90
 
                 Some implementations may return objects which can be read
91
 
                 past this length, but this is not guaranteed.
92
 
        """
93
 
        # LocalTransport.get_partial() doesn't care about the length
94
 
        # argument, because it is using a local file, and thus just
95
 
        # returns the file seek'ed to the appropriate location.
96
 
        try:
97
 
            path = self.abspath(relpath)
98
 
            f = open(path, 'rb')
99
 
            f.seek(start, 0)
100
 
            return f
101
 
        except IOError,e:
102
 
            if e.errno == errno.ENOENT:
103
 
                raise NoSuchFile('File %r does not exist' % path, orig_error=e)
104
 
            raise LocalTransportError(orig_error=e)
105
 
 
106
93
    def put(self, relpath, f):
107
94
        """Copy the file-like or string object into the location.
108
95
 
124
111
        finally:
125
112
            fp.close()
126
113
 
 
114
    def iter_files_recursive(self):
 
115
        """Iter the relative paths of files in the transports sub-tree."""
 
116
        queue = list(self.list_dir('.'))
 
117
        while queue:
 
118
            relpath = queue.pop(0)
 
119
            st = self.stat(relpath)
 
120
            if S_ISDIR(st[ST_MODE]):
 
121
                for i, basename in enumerate(self.list_dir(relpath)):
 
122
                    queue.insert(i, relpath+'/'+basename)
 
123
            else:
 
124
                yield relpath
 
125
 
127
126
    def mkdir(self, relpath):
128
127
        """Create a directory at the given path."""
129
128
        try:
228
227
        from bzrlib.lock import WriteLock
229
228
        return WriteLock(self.abspath(relpath))
230
229
 
 
230
 
 
231
class ScratchTransport(LocalTransport):
 
232
    """A transport that works in a temporary dir and cleans up after itself.
 
233
    
 
234
    The dir only exists for the lifetime of the Python object.
 
235
    Obviously you should not put anything precious in it.
 
236
    """
 
237
 
 
238
    def __init__(self, base=None):
 
239
        if base is None:
 
240
            base = tempfile.mkdtemp()
 
241
        super(ScratchTransport, self).__init__(base)
 
242
 
 
243
    def __del__(self):
 
244
        shutil.rmtree(self.base, ignore_errors=True)
 
245
        mutter("%r destroyed" % self)
 
246
 
231
247
# If nothing else matches, try the LocalTransport
232
248
register_transport(None, LocalTransport)
233
249
register_transport('file://', LocalTransport)