Skip to content

Commit 84cc2b0

Browse files
authored
[LIT] replace lit.util.mkdir with pathlib.Path.mkdir (#163948)
`lit.util.mkdir` and `lit.util.mkdir_p` were written during the Python 2.x era. Since modern `pathlib` functions have similar functionality, we can simply use those instead. If you encounter a path length issue after this change, the registry value `LongPathsEnabled` must be set as described in https://learn.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-limitation . Note that the Python runtime is already marked as a `longPathAware` executable. **Background:** On Cygwin, a file named `file_name.exe` can be accessed without the suffix, simply as `file_name`, as shown below: ``` $ echo > file_name.exe $ file file_name.exe file_name.exe: very short file (no magic) $ file file_name file_name: very short file (no magic) ``` In this situation, while running `mkdir file_name` works as intended, checking for the existence of the target before calling `mkdir` incorrectly reports that it already exists and thus skips the directory creation. ``` $ test -e file_name && echo exists exists $ mkdir file_name && echo ok ok $ file file_name file_name: directory ``` Therefore, the existence pre-check should be skipped on Cygwin. Instead of add a workaround, refactored them.
1 parent 9ee9fb0 commit 84cc2b0

File tree

6 files changed

+22
-47
lines changed

6 files changed

+22
-47
lines changed

llvm/utils/lit/lit/TestRunner.py

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -462,16 +462,15 @@ def executeBuiltinMkdir(cmd, cmd_shenv):
462462
stderr = StringIO()
463463
exitCode = 0
464464
for dir in args:
465-
cwd = cmd_shenv.cwd
466-
dir = to_unicode(dir) if kIsWindows else to_bytes(dir)
467-
cwd = to_unicode(cwd) if kIsWindows else to_bytes(cwd)
468-
if not os.path.isabs(dir):
469-
dir = lit.util.abs_path_preserve_drive(os.path.join(cwd, dir))
465+
dir = pathlib.Path(dir)
466+
cwd = pathlib.Path(to_unicode(cmd_shenv.cwd))
467+
if not dir.is_absolute():
468+
dir = lit.util.abs_path_preserve_drive(cwd / dir)
470469
if parent:
471-
lit.util.mkdir_p(dir)
470+
dir.mkdir(parents=True, exist_ok=True)
472471
else:
473472
try:
474-
lit.util.mkdir(dir)
473+
dir.mkdir(exist_ok=True)
475474
except OSError as err:
476475
stderr.write("Error: 'mkdir' command failed, %s\n" % str(err))
477476
exitCode = 1
@@ -2411,7 +2410,7 @@ def runOnce(
24112410
return out, err, exitCode, timeoutInfo, status
24122411

24132412
# Create the output directory if it does not already exist.
2414-
lit.util.mkdir_p(os.path.dirname(tmpBase))
2413+
pathlib.Path(tmpBase).parent.mkdir(parents=True, exist_ok=True)
24152414

24162415
# Re-run failed tests up to test.allowed_retries times.
24172416
execdir = os.path.dirname(test.getExecPath())

llvm/utils/lit/lit/util.py

Lines changed: 5 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import math
66
import numbers
77
import os
8+
import pathlib
89
import platform
910
import re
1011
import signal
@@ -131,48 +132,17 @@ def abs_path_preserve_drive(path):
131132
# Since Python 3.8, os.path.realpath resolves sustitute drives,
132133
# so we should not use it. In Python 3.7, os.path.realpath
133134
# was implemented as os.path.abspath.
135+
if isinstance(path, pathlib.Path):
136+
return path.absolute()
134137
return os.path.abspath(path)
135138
else:
136139
# On UNIX, the current directory always has symbolic links resolved,
137140
# so any program accepting relative paths cannot preserve symbolic
138141
# links in paths and we should always use os.path.realpath.
142+
if isinstance(path, pathlib.Path):
143+
return path.resolve()
139144
return os.path.realpath(path)
140145

141-
def mkdir(path):
142-
try:
143-
if platform.system() == "Windows":
144-
from ctypes import windll
145-
from ctypes import GetLastError, WinError
146-
147-
path = os.path.abspath(path)
148-
# Make sure that the path uses backslashes here, in case
149-
# python would have happened to use forward slashes, as the
150-
# NT path format only supports backslashes.
151-
path = path.replace("/", "\\")
152-
NTPath = to_unicode(r"\\?\%s" % path)
153-
if not windll.kernel32.CreateDirectoryW(NTPath, None):
154-
raise WinError(GetLastError())
155-
else:
156-
os.mkdir(path)
157-
except OSError:
158-
e = sys.exc_info()[1]
159-
# ignore EEXIST, which may occur during a race condition
160-
if e.errno != errno.EEXIST:
161-
raise
162-
163-
164-
def mkdir_p(path):
165-
"""mkdir_p(path) - Make the "path" directory, if it does not exist; this
166-
will also make directories for any missing parent directories."""
167-
if not path or os.path.exists(path):
168-
return
169-
170-
parent = os.path.dirname(path)
171-
if parent != path:
172-
mkdir_p(parent)
173-
174-
mkdir(path)
175-
176146

177147
def listdir_files(dirname, suffixes=None, exclude_filenames=None, prefixes=None):
178148
"""Yields files in a directory.

llvm/utils/lit/tests/Inputs/shtest-glob/example_dir1.input/empty

Whitespace-only changes.

llvm/utils/lit/tests/Inputs/shtest-glob/example_dir2.input/empty

Whitespace-only changes.
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,7 @@
11
## Tests glob pattern handling in the mkdir command.
2+
3+
## This mkdir should fail because the `example_file*.input`s are regular files.
24
# RUN: not mkdir %S/example_file*.input
5+
6+
## This mkdir should succeed (so RUN should fail) because the `example_dir*.input`s that already exist are directories.
7+
# RUN: not mkdir %S/example_dir*.input
Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
## Tests glob pattern handling in echo command.
22

33
# RUN: not %{lit} -a -v %{inputs}/shtest-glob \
4-
# RUN: | FileCheck -dump-input=fail -match-full-lines %s
5-
#
4+
# RUN: | FileCheck -dump-input=fail -match-full-lines --implicit-check-not=Error: %s
65
# END.
76

87
# CHECK: UNRESOLVED: shtest-glob :: glob-echo.txt ({{[^)]*}})
98
# CHECK: TypeError: string argument expected, got 'GlobItem'
109

11-
# CHECK: FAIL: shtest-glob :: glob-mkdir.txt ({{[^)]*}})
12-
# CHECK: # error: command failed with exit status: 1
10+
# CHECK: FAIL: shtest-glob :: glob-mkdir.txt ({{[^)]*}})
11+
# CHECK: # | Error: 'mkdir' command failed, {{.*}}example_file1.input'
12+
# CHECK-NEXT: # | Error: 'mkdir' command failed, {{.*}}example_file2.input'
13+
# CHECK: # error: command failed with exit status: 1

0 commit comments

Comments
 (0)