1
# Copyright (C) 2005-2011 Canonical Ltd
1
# Copyright (C) 2005, 2006 Canonical Ltd
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
23
from stat import ST_MODE, S_ISDIR, S_IMODE
23
from stat import ST_MODE, S_ISDIR, ST_SIZE, S_IMODE
26
26
from bzrlib.lazy_import import lazy_import
38
from bzrlib.trace import mutter
37
39
from bzrlib.transport import LateReadError
40
from bzrlib import transport
43
_append_flags = os.O_CREAT | os.O_APPEND | os.O_WRONLY | osutils.O_BINARY | osutils.O_NOINHERIT
44
_put_non_atomic_flags = os.O_CREAT | os.O_TRUNC | os.O_WRONLY | osutils.O_BINARY | osutils.O_NOINHERIT
47
class LocalTransport(transport.Transport):
42
from bzrlib.transport import Transport, Server
45
_append_flags = os.O_CREAT | os.O_APPEND | os.O_WRONLY | osutils.O_BINARY
46
_put_non_atomic_flags = os.O_CREAT | os.O_TRUNC | os.O_WRONLY | osutils.O_BINARY
49
class LocalTransport(Transport):
48
50
"""This is the transport agent for local filesystem access."""
50
52
def __init__(self, base):
97
99
- relative_reference is url escaped.
99
101
if relative_reference in ('.', ''):
100
# _local_base normally has a trailing slash; strip it so that stat
101
# on a transport pointing to a symlink reads the link not the
102
# referent but be careful of / and c:\
103
return osutils.split(self._local_base)[0]
102
return self._local_base
104
103
return self._local_base + urlutils.unescape(relative_reference)
106
105
def abspath(self, relpath):
161
160
transport._file_streams[canonical_url].flush()
163
162
path = self._abspath(relpath)
164
return osutils.open_file(path, 'rb')
163
return open(path, 'rb')
165
164
except (IOError, OSError),e:
166
165
if e.errno == errno.EISDIR:
167
166
return LateReadError(relpath)
287
285
def put_bytes_non_atomic(self, relpath, bytes, mode=None,
288
286
create_parent_dir=False, dir_mode=None):
292
289
self._put_non_atomic_helper(relpath, writer, mode=mode,
293
290
create_parent_dir=create_parent_dir,
294
291
dir_mode=dir_mode)
330
327
# initialise the file
331
328
self.put_bytes_non_atomic(relpath, "", mode=mode)
332
329
abspath = self._abspath(relpath)
333
handle = osutils.open_file(abspath, 'wb')
330
handle = open(abspath, 'wb')
334
331
if mode is not None:
335
332
self._check_mode_and_size(abspath, handle.fileno(), mode)
336
333
transport._file_streams[self.abspath(relpath)] = handle
401
397
def rename(self, rel_from, rel_to):
402
398
path_from = self._abspath(rel_from)
403
path_to = self._abspath(rel_to)
405
400
# *don't* call bzrlib.osutils.rename, because we want to
406
# detect conflicting names on rename, and osutils.rename tries to
407
# mask cross-platform differences there
408
os.rename(path_from, path_to)
401
# detect errors on rename
402
os.rename(path_from, self._abspath(rel_to))
409
403
except (IOError, OSError),e:
410
404
# TODO: What about path_to?
411
405
self._translate_error(e, path_from)
518
512
except (IOError, OSError),e:
519
513
self._translate_error(e, path)
521
if osutils.host_os_dereferences_symlinks():
522
def readlink(self, relpath):
523
"""See Transport.readlink."""
524
return osutils.readlink(self._abspath(relpath))
526
if osutils.hardlinks_good():
527
def hardlink(self, source, link_name):
528
"""See Transport.link."""
530
os.link(self._abspath(source), self._abspath(link_name))
531
except (IOError, OSError), e:
532
self._translate_error(e, source)
534
if osutils.has_symlinks():
535
def symlink(self, source, link_name):
536
"""See Transport.symlink."""
537
abs_link_dirpath = urlutils.dirname(self.abspath(link_name))
538
source_rel = urlutils.file_relpath(
539
urlutils.strip_trailing_slash(abs_link_dirpath),
540
urlutils.strip_trailing_slash(self.abspath(source))
544
os.symlink(source_rel, self._abspath(link_name))
545
except (IOError, OSError), e:
546
self._translate_error(e, source_rel)
548
515
def _can_roundtrip_unix_modebits(self):
549
516
if sys.platform == 'win32':
584
551
return EmulatedWin32LocalTransport(abspath)
554
class LocalURLServer(Server):
555
"""A pretend server for local transports, using file:// urls.
557
Of course no actual server is required to access the local filesystem, so
558
this just exists to tell the test code how to get to it.
562
"""Setup the server to service requests.
564
:param decorated_transport: ignored by this implementation.
568
"""See Transport.Server.get_url."""
569
return urlutils.local_path_to_url('')
587
572
def get_test_permutations():
588
573
"""Return the permutations to be used in testing."""
589
from bzrlib.tests import test_server
590
return [(LocalTransport, test_server.LocalURLServer),]
575
(LocalTransport, LocalURLServer),