Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(817)

Unified Diff: third_party/WebKit/Tools/Scripts/webkitpy/common/system/filesystem.py

Issue 2896423004: webkitpy: Remove contents of directory. (Closed)
Patch Set: Fixing mocks Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: third_party/WebKit/Tools/Scripts/webkitpy/common/system/filesystem.py
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/common/system/filesystem.py b/third_party/WebKit/Tools/Scripts/webkitpy/common/system/filesystem.py
index c06c190f8e66399a55140e0fbcdfeceba612bab1..4358b0fa9296e6449c465b8a6654bead82226c04 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/common/system/filesystem.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/common/system/filesystem.py
@@ -28,19 +28,23 @@
"""Wrapper object for the file system / source tree."""
-import stat
import codecs
import errno
import exceptions
import glob
import hashlib
+import logging
import os
import shutil
+import stat
import sys
import tempfile
import time
+_log = logging.getLogger(__name__)
+
+
class FileSystem(object):
"""FileSystem interface for webkitpy.
@@ -136,8 +140,8 @@ class FileSystem(object):
def listdir(self, path):
return os.listdir(path)
- def walk(self, top):
- return os.walk(top)
+ def walk(self, top, topdown=True, onerror=None, followlinks=False):
+ return os.walk(top, topdown=topdown, onerror=onerror, followlinks=followlinks)
def mkdtemp(self, **kwargs):
"""Create and return a uniquely named directory.
@@ -246,7 +250,7 @@ class FileSystem(object):
class _WindowsError(exceptions.OSError):
"""Fake exception for Linux and Mac."""
- def remove(self, path, osremove=os.remove):
+ def remove(self, path, osremove=os.remove, retry=True):
"""On Windows, if a process was recently killed and it held on to a
file, the OS will hold on to the file for a short while. This makes
attempts to delete the file fail. To work around that, this method
@@ -266,12 +270,78 @@ class FileSystem(object):
except exceptions.WindowsError:
time.sleep(sleep_interval)
retry_timeout_sec -= sleep_interval
- if retry_timeout_sec < 0:
+ if retry_timeout_sec < 0 and not retry:
raise
- def rmtree(self, path):
+ def rmtree(self, path, ignore_errors=True, onerror=None):
"""Delete the directory rooted at path, whether empty or not."""
- shutil.rmtree(path, ignore_errors=True)
+ shutil.rmtree(path, ignore_errors=ignore_errors, onerror=onerror)
+
+ def remove_contents(self, dirname):
+ """Attempt to remove the contents of a directory tree.
+ Args:
+ dirname (string): Directory to remove the contents of.
+
+ Returns:
+ bool: True if the directory is now empty.
+ """
+ # We try multiple times, because on Windows a process which is
+ # currently closing could still have a file open in the directory.
+ _log.info('Removing contents of %s', dirname)
+ errors = []
+
+ def onerror(func, path, exc_info):
+ errors.append(path)
+ _log.exception('Failed at %s %s: %r', func, path, exc_info)
+
+ attempts = 0
+ while attempts < 5:
+ del errors[:]
+
+ for name in self.listdir(dirname):
+ fullname = self.join(dirname, name)
+
+ isdir = True
+ try:
+ isdir = self.isdir(fullname)
+ except os.error:
+ onerror(self.isdir, fullname, sys.exc_info())
+ continue
+
+ if isdir:
+ try:
+ _log.debug('Removing directory %s', fullname)
+ self.rmtree(fullname, ignore_errors=False, onerror=onerror)
+ except os.error:
+ onerror(self.rmtree, fullname, sys.exc_info())
+ continue
+ else:
+ try:
+ _log.debug('Removing file %s', fullname)
+ self.remove(fullname, retry=False)
+ except os.error:
+ onerror(self.remove, fullname, sys.exc_info())
+ continue
+
+ if not errors:
+ break
+
+ _log.warning('Contents removal failed, retrying in 1 second.')
+ attempts += 1
+ time.sleep(1)
+
+ # Check the path is gone.
+ if not self.listdir(dirname):
+ return True
+
+ _log.warning('Unable to remove %s', dirname)
+ for dirpath, dirnames, filenames in self.walk(dirname, onerror=onerror, topdown=False):
+ for fname in filenames:
+ _log.warning('File %s still in output dir.', self.join(dirpath, fname))
+ for dname in dirnames:
+ _log.warning('Dir %s still in output dir.', self.join(dirpath, dname))
+
+ return False
def copytree(self, source, destination):
shutil.copytree(source, destination)

Powered by Google App Engine
This is Rietveld 408576698