24
24
from stat import ST_MODE, S_ISDIR, ST_SIZE
27
from bzrlib.osutils import (abspath, realpath, normpath, pathjoin, rename,
28
check_legal_path, rmtree)
29
from bzrlib.symbol_versioning import warn
28
30
from bzrlib.trace import mutter
29
31
from bzrlib.transport import Transport, Server
30
from bzrlib.osutils import (abspath, realpath, normpath, pathjoin, rename,
31
check_legal_path, rmtree)
32
import bzrlib.urlutils as urlutils
34
35
class LocalTransport(Transport):
37
38
def __init__(self, base):
38
39
"""Set the base path where files will be stored."""
39
if base.startswith('file://'):
40
base = base[len('file://'):]
41
# realpath is incompatible with symlinks. When we traverse
42
# up we might be able to normpath stuff. RBC 20051003
43
base = normpath(abspath(base))
40
if not base.startswith('file://'):
41
warn("Instantiating LocalTransport with a filesystem path"
42
" is deprecated as of bzr 0.8."
43
" Please use bzrlib.transport.get_transport()"
44
" or pass in a file:// url.",
48
base = urlutils.local_path_to_url(base)
44
49
if base[-1] != '/':
46
51
super(LocalTransport, self).__init__(base)
52
self._local_base = urlutils.local_path_from_url(base)
48
54
def should_cache(self):
61
67
def abspath(self, relpath):
62
68
"""Return the full url to the given relative URL."""
63
69
assert isinstance(relpath, basestring), (type(relpath), relpath)
64
result = normpath(pathjoin(self.base, urllib.unquote(relpath)))
65
#if result[-1] != '/':
70
# jam 20060426 Using normpath on the real path, because that ensures
71
# proper handling of stuff like
72
path = normpath(pathjoin(self._local_base, urlutils.unescape(relpath)))
73
return urlutils.local_path_to_url(path)
75
def local_abspath(self, relpath):
76
"""Transform the given relative path URL into the actual path on disk
78
This function only exists for the LocalTransport, since it is
79
the only one that has direct local access.
80
This is mostly for stuff like WorkingTree which needs to know
81
the local working directory.
83
absurl = self.abspath(relpath)
84
# mutter(u'relpath %s => base: %s, absurl %s', relpath, self.base, absurl)
85
return urlutils.local_path_from_url(absurl)
69
87
def relpath(self, abspath):
70
88
"""Return the local path portion from a given absolute path.
72
from bzrlib.osutils import relpath, strip_trailing_slash
73
90
if abspath is None:
76
return relpath(strip_trailing_slash(self.base),
77
strip_trailing_slash(abspath))
93
return urlutils.file_relpath(
94
urlutils.strip_trailing_slash(self.base),
95
urlutils.strip_trailing_slash(abspath))
79
97
def has(self, relpath):
80
return os.access(self.abspath(relpath), os.F_OK)
98
return os.access(self.local_abspath(relpath), os.F_OK)
82
100
def get(self, relpath):
83
101
"""Get the file at the given relative path.
85
103
:param relpath: The relative path to the file
88
path = self.abspath(relpath)
106
path = self.local_abspath(relpath)
107
# mutter('LocalTransport.get(%r) => %r', relpath, path)
89
108
return open(path, 'rb')
90
109
except (IOError, OSError),e:
91
110
self._translate_error(e, path)
103
path = self.abspath(relpath)
122
path = self.local_abspath(relpath)
104
123
check_legal_path(path)
105
124
fp = AtomicFile(path, 'wb', new_mode=mode)
106
125
except (IOError, OSError),e:
142
fp = open(self.abspath(relpath), 'ab')
161
fp = open(self.local_abspath(relpath), 'ab')
143
162
if mode is not None:
144
os.chmod(self.abspath(relpath), mode)
163
os.chmod(self.local_abspath(relpath), mode)
145
164
except (IOError, OSError),e:
146
165
self._translate_error(e, relpath)
147
166
# win32 workaround (tell on an unwritten file returns 0)
153
172
def copy(self, rel_from, rel_to):
154
173
"""Copy the item at rel_from to the location at rel_to"""
155
path_from = self.abspath(rel_from)
156
path_to = self.abspath(rel_to)
174
path_from = self.local_abspath(rel_from)
175
path_to = self.local_abspath(rel_to)
158
177
shutil.copy(path_from, path_to)
159
178
except (IOError, OSError),e:
161
180
self._translate_error(e, path_from)
163
182
def rename(self, rel_from, rel_to):
164
path_from = self.abspath(rel_from)
183
path_from = self.local_abspath(rel_from)
166
185
# *don't* call bzrlib.osutils.rename, because we want to
167
186
# detect errors on rename
168
os.rename(path_from, self.abspath(rel_to))
187
os.rename(path_from, self.local_abspath(rel_to))
169
188
except (IOError, OSError),e:
170
189
# TODO: What about path_to?
171
190
self._translate_error(e, path_from)
173
192
def move(self, rel_from, rel_to):
174
193
"""Move the item at rel_from to the location at rel_to"""
175
path_from = self.abspath(rel_from)
176
path_to = self.abspath(rel_to)
194
path_from = self.local_abspath(rel_from)
195
path_to = self.local_abspath(rel_to)
179
198
# this version will delete the destination if necessary
186
205
"""Delete the item at relpath"""
189
path = self.abspath(relpath)
208
path = self.local_abspath(relpath)
191
210
except (IOError, OSError),e:
192
211
# TODO: What about path_to?
206
225
for path in relpaths:
207
226
self._update_pb(pb, 'copy-to', count, total)
209
mypath = self.abspath(path)
210
otherpath = other.abspath(path)
228
mypath = self.local_abspath(path)
229
otherpath = other.local_abspath(path)
211
230
shutil.copy(mypath, otherpath)
212
231
if mode is not None:
213
232
os.chmod(otherpath, mode)
227
246
WARNING: many transports do not support this, so trying avoid using
228
247
it if at all possible.
230
path = self.abspath(relpath)
249
path = self.local_abspath(relpath)
232
return [urllib.quote(entry) for entry in os.listdir(path)]
251
return [urlutils.escape(entry) for entry in os.listdir(path)]
233
252
except (IOError, OSError), e:
234
253
self._translate_error(e, path)
241
path = self.abspath(relpath)
260
path = self.local_abspath(relpath)
242
261
return os.stat(path)
243
262
except (IOError, OSError),e:
244
263
self._translate_error(e, path)
250
269
from bzrlib.lock import ReadLock
253
path = self.abspath(relpath)
272
path = self.local_abspath(relpath)
254
273
return ReadLock(path)
255
274
except (IOError, OSError), e:
256
275
self._translate_error(e, path)
262
281
:return: A lock object, which should be passed to Transport.unlock()
264
283
from bzrlib.lock import WriteLock
265
return WriteLock(self.abspath(relpath))
284
return WriteLock(self.local_abspath(relpath))
267
286
def rmdir(self, relpath):
268
287
"""See Transport.rmdir."""
271
path = self.abspath(relpath)
290
path = self.local_abspath(relpath)
273
292
except (IOError, OSError),e:
274
293
self._translate_error(e, path)
320
339
def get_url(self):
321
340
"""See Transport.Server.get_url."""
322
# FIXME: \ to / on windows
323
return "file://%s" % os.path.abspath("")
341
return urlutils.local_path_to_url('')
326
344
def get_test_permutations():