~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-15 21:35:53 UTC
  • mfrom: (907.1.57)
  • mto: (1393.2.1)
  • mto: This revision was merged to the branch mainline in revision 1396.
  • Revision ID: john@arbash-meinel.com-20050915213552-a6c83a5ef1e20897
(broken) Transport work is merged in. Tests do not pass yet.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#!/usr/bin/env python
 
2
"""\
 
3
An implementation of the Transport object for local
 
4
filesystem access.
 
5
"""
 
6
 
 
7
from bzrlib.transport import Transport, register_transport, \
 
8
    TransportError, NoSuchFile, FileExists
 
9
import os, errno
 
10
 
 
11
class LocalTransportError(TransportError):
 
12
    pass
 
13
 
 
14
class LocalTransport(Transport):
 
15
    """This is the transport agent for local filesystem access."""
 
16
 
 
17
    def __init__(self, base):
 
18
        """Set the base path where files will be stored."""
 
19
        if base.startswith('file://'):
 
20
            base = base[7:]
 
21
        super(LocalTransport, self).__init__(os.path.realpath(base))
 
22
 
 
23
    def should_cache(self):
 
24
        return False
 
25
 
 
26
    def clone(self, offset=None):
 
27
        """Return a new LocalTransport with root at self.base + offset
 
28
        Because the local filesystem does not require a connection, 
 
29
        we can just return a new object.
 
30
        """
 
31
        if offset is None:
 
32
            return LocalTransport(self.base)
 
33
        else:
 
34
            return LocalTransport(self.abspath(offset))
 
35
 
 
36
    def abspath(self, relpath):
 
37
        """Return the full url to the given relative path.
 
38
        This can be supplied with a string or a list
 
39
        """
 
40
        if isinstance(relpath, basestring):
 
41
            relpath = [relpath]
 
42
        return os.path.join(self.base, *relpath)
 
43
 
 
44
    def relpath(self, abspath):
 
45
        """Return the local path portion from a given absolute path.
 
46
        """
 
47
        from branch import _relpath
 
48
        return _relpath(self.base, abspath)
 
49
 
 
50
    def has(self, relpath):
 
51
        return os.access(self.abspath(relpath), os.F_OK)
 
52
 
 
53
    def get(self, relpath):
 
54
        """Get the file at the given relative path.
 
55
 
 
56
        :param relpath: The relative path to the file
 
57
        """
 
58
        try:
 
59
            path = self.abspath(relpath)
 
60
            return open(path, 'rb')
 
61
        except IOError,e:
 
62
            if e.errno == errno.ENOENT:
 
63
                raise NoSuchFile('File %r does not exist' % path, orig_error=e)
 
64
            raise LocalTransportError(orig_error=e)
 
65
 
 
66
    def put(self, relpath, f):
 
67
        """Copy the file-like or string object into the location.
 
68
 
 
69
        :param relpath: Location to put the contents, relative to base.
 
70
        :param f:       File-like or string object.
 
71
        """
 
72
        from bzrlib.atomicfile import AtomicFile
 
73
 
 
74
        try:
 
75
            path = self.abspath(relpath)
 
76
            fp = AtomicFile(path, 'wb')
 
77
        except IOError, e:
 
78
            if e.errno == errno.ENOENT:
 
79
                raise NoSuchFile('File %r does not exist' % path, orig_error=e)
 
80
            raise LocalTransportError(orig_error=e)
 
81
        try:
 
82
            self._pump(f, fp)
 
83
            fp.commit()
 
84
        finally:
 
85
            fp.close()
 
86
 
 
87
    def mkdir(self, relpath):
 
88
        """Create a directory at the given path."""
 
89
        try:
 
90
            os.mkdir(self.abspath(relpath))
 
91
        except OSError,e:
 
92
            if e.errno == errno.EEXIST:
 
93
                raise FileExists(orig_error=e)
 
94
            elif e.errno == errno.ENOENT:
 
95
                raise NoSuchFile(orig_error=e)
 
96
            raise LocalTransportError(orig_error=e)
 
97
 
 
98
    def append(self, relpath, f):
 
99
        """Append the text in the file-like object into the final
 
100
        location.
 
101
        """
 
102
        fp = open(self.abspath(relpath), 'ab')
 
103
        self._pump(f, fp)
 
104
 
 
105
    def copy(self, rel_from, rel_to):
 
106
        """Copy the item at rel_from to the location at rel_to"""
 
107
        import shutil
 
108
        path_from = self.abspath(rel_from)
 
109
        path_to = self.abspath(rel_to)
 
110
        try:
 
111
            shutil.copy(path_from, path_to)
 
112
        except OSError,e:
 
113
            raise LocalTransportError(orig_error=e)
 
114
 
 
115
    def move(self, rel_from, rel_to):
 
116
        """Move the item at rel_from to the location at rel_to"""
 
117
        path_from = self.abspath(rel_from)
 
118
        path_to = self.abspath(rel_to)
 
119
 
 
120
        try:
 
121
            os.rename(path_from, path_to)
 
122
        except OSError,e:
 
123
            raise LocalTransportError(orig_error=e)
 
124
 
 
125
    def delete(self, relpath):
 
126
        """Delete the item at relpath"""
 
127
        try:
 
128
            os.remove(self.abspath(relpath))
 
129
        except OSError,e:
 
130
            raise LocalTransportError(orig_error=e)
 
131
 
 
132
    def copy_to(self, relpaths, other, pb=None):
 
133
        """Copy a set of entries from self into another Transport.
 
134
 
 
135
        :param relpaths: A list/generator of entries to be copied.
 
136
        """
 
137
        if isinstance(other, LocalTransport):
 
138
            # Both from & to are on the local filesystem
 
139
            # Unfortunately, I can't think of anything faster than just
 
140
            # copying them across, one by one :(
 
141
            import shutil
 
142
 
 
143
            total = self._get_total(relpaths)
 
144
            count = 0
 
145
            for path in relpaths:
 
146
                self._update_pb(pb, 'copy-to', count, total)
 
147
                shutil.copy(self.abspath(path), other.abspath(path))
 
148
                count += 1
 
149
            return count
 
150
        else:
 
151
            return super(LocalTransport, self).copy_to(relpaths, other, pb=pb)
 
152
 
 
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
 
161
 
 
162
    def list_dir(self, relpath):
 
163
        """Return a list of all files at the given location.
 
164
        WARNING: many transports do not support this, so trying avoid using
 
165
        it if at all possible.
 
166
        """
 
167
        try:
 
168
            return os.listdir(self.abspath(relpath))
 
169
        except OSError,e:
 
170
            raise LocalTransportError(orig_error=e)
 
171
 
 
172
    def stat(self, relpath):
 
173
        """Return the stat information for a file.
 
174
        """
 
175
        try:
 
176
            return os.stat(self.abspath(relpath))
 
177
        except OSError,e:
 
178
            raise LocalTransportError(orig_error=e)
 
179
 
 
180
    def lock_read(self, relpath):
 
181
        """Lock the given file for shared (read) access.
 
182
        :return: A lock object, which should be passed to Transport.unlock()
 
183
        """
 
184
        from bzrlib.lock import ReadLock
 
185
        return ReadLock(self.abspath(relpath))
 
186
 
 
187
    def lock_write(self, relpath):
 
188
        """Lock the given file for exclusive (write) access.
 
189
        WARNING: many transports do not support this, so trying avoid using it
 
190
 
 
191
        :return: A lock object, which should be passed to Transport.unlock()
 
192
        """
 
193
        from bzrlib.lock import WriteLock
 
194
        return WriteLock(self.abspath(relpath))
 
195
 
 
196
# If nothing else matches, try the LocalTransport
 
197
register_transport(None, LocalTransport)
 
198
register_transport('file://', LocalTransport)