Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 7 additions & 8 deletions llvm/utils/lit/lit/TestRunner.py
Original file line number Diff line number Diff line change
Expand Up @@ -462,16 +462,15 @@ def executeBuiltinMkdir(cmd, cmd_shenv):
stderr = StringIO()
exitCode = 0
for dir in args:
cwd = cmd_shenv.cwd
dir = to_unicode(dir) if kIsWindows else to_bytes(dir)
cwd = to_unicode(cwd) if kIsWindows else to_bytes(cwd)
if not os.path.isabs(dir):
dir = lit.util.abs_path_preserve_drive(os.path.join(cwd, dir))
dir = pathlib.Path(dir)
cwd = pathlib.Path(to_unicode(cmd_shenv.cwd))
if not dir.is_absolute():
dir = lit.util.abs_path_preserve_drive(cwd / dir)
if parent:
lit.util.mkdir_p(dir)
dir.mkdir(parents=True, exist_ok=True)
else:
try:
lit.util.mkdir(dir)
dir.mkdir(exist_ok=True)
except OSError as err:
stderr.write("Error: 'mkdir' command failed, %s\n" % str(err))
exitCode = 1
Expand Down Expand Up @@ -2395,7 +2394,7 @@ def runOnce(
return out, err, exitCode, timeoutInfo, status

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

# Re-run failed tests up to test.allowed_retries times.
execdir = os.path.dirname(test.getExecPath())
Expand Down
40 changes: 5 additions & 35 deletions llvm/utils/lit/lit/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import math
import numbers
import os
import pathlib
import platform
import re
import signal
Expand Down Expand Up @@ -131,48 +132,17 @@ def abs_path_preserve_drive(path):
# Since Python 3.8, os.path.realpath resolves sustitute drives,
# so we should not use it. In Python 3.7, os.path.realpath
# was implemented as os.path.abspath.
if isinstance(path, pathlib.Path):
return path.absolute()
return os.path.abspath(path)
else:
# On UNIX, the current directory always has symbolic links resolved,
# so any program accepting relative paths cannot preserve symbolic
# links in paths and we should always use os.path.realpath.
if isinstance(path, pathlib.Path):
return path.resolve()
return os.path.realpath(path)

def mkdir(path):
try:
if platform.system() == "Windows":
from ctypes import windll
from ctypes import GetLastError, WinError

path = os.path.abspath(path)
# Make sure that the path uses backslashes here, in case
# python would have happened to use forward slashes, as the
# NT path format only supports backslashes.
path = path.replace("/", "\\")
NTPath = to_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
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Previously, all EEXIST errors were ignored.
We should indeed ignore races between concurrent mkdir targets, but I don't see any reason to allow races between touch target and mkdir target.
Since pathlib's exist_ok=True behaves this way, the test shtest-glob.py has been updated to reflect the new behavior.

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."""
if not path or os.path.exists(path):
return

parent = os.path.dirname(path)
if parent != path:
mkdir_p(parent)

mkdir(path)


def listdir_files(dirname, suffixes=None, exclude_filenames=None, prefixes=None):
"""Yields files in a directory.
Expand Down
8 changes: 8 additions & 0 deletions llvm/utils/lit/tests/Inputs/shtest-glob/glob-mkdir.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,10 @@
## Tests glob pattern handling in the mkdir command.

## This mkdir should fail because the `example_file*.input`s are regular files.
# RUN: not mkdir %S/example_file*.input

# RUN: mkdir %S/example_dir1.new
# RUN: mkdir %S/example_dir2.new

## This mkdir should succeed (so RUN should fail) because the `example_dir*.new`s are directories already exist.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: remove `are'

# RUN: not mkdir %S/example_dir*.new
9 changes: 5 additions & 4 deletions llvm/utils/lit/tests/shtest-glob.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
## Tests glob pattern handling in echo command.

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

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

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