summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTristan Maat <tristan.maat@codethink.co.uk>2019-12-10 17:52:36 +0000
committerJürg Billeter <j@bitron.ch>2019-12-17 14:18:11 +0100
commitb696254824e5cc6715924bf16ef6f7c5e0ec2e89 (patch)
treee9bb071d3456da32d47ba5754fc1c44a0848ff87
parent0118773753c571aec6c153d30f85c87e0d501d2c (diff)
downloadbuildstream-b696254824e5cc6715924bf16ef6f7c5e0ec2e89.tar.gz
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.
-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))