From 9c1a38253f698c44ac5f23bdfa451b9eb841518a Mon Sep 17 00:00:00 2001 From: Pauli Virtanen Date: Sun, 25 Jun 2017 19:29:02 +0200 Subject: [PATCH] On Windows, try harder to remove files in long_path_rmtree --- asv/util.py | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/asv/util.py b/asv/util.py index f2b3c274a..d01e1477e 100644 --- a/asv/util.py +++ b/asv/util.py @@ -964,11 +964,23 @@ def long_path(path): return path return "\\\\?\\" + os.path.abspath(path) - def _remove_readonly(func, path, exc_info): - """Clear the readonly bit and reattempt the removal; - Windows rmtree doesn't do this by default""" - os.chmod(path, stat.S_IWRITE) - func(path) + def _remove_readonly(func, path, exc_info, wait_flag): + """Try harder to remove files on Windows""" + + if not wait_flag[0]: + # Wait a bit before trying again, but only once + wait_flag[0] = True + time.sleep(1) + + if exc_info[1].errno == errno.EACCES: + # Clear any read-only bits + os.chmod(path, stat.S_IRWXU | stat.S_IRWXG) + + try: + func(path) + except: + # Reraise original error + six.reraise(*exc_info) def long_path_open(filename, *a, **kw): return open(long_path(filename), *a, **kw) @@ -977,7 +989,8 @@ def long_path_rmtree(path, ignore_errors=False): if ignore_errors: onerror = None else: - onerror = _remove_readonly + wait_flag = [False] + onerror = lambda f, p, e: _remove_readonly(f, p, e, wait_flag) shutil.rmtree(long_path(path), ignore_errors=ignore_errors, onerror=onerror)