Add a variant of TemporaryDirectory that uses windows_proof_rmtree()

Adds TemporaryDirectoryWinProof which calls windows_proof_rmtree() on
error.

Use instead of hacky error handling (which might shadow other OSError)
in Compiler.compile().
This commit is contained in:
Christoph Reiter 2020-11-20 15:30:37 +01:00 committed by Dylan Baker
parent 1db800bf67
commit abc7e6af01
2 changed files with 66 additions and 51 deletions

View File

@ -13,7 +13,7 @@
# limitations under the License.
import abc
import contextlib, os.path, re, tempfile
import contextlib, os.path, re
import enum
import itertools
import typing as T
@ -25,7 +25,7 @@ from .. import mesonlib
from ..linkers import LinkerEnvVarsMixin
from ..mesonlib import (
EnvironmentException, MachineChoice, MesonException,
Popen_safe, split_args, LibType
Popen_safe, split_args, LibType, TemporaryDirectoryWinProof
)
from ..envconfig import (
get_env_var
@ -735,8 +735,8 @@ class Compiler(metaclass=abc.ABCMeta):
# TODO: there isn't really any reason for this to be a contextmanager
if extra_args is None:
extra_args = []
try:
with tempfile.TemporaryDirectory(dir=temp_dir) as tmpdirname:
with TemporaryDirectoryWinProof(dir=temp_dir) as tmpdirname:
no_ccache = False
if isinstance(code, str):
srcname = os.path.join(tmpdirname,
@ -781,11 +781,6 @@ class Compiler(metaclass=abc.ABCMeta):
if want_output:
result.output_name = output
yield result
except OSError:
# On Windows antivirus programs and the like hold on to files so
# they can't be deleted. There's not much to do in this case. Also,
# catch OSError because the directory is then no longer empty.
return
@contextlib.contextmanager
def cached_compile(self, code: str, cdata: coredata.CoreData, *,

View File

@ -22,6 +22,7 @@ import collections
from enum import IntEnum
from functools import lru_cache, wraps
from itertools import tee, filterfalse
from tempfile import TemporaryDirectory
import typing as T
import uuid
import textwrap
@ -1452,6 +1453,25 @@ def windows_proof_rm(fpath: str) -> None:
os.unlink(fpath)
class TemporaryDirectoryWinProof(TemporaryDirectory):
"""
Like TemporaryDirectory, but cleans things up using
windows_proof_rmtree()
"""
def __exit__(self, exc: T.Any, value: T.Any, tb: T.Any) -> None:
try:
super().__exit__(exc, value, tb)
except OSError:
windows_proof_rmtree(self.name)
def cleanup(self) -> None:
try:
super().cleanup()
except OSError:
windows_proof_rmtree(self.name)
def detect_subprojects(spdir_name: str, current_dir: str = '',
result: T.Optional[T.Dict[str, T.List[str]]] = None) -> T.Optional[T.Dict[str, T.List[str]]]:
if result is None: