Rev 4491: (mbp) force deletion of readonly files from TreeTransform in file:///home/pqm/archives/thelove/bzr/%2Btrunk/

Canonical.com Patch Queue Manager pqm at pqm.ubuntu.com
Tue Jun 30 06:12:29 BST 2009


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

------------------------------------------------------------
revno: 4491 [merge]
revision-id: pqm at pqm.ubuntu.com-20090630051227-ncar0w60u6cbyydk
parent: pqm at pqm.ubuntu.com-20090629163313-qaehowmd2u5mxlvw
parent: mbp at sourcefrog.net-20090630041319-luqqrjw1nn59chft
committer: Canonical.com Patch Queue Manager <pqm at pqm.ubuntu.com>
branch nick: +trunk
timestamp: Tue 2009-06-30 06:12:27 +0100
message:
  (mbp) force deletion of readonly files from TreeTransform
modified:
  NEWS                           NEWS-20050323055033-4e00b5db738777ff
  bzrlib/osutils.py              osutils.py-20050309040759-eeaff12fbf77ac86
  bzrlib/tests/test_osutils.py   test_osutils.py-20051201224856-e48ee24c12182989
  bzrlib/transform.py            transform.py-20060105172343-dd99e54394d91687
=== modified file 'NEWS'
--- a/NEWS	2009-06-29 15:10:47 +0000
+++ b/NEWS	2009-06-30 04:13:19 +0000
@@ -53,6 +53,10 @@
 * Fetch between repositories does not error if they have inconsistent data
   that should be irrelevant to the fetch operation. (Aaron Bentley)
 
+* Force deletion of readonly files during merge, update and other tree
+  transforms.
+  (Craig Hewetson, Martin Pool, #218206)
+
 * Progress bars are now suppressed again when the environment variable
   ``BZR_PROGRESS_BAR`` is set to ``none``.
   (Martin Pool, #339385)

=== modified file 'bzrlib/osutils.py'
--- a/bzrlib/osutils.py	2009-06-10 06:25:56 +0000
+++ b/bzrlib/osutils.py	2009-06-30 04:08:12 +0000
@@ -927,13 +927,31 @@
         shutil.copyfile(src, dest)
 
 
-# Look Before You Leap (LBYL) is appropriate here instead of Easier to Ask for
-# Forgiveness than Permission (EAFP) because:
-# - root can damage a solaris file system by using unlink,
-# - unlink raises different exceptions on different OSes (linux: EISDIR, win32:
-#   EACCES, OSX: EPERM) when invoked on a directory.
 def delete_any(path):
-    """Delete a file or directory."""
+    """Delete a file, symlink or directory.  
+    
+    Will delete even if readonly.
+    """
+    try:
+       _delete_file_or_dir(path)
+    except (OSError, IOError), e:
+        if e.errno in (errno.EPERM, errno.EACCES):
+            # make writable and try again
+            try:
+                make_writable(path)
+            except (OSError, IOError):
+                pass
+            _delete_file_or_dir(path)
+        else:
+            raise
+
+
+def _delete_file_or_dir(path):
+    # Look Before You Leap (LBYL) is appropriate here instead of Easier to Ask for
+    # Forgiveness than Permission (EAFP) because:
+    # - root can damage a solaris file system by using unlink,
+    # - unlink raises different exceptions on different OSes (linux: EISDIR, win32:
+    #   EACCES, OSX: EPERM) when invoked on a directory.
     if isdir(path): # Takes care of symlinks
         os.rmdir(path)
     else:

=== modified file 'bzrlib/tests/test_osutils.py'
--- a/bzrlib/tests/test_osutils.py	2009-06-10 03:56:49 +0000
+++ b/bzrlib/tests/test_osutils.py	2009-06-30 04:13:19 +0000
@@ -240,6 +240,18 @@
         self.failIfExists('dir')
 
 
+class TestDeleteAny(tests.TestCaseInTempDir):
+
+    def test_delete_any_readonly(self):
+        # from <https://bugs.launchpad.net/bzr/+bug/218206>
+        self.build_tree(['d/', 'f'])
+        osutils.make_readonly('d')
+        osutils.make_readonly('f')
+
+        osutils.delete_any('f')
+        osutils.delete_any('d')
+
+
 class TestKind(tests.TestCaseInTempDir):
 
     def test_file_kind(self):

=== modified file 'bzrlib/transform.py'
--- a/bzrlib/transform.py	2009-06-17 03:41:33 +0000
+++ b/bzrlib/transform.py	2009-06-30 04:08:12 +0000
@@ -995,18 +995,15 @@
                        self._new_contents.iteritems()]
             entries.sort(reverse=True)
             for path, trans_id, kind in entries:
-                if kind == "directory":
-                    os.rmdir(path)
-                else:
-                    os.unlink(path)
+                delete_any(path)
             try:
-                os.rmdir(self._limbodir)
+                delete_any(self._limbodir)
             except OSError:
                 # We don't especially care *why* the dir is immortal.
                 raise ImmortalLimbo(self._limbodir)
             try:
                 if self._deletiondir is not None:
-                    os.rmdir(self._deletiondir)
+                    delete_any(self._deletiondir)
             except OSError:
                 raise errors.ImmortalPendingDeletion(self._deletiondir)
         finally:




More information about the bazaar-commits mailing list