Index: utils/lit/lit/TestRunner.py =================================================================== --- utils/lit/lit/TestRunner.py +++ utils/lit/lit/TestRunner.py @@ -350,7 +350,7 @@ lit.util.mkdir_p(dir) else: try: - os.mkdir(dir) + lit.util.mkdir(dir) except OSError as err: stderr.write("Error: 'mkdir' command failed, %s\n" % str(err)) exitCode = 1 @@ -607,7 +607,51 @@ if not recursive: stderr.write("Error: %s is a directory\n" % path) exitCode = 1 - shutil.rmtree(path, onerror = on_rm_error if force else None) + + if platform.system() == 'Windows': + # NOTE: use ctypes to access `SHFileOperationW` on Windows + # to use the NT style path to get access to long file paths + # which cannot be removed otherwise. + from ctypes.wintypes import BOOL, HWND, LPCWSTR, POINTER, UINT, WORD + from ctypes import c_void_p, byref + from ctypes import Structure + from ctypes import windll, WinError + + class SHFILEOPSTRUCTW(Structure): + _fields_ = [ + ('hWnd', HWND), + ('wFunc', UINT), + ('pFrom', LPCWSTR), + ('pTo', LPCWSTR), + ('fFlags', WORD), + ('fAnyOperationsAborted', BOOL), + ('hNameMappings', c_void_p), + ('lpszProgressTitle', LPCWSTR), + ] + + FO_MOVE, FO_COPY, FO_DELETE, FO_RENAME = xrange(1, 5) + + FOF_SILENT = 4 + FOF_NOCONFIRMATION = 16 + FOF_NOCONFIRMMKDIR = 512 + FOF_NOERRORUI = 1024 + + FOF_NO_UI = FOF_SILENT | FOF_NOCONFIRMATION | FOF_NOERRORUI | FOF_NOCONFIRMMKDIR + + SHFileOperationW = windll.shell32.SHFileOperationW + SHFileOperationW.argtypes = [POINTER(SHFILEOPSTRUCTW)] + + path = os.path.abspath(path) + + operation = SHFILEOPSTRUCTW(wFunc=UINT(FO_DELETE), + pFrom=LPCWSTR(unicode(path + '\0')), + fFlags=FOF_NO_UI) + result = SHFileOperationW(byref(operation)) + if result: + raise WinError(result) + else: + shutil.rmtree(path, onerror = on_rm_error if force else None) + else: if force and not os.access(path, os.W_OK): os.chmod(path, Index: utils/lit/lit/util.py =================================================================== --- utils/lit/lit/util.py +++ utils/lit/lit/util.py @@ -128,6 +128,25 @@ return 1 # Default +def mkdir(path): + try: + if platform.system() == 'Windows': + from ctypes import windll + from ctypes import GetLastError, WinError + + path = os.path.abspath(path) + NTPath = unicode(r'\\?\%s' % path) + if not windll.CreateDirectoryW(NTPath, None): + raise WinError(GetLastError()) + else: + os.mkdir(path) + except OSError: + e = sys.exc_info()[1] + # ignore EEXIST, which may occur during a race condition + if e.errno != errno.EEXIST: + raise + + def mkdir_p(path): """mkdir_p(path) - Make the "path" directory, if it does not exist; this will also make directories for any missing parent directories.""" @@ -138,13 +157,7 @@ if parent != path: mkdir_p(parent) - try: - os.mkdir(path) - except OSError: - e = sys.exc_info()[1] - # Ignore EEXIST, which may occur during a race condition. - if e.errno != errno.EEXIST: - raise + mkdir(path) def listdir_files(dirname, suffixes=None, exclude_filenames=None):