3
An implementation of the Transport object for local
7
from bzrlib.transport import Transport, register_transport, \
8
TransportError, NoSuchFile, FileExists
11
class LocalTransportError(TransportError):
14
class LocalTransport(Transport):
15
"""This is the transport agent for local filesystem access."""
17
def __init__(self, base):
18
"""Set the base path where files will be stored."""
19
if base.startswith('file://'):
21
super(LocalTransport, self).__init__(os.path.realpath(base))
23
def should_cache(self):
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.
32
return LocalTransport(self.base)
34
return LocalTransport(self.abspath(offset))
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
40
if isinstance(relpath, basestring):
42
return os.path.join(self.base, *relpath)
44
def relpath(self, abspath):
45
"""Return the local path portion from a given absolute path.
47
from branch import _relpath
48
return _relpath(self.base, abspath)
50
def has(self, relpath):
51
return os.access(self.abspath(relpath), os.F_OK)
53
def get(self, relpath):
54
"""Get the file at the given relative path.
56
:param relpath: The relative path to the file
59
path = self.abspath(relpath)
60
return open(path, 'rb')
62
if e.errno == errno.ENOENT:
63
raise NoSuchFile('File %r does not exist' % path, orig_error=e)
64
raise LocalTransportError(orig_error=e)
66
def put(self, relpath, f):
67
"""Copy the file-like or string object into the location.
69
:param relpath: Location to put the contents, relative to base.
70
:param f: File-like or string object.
72
from bzrlib.atomicfile import AtomicFile
75
path = self.abspath(relpath)
76
fp = AtomicFile(path, 'wb')
78
if e.errno == errno.ENOENT:
79
raise NoSuchFile('File %r does not exist' % path, orig_error=e)
80
raise LocalTransportError(orig_error=e)
87
def mkdir(self, relpath):
88
"""Create a directory at the given path."""
90
os.mkdir(self.abspath(relpath))
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)
98
def append(self, relpath, f):
99
"""Append the text in the file-like object into the final
102
fp = open(self.abspath(relpath), 'ab')
105
def copy(self, rel_from, rel_to):
106
"""Copy the item at rel_from to the location at rel_to"""
108
path_from = self.abspath(rel_from)
109
path_to = self.abspath(rel_to)
111
shutil.copy(path_from, path_to)
113
raise LocalTransportError(orig_error=e)
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)
121
os.rename(path_from, path_to)
123
raise LocalTransportError(orig_error=e)
125
def delete(self, relpath):
126
"""Delete the item at relpath"""
128
os.remove(self.abspath(relpath))
130
raise LocalTransportError(orig_error=e)
132
def copy_to(self, relpaths, other, pb=None):
133
"""Copy a set of entries from self into another Transport.
135
:param relpaths: A list/generator of entries to be copied.
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 :(
143
total = self._get_total(relpaths)
145
for path in relpaths:
146
self._update_pb(pb, 'copy-to', count, total)
147
shutil.copy(self.abspath(path), other.abspath(path))
151
return super(LocalTransport, self).copy_to(relpaths, other, pb=pb)
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.
160
raise NotImplementedError
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.
168
return os.listdir(self.abspath(relpath))
170
raise LocalTransportError(orig_error=e)
172
def stat(self, relpath):
173
"""Return the stat information for a file.
176
return os.stat(self.abspath(relpath))
178
raise LocalTransportError(orig_error=e)
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()
184
from bzrlib.lock import ReadLock
185
return ReadLock(self.abspath(relpath))
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
191
:return: A lock object, which should be passed to Transport.unlock()
193
from bzrlib.lock import WriteLock
194
return WriteLock(self.abspath(relpath))
196
# If nothing else matches, try the LocalTransport
197
register_transport(None, LocalTransport)
198
register_transport('file://', LocalTransport)