Patchwork [2,of,7,VFS] vfs: add rmtree

login
register
mail settings
Submitter Katsunori FUJIWARA
Date April 10, 2015, 3:54 p.m.
Message ID <80c7f6d4d6d42a58967e.1428681264@juju>
Download mbox | patch
Permalink /patch/8595/
State Accepted
Commit ca3a90096c9538493f2780ba06c895762113631f
Headers show

Comments

Katsunori FUJIWARA - April 10, 2015, 3:54 p.m.
# HG changeset patch
# User FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
# Date 1428680829 -32400
#      Sat Apr 11 00:47:09 2015 +0900
# Node ID 80c7f6d4d6d42a58967ee299b2a4ca89439907cb
# Parent  17c9d35176133223e44820d39b30146d06048b1f
vfs: add rmtree

This duplicates "onerror()" function from "svnsubrepo.remove()" for
equivalence of replacing in subsequent patch.

This "onerror()" function for "shutil.rmtree()" was introduced by
92b0d669637f, which avoids failure of removing svn repository on
Windows.

Patch

diff --git a/mercurial/scmutil.py b/mercurial/scmutil.py
--- a/mercurial/scmutil.py
+++ b/mercurial/scmutil.py
@@ -10,7 +10,7 @@  from mercurial.node import nullrev
 import util, error, osutil, revset, similar, encoding, phases
 import pathutil
 import match as matchmod
-import os, errno, re, glob, tempfile
+import os, errno, re, glob, tempfile, shutil, stat
 
 if os.name == 'nt':
     import scmwindows as scmplatform
@@ -316,6 +316,26 @@  class abstractvfs(object):
     def readlink(self, path):
         return os.readlink(self.join(path))
 
+    def rmtree(self, path=None, ignore_errors=False, forcibly=False):
+        """Remove a directory tree recursively
+
+        If ``forcibly``, this tries to remove READ-ONLY files, too.
+        """
+        if forcibly:
+            def onerror(function, path, excinfo):
+                if function is not os.remove:
+                    raise
+                # read-only files cannot be unlinked under Windows
+                s = os.stat(path)
+                if (s.st_mode & stat.S_IWRITE) != 0:
+                    raise
+                os.chmod(path, stat.S_IMODE(s.st_mode) | stat.S_IWRITE)
+                os.remove(path)
+        else:
+            onerror = None
+        return shutil.rmtree(self.join(path),
+                             ignore_errors=ignore_errors, onerror=onerror)
+
     def setflags(self, path, l, x):
         return util.setflags(self.join(path), l, x)