Create helper function for a rmtree that works reliably on Windows.

pull/1809/merge
Jussi Pakkanen 8 years ago
parent 189784b474
commit effe4fb134
  1. 17
      mesonbuild/mesonlib.py
  2. 3
      mesonbuild/scripts/dist.py
  3. 23
      run_project_tests.py

@ -15,6 +15,7 @@
"""A library of random helper functionality.""" """A library of random helper functionality."""
import stat import stat
import time
import platform, subprocess, operator, os, shutil, re import platform, subprocess, operator, os, shutil, re
import collections import collections
@ -687,6 +688,22 @@ def get_filenames_templates_dict(inputs, outputs):
values['@OUTDIR@'] = '.' values['@OUTDIR@'] = '.'
return values return values
def windows_proof_rmtree(f):
# On Windows if anyone is holding a file open you can't
# delete it. As an example an anti virus scanner might
# be scanning files you are trying to delete. The only
# way to fix this is to try again and again.
delays = [0.1, 0.1, 0.2, 0.2, 0.2, 0.5, 0.5, 1, 1, 1, 1, 2]
for d in delays:
try:
shutil.rmtree(f)
return
except (OSError, PermissionError):
time.sleep(d)
# Try one last time and throw if it fails.
shutil.rmtree(f)
class OrderedSet(collections.MutableSet): class OrderedSet(collections.MutableSet):
"""A set that preserves the order in which items are added, by first """A set that preserves the order in which items are added, by first
insertion. insertion.

@ -22,6 +22,7 @@ import tarfile, zipfile
import tempfile import tempfile
from glob import glob from glob import glob
from mesonbuild.environment import detect_ninja from mesonbuild.environment import detect_ninja
from mesonbuild.mesonlib import windows_proof_rmtree
def create_hash(fname): def create_hash(fname):
hashname = fname + '.sha256sum' hashname = fname + '.sha256sum'
@ -49,7 +50,7 @@ def create_zip(zipfilename, packaging_dir):
def del_gitfiles(dirname): def del_gitfiles(dirname):
for f in glob(os.path.join(dirname, '.git*')): for f in glob(os.path.join(dirname, '.git*')):
if os.path.isdir(f) and not os.path.islink(f): if os.path.isdir(f) and not os.path.islink(f):
shutil.rmtree(f) windows_proof_rmtree(f)
else: else:
os.unlink(f) os.unlink(f)

@ -114,24 +114,11 @@ class AutoDeletedDir:
return self.dir return self.dir
def __exit__(self, _type, value, traceback): def __exit__(self, _type, value, traceback):
# On Windows, shutil.rmtree fails sometimes, because 'the directory is not empty'. # We don't use tempfile.TemporaryDirectory, but wrap the
# Retrying fixes this. # deletion in the AutoDeletedDir class because
# That's why we don't use tempfile.TemporaryDirectory, but wrap the deletion in the AutoDeletedDir class. # it fails on Windows due antivirus programs
retries = 5 # holding files open.
for i in range(0, retries): mesonlib.windows_proof_rmtree(self.dir)
try:
shutil.rmtree(self.dir)
return
# Sometimes we get: ValueError: I/O operation on closed file.
except ValueError:
return
# Deleting can raise OSError or PermissionError on Windows
# (most likely because of anti-virus locking the file)
except (OSError, PermissionError):
if i == retries - 1:
mlog.warning('Could not delete temporary directory.')
return
time.sleep(0.1 * (2**i))
failing_logs = [] failing_logs = []
print_debug = 'MESON_PRINT_TEST_OUTPUT' in os.environ print_debug = 'MESON_PRINT_TEST_OUTPUT' in os.environ

Loading…
Cancel
Save