1
# Copyright (C) 2005, 2006 Canonical Ltd
1
# Copyright (C) 2005-2011 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, ST_SIZE, S_IMODE
23
from stat import ST_MODE, S_ISDIR, S_IMODE
26
26
from bzrlib.lazy_import import lazy_import
38
from bzrlib.trace import mutter
39
37
from bzrlib.transport import LateReadError
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):
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):
50
48
"""This is the transport agent for local filesystem access."""
52
50
def __init__(self, base):
99
97
- relative_reference is url escaped.
101
99
if relative_reference in ('.', ''):
102
return self._local_base
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]
103
104
return self._local_base + urlutils.unescape(relative_reference)
105
106
def abspath(self, relpath):
160
161
transport._file_streams[canonical_url].flush()
162
163
path = self._abspath(relpath)
163
return open(path, 'rb')
164
return osutils.open_file(path, 'rb')
164
165
except (IOError, OSError),e:
165
166
if e.errno == errno.EISDIR:
166
167
return LateReadError(relpath)
329
330
# initialise the file
330
331
self.put_bytes_non_atomic(relpath, "", mode=mode)
331
332
abspath = self._abspath(relpath)
332
handle = open(abspath, 'wb')
333
handle = osutils.open_file(abspath, 'wb')
333
334
if mode is not None:
334
335
self._check_mode_and_size(abspath, handle.fileno(), mode)
335
336
transport._file_streams[self.abspath(relpath)] = handle
400
401
def rename(self, rel_from, rel_to):
401
402
path_from = self._abspath(rel_from)
403
path_to = self._abspath(rel_to)
403
405
# *don't* call bzrlib.osutils.rename, because we want to
404
# detect errors on rename
405
os.rename(path_from, self._abspath(rel_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)
406
409
except (IOError, OSError),e:
407
410
# TODO: What about path_to?
408
411
self._translate_error(e, path_from)
515
518
except (IOError, OSError),e:
516
519
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)
518
548
def _can_roundtrip_unix_modebits(self):
519
549
if sys.platform == 'win32':
554
584
return EmulatedWin32LocalTransport(abspath)
557
class LocalURLServer(Server):
558
"""A pretend server for local transports, using file:// urls.
560
Of course no actual server is required to access the local filesystem, so
561
this just exists to tell the test code how to get to it.
565
"""Setup the server to service requests.
567
:param decorated_transport: ignored by this implementation.
571
"""See Transport.Server.get_url."""
572
return urlutils.local_path_to_url('')
575
587
def get_test_permutations():
576
588
"""Return the permutations to be used in testing."""
578
(LocalTransport, LocalURLServer),
589
from bzrlib.tests import test_server
590
return [(LocalTransport, test_server.LocalURLServer),]