~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/transport/local.py

  • Committer: John Arbash Meinel
  • Date: 2005-09-17 20:29:29 UTC
  • mto: (1393.2.1)
  • mto: This revision was merged to the branch mainline in revision 1396.
  • Revision ID: john@arbash-meinel.com-20050917202929-a9e4a3be80bf4ba4
Working on getting tests to run. TestFetch only works if named runTest

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005 Canonical Ltd
2
 
 
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.
7
 
 
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.
12
 
 
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
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
 
import urllib
27
 
 
28
 
from bzrlib.trace import mutter
 
1
#!/usr/bin/env python
 
2
"""\
 
3
An implementation of the Transport object for local
 
4
filesystem access.
 
5
"""
 
6
 
29
7
from bzrlib.transport import Transport, register_transport, \
30
8
    TransportError, NoSuchFile, FileExists
31
 
from bzrlib.osutils import abspath
 
9
import os, errno
32
10
 
33
11
class LocalTransportError(TransportError):
34
12
    pass
35
13
 
36
 
 
37
14
class LocalTransport(Transport):
38
15
    """This is the transport agent for local filesystem access."""
39
16
 
41
18
        """Set the base path where files will be stored."""
42
19
        if base.startswith('file://'):
43
20
            base = base[7:]
44
 
        # realpath is incompatible with symlinks. When we traverse
45
 
        # up we might be able to normpath stuff. RBC 20051003
46
 
        super(LocalTransport, self).__init__(
47
 
            os.path.normpath(abspath(base)))
 
21
        super(LocalTransport, self).__init__(os.path.realpath(base))
48
22
 
49
23
    def should_cache(self):
50
24
        return False
60
34
            return LocalTransport(self.abspath(offset))
61
35
 
62
36
    def abspath(self, relpath):
63
 
        """Return the full url to the given relative URL.
 
37
        """Return the full url to the given relative path.
64
38
        This can be supplied with a string or a list
65
39
        """
66
 
        assert isinstance(relpath, basestring), (type(relpath), relpath)
67
 
        return os.path.join(self.base, urllib.unquote(relpath))
 
40
        if isinstance(relpath, basestring):
 
41
            relpath = [relpath]
 
42
        return os.path.join(self.base, *relpath)
68
43
 
69
44
    def relpath(self, abspath):
70
45
        """Return the local path portion from a given absolute path.
71
46
        """
72
 
        from bzrlib.osutils import relpath
73
 
        if abspath is None:
74
 
            abspath = u'.'
75
 
        return relpath(self.base, abspath)
 
47
        from bzrlib.branch import _relpath
 
48
        return _relpath(self.base, abspath)
76
49
 
77
50
    def has(self, relpath):
78
51
        return os.access(self.abspath(relpath), os.F_OK)
86
59
            path = self.abspath(relpath)
87
60
            return open(path, 'rb')
88
61
        except IOError,e:
89
 
            if e.errno in (errno.ENOENT, errno.ENOTDIR):
90
 
                raise NoSuchFile('File or directory %r does not exist' % path, orig_error=e)
 
62
            if e.errno == errno.ENOENT:
 
63
                raise NoSuchFile('File %r does not exist' % path, orig_error=e)
91
64
            raise LocalTransportError(orig_error=e)
92
65
 
93
66
    def put(self, relpath, f):
111
84
        finally:
112
85
            fp.close()
113
86
 
114
 
    def iter_files_recursive(self):
115
 
        """Iter the relative paths of files in the transports sub-tree."""
116
 
        queue = list(self.list_dir(u'.'))
117
 
        while queue:
118
 
            relpath = urllib.quote(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
 
 
126
87
    def mkdir(self, relpath):
127
88
        """Create a directory at the given path."""
128
89
        try:
183
144
            count = 0
184
145
            for path in relpaths:
185
146
                self._update_pb(pb, 'copy-to', count, total)
186
 
                try:
187
 
                    shutil.copy(self.abspath(path), other.abspath(path))
188
 
                except IOError, e:
189
 
                    if e.errno in (errno.ENOENT, errno.ENOTDIR):
190
 
                        raise NoSuchFile('File or directory %r does not exist' % path, orig_error=e)
191
 
                    raise LocalTransportError(orig_error=e)
 
147
                shutil.copy(self.abspath(path), other.abspath(path))
192
148
                count += 1
193
149
            return count
194
150
        else:
195
151
            return super(LocalTransport, self).copy_to(relpaths, other, pb=pb)
196
152
 
197
 
    def listable(self):
198
 
        """See Transport.listable."""
199
 
        return True
 
153
 
 
154
    def async_get(self, relpath):
 
155
        """Make a request for an file at the given location, but
 
156
        don't worry about actually getting it yet.
 
157
 
 
158
        :rtype: AsyncFile
 
159
        """
 
160
        raise NotImplementedError
200
161
 
201
162
    def list_dir(self, relpath):
202
163
        """Return a list of all files at the given location.
232
193
        from bzrlib.lock import WriteLock
233
194
        return WriteLock(self.abspath(relpath))
234
195
 
235
 
 
236
 
class ScratchTransport(LocalTransport):
237
 
    """A transport that works in a temporary dir and cleans up after itself.
238
 
    
239
 
    The dir only exists for the lifetime of the Python object.
240
 
    Obviously you should not put anything precious in it.
241
 
    """
242
 
 
243
 
    def __init__(self, base=None):
244
 
        if base is None:
245
 
            base = tempfile.mkdtemp()
246
 
        super(ScratchTransport, self).__init__(base)
247
 
 
248
 
    def __del__(self):
249
 
        shutil.rmtree(self.base, ignore_errors=True)
250
 
        mutter("%r destroyed" % self)
 
196
# If nothing else matches, try the LocalTransport
 
197
register_transport(None, LocalTransport)
 
198
register_transport('file://', LocalTransport)