Rev 2423: Fix ftp transport with servers that don't support atomic rename in file:///home/pqm/archives/thelove/bzr/%2Btrunk/

Canonical.com Patch Queue Manager pqm at pqm.ubuntu.com
Tue Apr 17 01:59:32 BST 2007


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

------------------------------------------------------------
revno: 2423
revision-id: pqm at pqm.ubuntu.com-20070417005930-rofskshyjsfzrahh
parent: pqm at pqm.ubuntu.com-20070416210546-4ib7pt7wkkk71zzj
parent: abentley at panoramicfeedback.com-20070416211229-xa9pdlxs721oxhyx
committer: Canonical.com Patch Queue Manager<pqm at pqm.ubuntu.com>
branch nick: +trunk
timestamp: Tue 2007-04-17 01:59:30 +0100
message:
  Fix ftp transport with servers that don't support atomic rename
modified:
  NEWS                           NEWS-20050323055033-4e00b5db738777ff
  bzrlib/transport/ftp.py        ftp.py-20051116161804-58dc9506548c2a53
    ------------------------------------------------------------
    revno: 1551.2.49.1.40.1.22.1.42.1.31.1.39.1.17.1.4
    merged: abentley at panoramicfeedback.com-20070416211229-xa9pdlxs721oxhyx
    parent: abentley at panoramicfeedback.com-20070416210345-8btya3q24r5488md
    committer: Aaron Bentley <abentley at panoramicfeedback.com>
    branch nick: Aaron's mergeable stuff
    timestamp: Mon 2007-04-16 17:12:29 -0400
    message:
      Revert now-unnecessary changes
    ------------------------------------------------------------
    revno: 1551.2.49.1.40.1.22.1.42.1.31.1.39.1.17.1.3
    merged: abentley at panoramicfeedback.com-20070416210345-8btya3q24r5488md
    parent: abentley at panoramicfeedback.com-20070416153810-llz9qggakjio05ku
    committer: Aaron Bentley <abentley at panoramicfeedback.com>
    branch nick: Aaron's mergeable stuff
    timestamp: Mon 2007-04-16 17:03:45 -0400
    message:
      Separate FtpTransport.rename from FtpTransport.move
    ------------------------------------------------------------
    revno: 1551.2.49.1.40.1.22.1.42.1.31.1.39.1.17.1.2
    merged: abentley at panoramicfeedback.com-20070416153810-llz9qggakjio05ku
    parent: abentley at panoramicfeedback.com-20070416125430-a4qpwmrsz7h2hw39
    committer: Aaron Bentley <abentley at panoramicfeedback.com>
    branch nick: Aaron's mergeable stuff
    timestamp: Mon 2007-04-16 11:38:10 -0400
    message:
      FTP does not require atomic rename. Fixes #89436
    ------------------------------------------------------------
    revno: 1551.2.49.1.40.1.22.1.42.1.31.1.39.1.17.1.1
    merged: abentley at panoramicfeedback.com-20070416125430-a4qpwmrsz7h2hw39
    parent: abentley at panoramicfeedback.com-20070410210517-0m7mhl5d2fhs66u5
    parent: pqm at pqm.ubuntu.com-20070413050623-10v4wozs1tu04kcu
    committer: Aaron Bentley <abentley at panoramicfeedback.com>
    branch nick: Aaron's mergeable stuff
    timestamp: Mon 2007-04-16 08:54:30 -0400
    message:
      merge bzr.dev
=== modified file 'NEWS'
--- a/NEWS	2007-04-13 15:37:58 +0000
+++ b/NEWS	2007-04-17 00:59:30 +0000
@@ -77,6 +77,9 @@
       in this versus base, but it isn't marked as a rename).
       (John Arbash Meinel, #103870)
 
+    * FTP now works even when the FTP server does not support atomic rename.
+      (Aaron Bentley, #89436)
+
   TESTING:
 
     * Added ``bzrlib.strace.strace`` which will strace a single callable and

=== modified file 'bzrlib/transport/ftp.py'
--- a/bzrlib/transport/ftp.py	2007-04-13 16:02:37 +0000
+++ b/bzrlib/transport/ftp.py	2007-04-17 00:59:30 +0000
@@ -29,6 +29,7 @@
 import errno
 import ftplib
 import os
+import os.path
 import urllib
 import urlparse
 import select
@@ -40,6 +41,7 @@
 
 from bzrlib import (
     errors,
+    osutils,
     urlutils,
     )
 from bzrlib.trace import mutter, warning
@@ -303,7 +305,8 @@
         :param retries: Number of retries after temporary failures so far
                         for this operation.
 
-        TODO: jam 20051215 ftp as a protocol seems to support chmod, but ftplib does not
+        TODO: jam 20051215 ftp as a protocol seems to support chmod, but
+        ftplib does not
         """
         abspath = self._abspath(relpath)
         tmp_abspath = '%s.tmp.%.9f.%d.%d' % (abspath, time.time(),
@@ -315,7 +318,7 @@
             f = self._get_FTP()
             try:
                 f.storbinary('STOR '+tmp_abspath, fp)
-                f.rename(tmp_abspath, abspath)
+                self._rename_and_overwrite(tmp_abspath, abspath, f)
             except (ftplib.error_temp,EOFError), e:
                 warning("Failure during ftp PUT. Deleting temporary file.")
                 try:
@@ -434,6 +437,20 @@
     #       to give it its own address as the 'to' location.
     #       So implement a fancier 'copy()'
 
+    def rename(self, rel_from, rel_to):
+        abs_from = self._abspath(rel_from)
+        abs_to = self._abspath(rel_to)
+        mutter("FTP rename: %s => %s", abs_from, abs_to)
+        f = self._get_FTP()
+        return self._rename(abs_from, abs_to, f)
+
+    def _rename(self, abs_from, abs_to, f):
+        try:
+            f.rename(abs_from, abs_to)
+        except ftplib.error_perm, e:
+            self._translate_perm_error(e, abs_from,
+                ': unable to rename to %r' % (abs_to))
+
     def move(self, rel_from, rel_to):
         """Move the item at rel_from to the location at rel_to"""
         abs_from = self._abspath(rel_from)
@@ -441,20 +458,30 @@
         try:
             mutter("FTP mv: %s => %s", abs_from, abs_to)
             f = self._get_FTP()
-            f.rename(abs_from, abs_to)
+            self._rename_and_overwrite(abs_from, abs_to, f)
         except ftplib.error_perm, e:
             self._translate_perm_error(e, abs_from,
                 extra='unable to rename to %r' % (rel_to,), 
                 unknown_exc=errors.PathError)
 
-    rename = move
+    def _rename_and_overwrite(self, abs_from, abs_to, f):
+        """Do a fancy rename on the remote server.
+
+        Using the implementation provided by osutils.
+        """
+        osutils.fancy_rename(abs_from, abs_to,
+            rename_func=lambda p1, p2: self._rename(p1, p2, f),
+            unlink_func=lambda p: self._delete(p, f))
 
     def delete(self, relpath):
         """Delete the item at relpath"""
         abspath = self._abspath(relpath)
+        f = self._get_FTP()
+        self._delete(abspath, f)
+
+    def _delete(self, abspath, f):
         try:
             mutter("FTP rm: %s", abspath)
-            f = self._get_FTP()
             f.delete(abspath)
         except ftplib.error_perm, e:
             self._translate_perm_error(e, abspath, 'error deleting',
@@ -666,6 +693,9 @@
             pfrom = self.filesystem.translate(self._renaming)
             self._renaming = None
             pto = self.filesystem.translate(line[1])
+            if os.path.exists(pto):
+                self.respond('550 RNTO failed: file exists')
+                return
             try:
                 os.rename(pfrom, pto)
             except (IOError, OSError), e:




More information about the bazaar-commits mailing list