Commit 086285fa authored by Jérome Perrin's avatar Jérome Perrin

testnode: properly support deletion of chmod'ed files

/reviewed-on !748
parent 70653d64
...@@ -489,21 +489,35 @@ shared = true ...@@ -489,21 +489,35 @@ shared = true
test_node.purgeOldTestSuite(test_suite_data) test_node.purgeOldTestSuite(test_suite_data)
self.assertEquals(['foo'], os.listdir(self.working_directory)) self.assertEquals(['foo'], os.listdir(self.working_directory))
def test_purgeOldTestSuiteChmod(self): def test_purgeOldTestSuiteChmodNonWriteable(self):
"""Old test suites can be deleted even when some files/directories have """Old test suites can be deleted even when some files/directories have
been chmod'd to make read only. """ been chmod'd to make non-writeable """
test_node = self.getTestNode() test_node = self.getTestNode()
test_suite_data = self.getTestSuiteData(add_third_repository=True) test_suite_data = self.getTestSuiteData(add_third_repository=True)
os.mkdir(os.path.join(self.working_directory, 'bar')) os.mkdir(os.path.join(self.working_directory, 'bar'))
non_writable_file = open(os.path.join(self.working_directory, 'bar', 'non-writable-file'), 'w') non_writable_file = open(os.path.join(self.working_directory, 'bar', 'non-writable-file'), 'w')
non_writable_file.close() non_writable_file.close()
# make this file and directory non writeable
os.chmod(os.path.join(self.working_directory, 'bar', 'non-writable-file'), 0o000) os.chmod(os.path.join(self.working_directory, 'bar', 'non-writable-file'), 0o400) # -r--------
os.chmod(os.path.join(self.working_directory, 'bar'), 0o000) os.chmod(os.path.join(self.working_directory, 'bar'), 0o500) # dr-x------
test_node.purgeOldTestSuite(test_suite_data) # should not fail test_node.purgeOldTestSuite(test_suite_data) # should not fail
self.assertEqual([], os.listdir(self.working_directory)) self.assertEqual([], os.listdir(self.working_directory))
def test_purgeOldTestSuiteChmodNonWriteableNonReadable(self):
"""Old test suites can be deleted even when some files/directories have
been chmod'd to make them non readable and non writeable. """
test_node = self.getTestNode()
test_suite_data = self.getTestSuiteData(add_third_repository=True)
os.mkdir(os.path.join(self.working_directory, 'bar'))
non_writable_file = open(os.path.join(self.working_directory, 'bar', 'non-writable-file'), 'w')
non_writable_file.close()
os.chmod(os.path.join(self.working_directory, 'bar', 'non-writable-file'), 0o000) # ----------
os.chmod(os.path.join(self.working_directory, 'bar'), 0o000) # d---------
test_node.purgeOldTestSuite(test_suite_data) # should not fail
self.assertEqual([], os.listdir(self.working_directory))
def test_09_runTestSuite(self, my_test_type='UnitTest'): def test_09_runTestSuite(self, my_test_type='UnitTest'):
""" """
......
import os import os
import stat import stat
import shutil import shutil
import errno
def rmtree(path): def rmtree(path):
"""Delete a path recursively. """Delete a path recursively.
Like shutil.rmtree, but supporting the case that some files or folder Like shutil.rmtree, but supporting the case that some files or folder
might have been marked read only. """ might have been marked read only. """
def chmod_retry(func, path, _): def chmod_retry(func, failed_path, exc_info):
"""Make sure the file is writeable / the directory is executable. """Make sure the directories are executable and writable.
""" """
if not os.path.exists(path): e = exc_info[1]
# because we are calling again rmtree on listdir errors, this path might if isinstance(e, OSError):
# have been already deleted by the recursive call to rmtree. if e.errno == errno.ENOENT:
return # because we are calling again rmtree on listdir errors, this path might
# have been already deleted by the recursive call to rmtree.
return
if e.errno == errno.EACCES:
if func is os.listdir:
os.chmod(failed_path, 0o700)
# corner case to handle errors in listing directories.
# https://bugs.python.org/issue8523
return shutil.rmtree(failed_path, onerror=chmod_retry)
# If parent directory is not writable, we still cannot delete the file.
# But make sure not to change the parent of the folder we are deleting.
if failed_path != path:
os.chmod(os.path.dirname(failed_path), 0o700)
return func(failed_path)
raise
os.chmod(path, 0o777)
if func is os.listdir:
# corner case to handle errors in listing directories.
# https://bugs.python.org/issue8523
# This might raises MaxRecursionError when the directory cannot be listed
# for other reasons than "user does not have read permssion"
return shutil.rmtree(path, onerror=chmod_retry)
func(path)
shutil.rmtree(path, onerror=chmod_retry) shutil.rmtree(path, onerror=chmod_retry)
def createFolder(folder, clean=False): def createFolder(folder, clean=False):
if os.path.exists(folder): if os.path.exists(folder):
if not clean: if not clean:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment