1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-24 19:52:54 +01:00

lit: support long paths on Windows

Use ctypes to call into SHFileOperationW with the extended NT path to allow us
to remove paths which exceed 261 characters on Windows. This functionality is
exercised by swift's test suite.

llvm-svn: 357778
This commit is contained in:
Saleem Abdulrasool 2019-04-05 16:48:00 +00:00
parent e77d808b74
commit 52d35270c6
2 changed files with 64 additions and 9 deletions

View File

@ -353,7 +353,7 @@ def executeBuiltinMkdir(cmd, cmd_shenv):
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
@ -613,7 +613,49 @@ def executeBuiltinRm(cmd, cmd_shenv):
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 `SHFileOperationsW` 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,

View File

@ -142,6 +142,25 @@ def detectCPUs():
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.kernel32.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."""
@ -152,13 +171,7 @@ def mkdir_p(path):
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):