From 04aa5e0aeb451bf6b3399c704f1563d2803b1ecb Mon Sep 17 00:00:00 2001 From: Christian Kellner Date: Wed, 18 Mar 2020 14:47:39 +0100 Subject: [PATCH] objectstore: manually cleanup tree dir for Object The tree, which is created by stages and assemblers, might contain immutable files, which for Python 3 currently (version 3.8) leads to errors when the tempfile.TemporaryDirectory is being cleaned up. Therefore, manually cleanup the tree directory, if it exists, via shutil.rmtree with a custom onerror handler that also removes the immutable bit on permission errors. --- osbuild/objectstore.py | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/osbuild/objectstore.py b/osbuild/objectstore.py index 67f8c0f6..c82503a4 100644 --- a/osbuild/objectstore.py +++ b/osbuild/objectstore.py @@ -3,6 +3,7 @@ import contextlib import errno import hashlib import os +import shutil import subprocess import tempfile import weakref @@ -52,6 +53,35 @@ def umount(target, lazy=True): subprocess.run(["umount"] + args + [target], check=True) +def remove_tree(path): + def fixperms(p): + subprocess.run(["chattr", "-i", p], + check=False) + os.chmod(p, 0o777) + + def unlink(p): + try: + os.unlink(p) + except IsADirectoryError: + remove_tree(p) + except FileNotFoundError: + pass + + def on_error(_fn, p, exc_info): + e = exc_info[0] + if issubclass(e, FileNotFoundError): + pass + elif issubclass(e, PermissionError): + if p != path: + fixperms(os.path.dirname(p)) + fixperms(p) + unlink(p) + else: + raise e + + shutil.rmtree(path, onerror=on_error) + + # pylint: disable=too-many-instance-attributes class Object: def __init__(self, store: "ObjectStore"): @@ -158,6 +188,12 @@ class Object: def cleanup(self): self._check_readers() self._check_writer() + if self._tree: + # manually remove the tree, it might contain + # files with immutable flag set, which will + # throw off standard Python 3 tempdir cleanup + remove_tree(self._tree) + self._tree = None if self._workdir: self._workdir.cleanup() self._workdir = None