Rev 5081: (mbp, for rls) add Transport readlink, symlink, hardlink in file:///home/pqm/archives/thelove/bzr/%2Btrunk/
Canonical.com Patch Queue Manager
pqm at pqm.ubuntu.com
Thu Mar 11 05:02:33 GMT 2010
At file:///home/pqm/archives/thelove/bzr/%2Btrunk/
------------------------------------------------------------
revno: 5081 [merge]
revision-id: pqm at pqm.ubuntu.com-20100311050232-4n3s5jbvlb1w3dy7
parent: pqm at pqm.ubuntu.com-20100310063827-8flct2zz07y0oywf
parent: mbp at canonical.com-20100311041833-kh1kwk29cp6sbmcs
committer: Canonical.com Patch Queue Manager <pqm at pqm.ubuntu.com>
branch nick: +trunk
timestamp: Thu 2010-03-11 05:02:32 +0000
message:
(mbp, for rls) add Transport readlink, symlink, hardlink
modified:
NEWS NEWS-20050323055033-4e00b5db738777ff
bzrlib/tests/per_transport.py test_transport_implementations.py-20051227111451-f97c5c7d5c49fce7
bzrlib/transport/__init__.py transport.py-20050711165921-4978aa7ce1285ad5
bzrlib/transport/local.py local_transport.py-20050711165921-9b1f142bfe480c24
bzrlib/transport/sftp.py sftp.py-20051019050329-ab48ce71b7e32dfe
=== modified file 'NEWS'
--- a/NEWS 2010-03-10 06:38:27 +0000
+++ b/NEWS 2010-03-11 04:18:33 +0000
@@ -8,7 +8,6 @@
bzr 2.2.0b1
###########
-:Codename: ???
:2.2.0b1: Not released yet
Compatibility Breaks
@@ -124,6 +123,9 @@
* New method ``BzrDir.list_branches()`` that returns a sequence of branches
present in a control directory. (Jelmer Vernooij)
+* New transport methods ``readlink``, ``symlink`` and ``hardlink``.
+ (Neil Santos)
+
* Remove unused ``CommandFailed`` exception.
(Martin Pool)
=== modified file 'bzrlib/tests/per_transport.py'
--- a/bzrlib/tests/per_transport.py 2010-02-23 07:43:11 +0000
+++ b/bzrlib/tests/per_transport.py 2010-03-05 05:30:19 +0000
@@ -1083,6 +1083,52 @@
subdir.stat('./file')
subdir.stat('.')
+ def test_hardlink(self):
+ from stat import ST_NLINK
+
+ t = self.get_transport()
+
+ source_name = "original_target"
+ link_name = "target_link"
+
+ self.build_tree([source_name], transport=t)
+
+ try:
+ t.hardlink(source_name, link_name)
+
+ self.failUnless(t.has(source_name))
+ self.failUnless(t.has(link_name))
+
+ st = t.stat(link_name)
+ self.failUnlessEqual(st[ST_NLINK], 2)
+ except TransportNotPossible:
+ raise TestSkipped("Transport %s does not support hardlinks." %
+ self._server.__class__)
+
+ def test_symlink(self):
+ from stat import S_ISLNK
+
+ t = self.get_transport()
+
+ source_name = "original_target"
+ link_name = "target_link"
+
+ self.build_tree([source_name], transport=t)
+
+ try:
+ t.symlink(source_name, link_name)
+
+ self.failUnless(t.has(source_name))
+ self.failUnless(t.has(link_name))
+
+ st = t.stat(link_name)
+ self.failUnless(S_ISLNK(st.st_mode))
+ except TransportNotPossible:
+ raise TestSkipped("Transport %s does not support symlinks." %
+ self._server.__class__)
+ except IOError:
+ raise tests.KnownFailure("Paramiko fails to create symlinks during tests")
+
def test_list_dir(self):
# TODO: Test list_dir, just try once, and if it throws, stop testing
t = self.get_transport()
=== modified file 'bzrlib/transport/__init__.py'
--- a/bzrlib/transport/__init__.py 2010-02-23 07:43:11 +0000
+++ b/bzrlib/transport/__init__.py 2010-03-05 05:30:19 +0000
@@ -1202,6 +1202,18 @@
count = self._iterate_over(relpaths, gather, pb, 'stat', expand=False)
return stats
+ def readlink(self, relpath):
+ """Return a string representing the path to which the symbolic link points."""
+ raise errors.TransportNotPossible("Dereferencing symlinks is not supported on %s" % self)
+
+ def hardlink(self, source, link_name):
+ """Create a hardlink pointing to source named link_name."""
+ raise errors.TransportNotPossible("Hard links are not supported on %s" % self)
+
+ def symlink(self, source, link_name):
+ """Create a symlink pointing to source named link_name."""
+ raise errors.TransportNotPossible("Symlinks are not supported on %s" % self)
+
def listable(self):
"""Return True if this store supports listing."""
raise NotImplementedError(self.listable)
@@ -1831,6 +1843,6 @@
transport_server_registry = registry.Registry()
-transport_server_registry.register_lazy('bzr', 'bzrlib.smart.server',
+transport_server_registry.register_lazy('bzr', 'bzrlib.smart.server',
'serve_bzr', help="The Bazaar smart server protocol over TCP. (default port: 4155)")
transport_server_registry.default_key = 'bzr'
=== modified file 'bzrlib/transport/local.py'
--- a/bzrlib/transport/local.py 2010-03-05 08:55:12 +0000
+++ b/bzrlib/transport/local.py 2010-03-11 04:18:33 +0000
@@ -481,7 +481,7 @@
path = relpath
try:
path = self._abspath(relpath)
- return os.stat(path)
+ return os.lstat(path)
except (IOError, OSError),e:
self._translate_error(e, path)
@@ -515,6 +515,33 @@
except (IOError, OSError),e:
self._translate_error(e, path)
+ if osutils.host_os_dereferences_symlinks():
+ def readlink(self, relpath):
+ """See Transport.readlink."""
+ return osutils.readlink(self._abspath(relpath))
+
+ if osutils.hardlinks_good():
+ def hardlink(self, source, link_name):
+ """See Transport.link."""
+ try:
+ os.link(self._abspath(source), self._abspath(link_name))
+ except (IOError, OSError), e:
+ self._translate_error(e, source)
+
+ if osutils.has_symlinks():
+ def symlink(self, source, link_name):
+ """See Transport.symlink."""
+ abs_link_dirpath = urlutils.dirname(self.abspath(link_name))
+ source_rel = urlutils.file_relpath(
+ urlutils.strip_trailing_slash(abs_link_dirpath),
+ urlutils.strip_trailing_slash(self.abspath(source))
+ )
+
+ try:
+ os.symlink(source_rel, self._abspath(link_name))
+ except (IOError, OSError), e:
+ self._translate_error(e, source_rel)
+
def _can_roundtrip_unix_modebits(self):
if sys.platform == 'win32':
# anyone else?
=== modified file 'bzrlib/transport/sftp.py'
--- a/bzrlib/transport/sftp.py 2010-02-23 07:43:11 +0000
+++ b/bzrlib/transport/sftp.py 2010-03-04 02:43:41 +0000
@@ -82,7 +82,7 @@
else:
from paramiko.sftp import (SFTP_FLAG_WRITE, SFTP_FLAG_CREATE,
SFTP_FLAG_EXCL, SFTP_FLAG_TRUNC,
- CMD_HANDLE, CMD_OPEN)
+ SFTP_OK, CMD_HANDLE, CMD_OPEN)
from paramiko.sftp_attr import SFTPAttributes
from paramiko.sftp_file import SFTPFile
@@ -810,10 +810,32 @@
"""Return the stat information for a file."""
path = self._remote_path(relpath)
try:
- return self._get_sftp().stat(path)
+ return self._get_sftp().lstat(path)
except (IOError, paramiko.SSHException), e:
self._translate_io_exception(e, path, ': unable to stat')
+ def readlink(self, relpath):
+ """See Transport.readlink."""
+ path = self._remote_path(relpath)
+ try:
+ return self._get_sftp().readlink(path)
+ except (IOError, paramiko.SSHException), e:
+ self._translate_io_exception(e, path, ': unable to readlink')
+
+ def symlink(self, source, link_name):
+ """See Transport.symlink."""
+ try:
+ conn = self._get_sftp()
+ sftp_retval = conn.symlink(source, link_name)
+ if SFTP_OK != sftp_retval:
+ raise TransportError(
+ '%r: unable to create symlink to %r' % (link_name, source),
+ sftp_retval
+ )
+ except (IOError, paramiko.SSHException), e:
+ self._translate_io_exception(e, link_name,
+ ': unable to create symlink to %r' % (source))
+
def lock_read(self, relpath):
"""
Lock the given file for shared (read) access.
More information about the bazaar-commits
mailing list