You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@buildstream.apache.org by tv...@apache.org on 2021/02/04 07:28:01 UTC

[buildstream] 10/10: utils.py: Use `onerror` in `_force_rmtree`

This is an automated email from the ASF dual-hosted git repository.

tvb pushed a commit to branch tlater/buildbox-run-userchroot
in repository https://gitbox.apache.org/repos/asf/buildstream.git

commit c4facc4b8bf46803df6866ebedfe296dc07373d1
Author: Tristan Maat <tr...@codethink.co.uk>
AuthorDate: Tue Dec 10 17:52:36 2019 +0000

    utils.py: Use `onerror` in `_force_rmtree`
    
    If we don't, and encounter a file we don't own, but have permission to
    delete, we'll fail with EPERM, since we won't be able to change
    permissions but will be able to delete it.
    
    Instead, we now try to change permissions and remove a file *after* we
    realize we couldn't at first.
---
 src/buildstream/utils.py | 27 ++++++++++++++++-----------
 1 file changed, 16 insertions(+), 11 deletions(-)

diff --git a/src/buildstream/utils.py b/src/buildstream/utils.py
index b6716a2..545816e 100644
--- a/src/buildstream/utils.py
+++ b/src/buildstream/utils.py
@@ -819,20 +819,25 @@ def _remove_path_with_parents(basedir: Union[Path, str], path: Union[Path, str])
 
 # Recursively remove directories, ignoring file permissions as much as
 # possible.
-def _force_rmtree(rootpath, **kwargs):
+def _force_rmtree(rootpath):
+    def fix_permissions(function, path, info):
+        parent = os.path.dirname(path)
 
-    os.chmod(rootpath, 0o755)
-    for root, dirs, _ in os.walk(rootpath):
-        for d in dirs:
-            path = os.path.join(root, d.lstrip("/"))
-            if os.path.exists(path) and not os.path.islink(path):
-                try:
-                    os.chmod(path, 0o755)
-                except OSError as e:
-                    raise UtilError("Failed to ensure write permission on file '{}': {}".format(path, e))
+        try:
+            os.chmod(parent, 0o755)
+        except OSError as e:
+            raise UtilError("Failed to ensure write permission on directory '{}': {}".format(parent, e))
+
+        # Directories need to be removed with `rmdir`, though
+        # `os.path.isdir` will follow symlinks, so make sure it's
+        # not a symlink first
+        if not os.path.islink(path) and os.path.isdir(path):
+            os.rmdir(path)
+        else:
+            os.remove(path)
 
     try:
-        shutil.rmtree(rootpath, **kwargs)
+        shutil.rmtree(rootpath, onerror=fix_permissions)
     except OSError as e:
         raise UtilError("Failed to remove cache directory '{}': {}".format(rootpath, e))