summaryrefslogtreecommitdiff
path: root/src/buildstream/utils.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/buildstream/utils.py')
-rw-r--r--src/buildstream/utils.py27
1 files changed, 16 insertions, 11 deletions
diff --git a/src/buildstream/utils.py b/src/buildstream/utils.py
index b6716a29d..545816e89 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))