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