llvm.org GIT mirror llvm / 11ab360
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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@357778 91177308-0d34-0410-b5e6-96231b3b80d8 Saleem Abdulrasool 4 months ago
2 changed file(s) with 64 addition(s) and 9 deletion(s). Raw diff Collapse all Expand all
352352 lit.util.mkdir_p(dir)
353353 else:
354354 try:
355 os.mkdir(dir)
355 lit.util.mkdir(dir)
356356 except OSError as err:
357357 stderr.write("Error: 'mkdir' command failed, %s\n" % str(err))
358358 exitCode = 1
612612 if not recursive:
613613 stderr.write("Error: %s is a directory\n" % path)
614614 exitCode = 1
615 shutil.rmtree(path, onerror = on_rm_error if force else None)
615 if platform.system() == 'Windows':
616 # NOTE: use ctypes to access `SHFileOperationsW` on Windows to
617 # use the NT style path to get access to long file paths which
618 # cannot be removed otherwise.
619 from ctypes.wintypes import BOOL, HWND, LPCWSTR, POINTER, UINT, WORD
620 from ctypes import c_void_p, byref
621 from ctypes import Structure
622 from ctypes import windll, WinError
623
624 class SHFILEOPSTRUCTW(Structure):
625 _fields_ = [
626 ('hWnd', HWND),
627 ('wFunc', UINT),
628 ('pFrom', LPCWSTR),
629 ('pTo', LPCWSTR),
630 ('fFlags', WORD),
631 ('fAnyOperationsAborted', BOOL),
632 ('hNameMappings', c_void_p),
633 ('lpszProgressTitle', LPCWSTR),
634 ]
635
636 FO_MOVE, FO_COPY, FO_DELETE, FO_RENAME = xrange(1, 5)
637
638 FOF_SILENT = 4
639 FOF_NOCONFIRMATION = 16
640 FOF_NOCONFIRMMKDIR = 512
641 FOF_NOERRORUI = 1024
642
643 FOF_NO_UI = FOF_SILENT | FOF_NOCONFIRMATION | FOF_NOERRORUI | FOF_NOCONFIRMMKDIR
644
645 SHFileOperationW = windll.shell32.SHFileOperationW
646 SHFileOperationW.argtypes = [POINTER(SHFILEOPSTRUCTW)]
647
648 path = os.path.abspath(path)
649
650 operation = SHFILEOPSTRUCTW(wFunc=UINT(FO_DELETE),
651 pFrom=LPCWSTR(unicode(path + '\0')),
652 fFlags=FOF_NO_UI)
653 result = SHFileOperationW(byref(operation))
654 if result:
655 raise WinError(result)
656 else:
657 shutil.rmtree(path, onerror = on_rm_error if force else None)
616658 else:
617659 if force and not os.access(path, os.W_OK):
618660 os.chmod(path,
141141 return 1 # Default
142142
143143
144 def mkdir(path):
145 try:
146 if platform.system() == 'Windows':
147 from ctypes import windll
148 from ctypes import GetLastError, WinError
149
150 path = os.path.abspath(path)
151 NTPath = unicode(r'\\?\%s' % path)
152 if not windll.kernel32.CreateDirectoryW(NTPath, None):
153 raise WinError(GetLastError())
154 else:
155 os.mkdir(path)
156 except OSError:
157 e = sys.exc_info()[1]
158 # ignore EEXIST, which may occur during a race condition
159 if e.errno != errno.EEXIST:
160 raise
161
162
144163 def mkdir_p(path):
145164 """mkdir_p(path) - Make the "path" directory, if it does not exist; this
146165 will also make directories for any missing parent directories."""
151170 if parent != path:
152171 mkdir_p(parent)
153172
154 try:
155 os.mkdir(path)
156 except OSError:
157 e = sys.exc_info()[1]
158 # Ignore EEXIST, which may occur during a race condition.
159 if e.errno != errno.EEXIST:
160 raise
173 mkdir(path)
161174
162175
163176 def listdir_files(dirname, suffixes=None, exclude_filenames=None):