[PATCH] knit pushing with ftp transport

Alexandre Saint stalst at gmail.com
Sun Apr 30 16:48:13 BST 2006


Hello,

This patch adds support for knit format to the ftp transport.

Added an append() method using FTP 'APPE' command.
Modified copy() to deal well with relative paths (and not only with
absolute ones).

Regards.
-- 
alex
-------------- next part --------------
=== modified file 'a/bzrlib/transport/ftp.py'
--- a/bzrlib/transport/ftp.py	
+++ b/bzrlib/transport/ftp.py	
@@ -303,11 +303,56 @@
                 raise TransportError(msg="Cannot remove directory at %s" % \
                         self._abspath(rel_path), extra=str(e))
 
-    def append(self, relpath, f):
+    def append(self, relpath, f, mode=None, retries=0):
         """Append the text in the file-like object into the final
         location.
         """
-        raise TransportNotPossible('ftp does not support append()')
+        offset = f.tell()
+        try:
+            abspath = self._abspath(relpath)
+            mutter("FTP appe to %s" % abspath)
+            ftp = self._get_FTP()
+            if self.has(relpath):
+                result = ftp.size(abspath)
+            else:
+                result = 0
+            ftp.voidcmd("TYPE I")
+            cmd = "APPE %s" % abspath
+            conn = ftp.transfercmd(cmd)
+            conn.sendall(f.read())
+            conn.close()
+            if mode is not None:
+                self._setmode(relpath, mode)
+            ftp.getresp()
+            return result
+        except ftplib.error_perm, e:
+            FtpTransportError("Error appending data to %s" % abspath,
+                    orig_error=e)
+        except ftplib.error_temp, e:
+            if retries > _number_of_retries:
+                raise TransportError("FTP temporary error during APPEND %s." \
+                        "Aborting." % self.abspath(relpath), orig_error=e)
+            else:
+                warning("FTP temporary error: %s. Retrying." % str(e))
+                self._FTP_instance = None
+                # Make sure the file is at the same position it was given.
+                f.seek(offset)
+                self.append(relpath, f, retries=retries+1)
+
+    def _setmode(self, relpath, mode):
+        """Set permissions on a path.
+
+        Only set permissions if the FTP server support the 'SITE CHMOD'
+        extension.
+        """
+        try:
+            ftp = self._get_FTP()
+            cmd = "SITE CHMOD %s %s" % (self._abspath(relpath), str(mode))
+            ftp.sendcmd(cmd)
+        except ftplib.error_perm, e:
+            # Command probably not available on this server
+            pass
+
 
     def copy(self, rel_from, rel_to):
         """Copy the item at rel_from to the location at rel_to"""
@@ -347,11 +392,12 @@
             mutter("FTP nlst: %s" % self._abspath(relpath))
             f = self._get_FTP()
             basepath = self._abspath(relpath)
-            # FTP.nlst returns paths prefixed by relpath, strip 'em
-            the_list = f.nlst(basepath)
-            stripped = [path[len(basepath)+1:] for path in the_list]
+            paths = f.nlst(basepath)
+            # If FTP.nlst returns paths prefixed by relpath, strip 'em
+            if paths[0].startswith(basepath):
+                paths = [path[len(basepath)+1:] for path in paths]
             # Remove . and .. if present, and return
-            return [path for path in stripped if path not in (".", "..")]
+            return [path for path in paths if path not in (".", "..")]
         except ftplib.error_perm, e:
             raise TransportError(orig_error=e)
 

-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 191 bytes
Desc: not available
Url : https://lists.ubuntu.com/archives/bazaar/attachments/20060430/e9bc7d98/attachment.pgp 


More information about the bazaar mailing list