diff --git a/mesonbuild/mesonlib.py b/mesonbuild/mesonlib.py index 59d4f8108..98c2366d6 100644 --- a/mesonbuild/mesonlib.py +++ b/mesonbuild/mesonlib.py @@ -1116,6 +1116,22 @@ def windows_proof_rmtree(f): shutil.rmtree(f) +def windows_proof_rm(fpath): + """Like windows_proof_rmtree, but for a single file.""" + if os.path.isfile(fpath): + os.chmod(fpath, os.stat(fpath).st_mode | stat.S_IWRITE | stat.S_IREAD) + 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: + os.unlink(fpath) + return + except FileNotFoundError: + return + except (OSError, PermissionError): + time.sleep(d) + os.unlink(fpath) + + def detect_subprojects(spdir_name, current_dir='', result=None): if result is None: result = {} diff --git a/mesonbuild/msetup.py b/mesonbuild/msetup.py index 63014f196..56a0e9a79 100644 --- a/mesonbuild/msetup.py +++ b/mesonbuild/msetup.py @@ -73,7 +73,15 @@ class MesonApp: coredata.read_cmd_line_file(self.build_dir, options) try: - mesonlib.windows_proof_rmtree(self.build_dir) + # Don't delete the whole tree, just all of the files and + # folders in the tree. Otherwise calling wipe form the builddir + # will cause a crash + for l in os.listdir(self.build_dir): + l = os.path.join(self.build_dir, l) + if os.path.isdir(l): + mesonlib.windows_proof_rmtree(l) + else: + mesonlib.windows_proof_rm(l) finally: # Restore the file path = os.path.dirname(filename) diff --git a/run_unittests.py b/run_unittests.py index 743eb12d3..6a1f5df9e 100755 --- a/run_unittests.py +++ b/run_unittests.py @@ -2922,11 +2922,7 @@ recommended as it is not supported on some platforms''') self.wipe() self.init(testdir, extra_args=['-Dstart_native=true']) - def test_reconfigure(self): - testdir = os.path.join(self.unit_test_dir, '46 reconfigure') - self.init(testdir, extra_args=['-Dopt1=val1']) - self.setconf('-Dopt2=val2') - + def __reconfigure(self): # Set an older version to force a reconfigure from scratch filename = os.path.join(self.privatedir, 'coredata.dat') with open(filename, 'rb') as f: @@ -2935,6 +2931,13 @@ recommended as it is not supported on some platforms''') with open(filename, 'wb') as f: pickle.dump(obj, f) + def test_reconfigure(self): + testdir = os.path.join(self.unit_test_dir, '46 reconfigure') + self.init(testdir, extra_args=['-Dopt1=val1']) + self.setconf('-Dopt2=val2') + + self.__reconfigure() + out = self.init(testdir, extra_args=['--reconfigure', '-Dopt3=val3']) self.assertRegex(out, 'WARNING:.*Regenerating configuration from scratch') self.assertRegex(out, 'opt1 val1') @@ -2957,6 +2960,14 @@ recommended as it is not supported on some platforms''') self.build() self.run_tests() + def test_wipe_from_builddir(self): + testdir = os.path.join(self.common_test_dir, '162 custom target subdir depend files') + self.init(testdir) + self.__reconfigure() + + with Path(self.builddir): + self.init(testdir, extra_args=['--wipe']) + def test_target_construct_id_from_path(self): # This id is stable but not guessable. # The test is supposed to prevent unintentional