Rev 4559: (mbp) workaround for ftp servers without APPE in file:///home/pqm/archives/thelove/bzr/%2Btrunk/

Canonical.com Patch Queue Manager pqm at pqm.ubuntu.com
Wed Jul 22 11:01:39 BST 2009


At file:///home/pqm/archives/thelove/bzr/%2Btrunk/

------------------------------------------------------------
revno: 4559 [merge]
revision-id: pqm at pqm.ubuntu.com-20090722100136-z7hpflqttygepstr
parent: pqm at pqm.ubuntu.com-20090722090335-m1okio1ev9bwytui
parent: mbp at sourcefrog.net-20090722075750-qrysvi0t3lk7ixhz
committer: Canonical.com Patch Queue Manager <pqm at pqm.ubuntu.com>
branch nick: +trunk
timestamp: Wed 2009-07-22 11:01:36 +0100
message:
  (mbp) workaround for ftp servers without APPE
modified:
  NEWS                           NEWS-20050323055033-4e00b5db738777ff
  bzrlib/transport/ftp/__init__.py ftp.py-20051116161804-58dc9506548c2a53
=== modified file 'NEWS'
--- a/NEWS	2009-07-22 06:00:45 +0000
+++ b/NEWS	2009-07-22 10:01:36 +0000
@@ -48,6 +48,10 @@
 * ``bzr revert .`` no longer generates an InconsistentDelta error when
   there are missing subtrees. (Robert Collins, #367632)
 
+* Cope with FTP servers that don't support restart/append by falling back
+  to reading and then rewriting the whole file, such as TahoeLAFS.  (This
+  fallback may be slow for some access patterns.)  (Nils Durner, #294709)
+
 * Fixed a NameError that occurs when merging or pulling from a URL that
   causes a redirection loop when bzr tries to read a URL as a bundle.
   (Andrew Bennetts, #400847)

=== modified file 'bzrlib/transport/ftp/__init__.py'
--- a/bzrlib/transport/ftp/__init__.py	2009-04-27 16:10:10 +0000
+++ b/bzrlib/transport/ftp/__init__.py	2009-07-22 06:51:13 +0000
@@ -99,6 +99,9 @@
             self.is_active = True
         else:
             self.is_active = False
+        
+        # Most modern FTP servers support the APPE command. If ours doesn't, we (re)set this flag accordingly later.
+        self._has_append = True
 
     def _get_FTP(self):
         """Return the ftplib.FTP instance for this object."""
@@ -387,6 +390,8 @@
         """Append the text in the file-like object into the final
         location.
         """
+        text = f.read()
+        
         abspath = self._remote_path(relpath)
         if self.has(relpath):
             ftp = self._get_FTP()
@@ -394,8 +399,11 @@
         else:
             result = 0
 
-        mutter("FTP appe to %s", abspath)
-        self._try_append(relpath, f.read(), mode)
+        if self._has_append:
+            mutter("FTP appe to %s", abspath)
+            self._try_append(relpath, text, mode)
+        else:
+            self._fallback_append(relpath, text, mode)
 
         return result
 
@@ -416,8 +424,16 @@
             self._setmode(relpath, mode)
             ftp.getresp()
         except ftplib.error_perm, e:
-            self._translate_perm_error(e, abspath, extra='error appending',
-                unknown_exc=errors.NoSuchFile)
+            # Check whether the command is not supported (reply code 502)
+            if str(e).startswith('502 '):
+                warning("FTP server does not support file appending natively. " \
+                    "Performance may be severely degraded! (%s)", e)
+                self._has_append = False
+                self._fallback_append(relpath, text, mode)
+            else:
+                self._translate_perm_error(e, abspath, extra='error appending',
+                    unknown_exc=errors.NoSuchFile)
+            
         except ftplib.error_temp, e:
             if retries > _number_of_retries:
                 raise errors.TransportError("FTP temporary error during APPEND %s." \
@@ -427,6 +443,13 @@
                 self._reconnect()
                 self._try_append(relpath, text, mode, retries+1)
 
+    def _fallback_append(self, relpath, text, mode = None):
+        remote = self.get(relpath)
+        remote.seek(0, 2)
+        remote.write(text)
+        remote.seek(0, 0)
+        return self.put_file(relpath, remote, mode)
+
     def _setmode(self, relpath, mode):
         """Set permissions on a path.
 




More information about the bazaar-commits mailing list