mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
We only want to path normalize a string (and replace backslashes with forward slashes if on Windows) if it's actually a path. But checking if there's a path with that name doesn't work if the path is a substring of an actual path. Additionally check whether the dirname points to something on the file system. If it does, it's likely meant to be interpreted as a path.
132 lines
4.8 KiB
Python
Executable File
132 lines
4.8 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
# utils/PathSanitizingFileCheck -*- python -*-
|
|
#
|
|
# This source file is part of the Swift.org open source project
|
|
#
|
|
# Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
|
|
# Licensed under Apache License v2.0 with Runtime Library Exception
|
|
#
|
|
# See https://swift.org/LICENSE.txt for license information
|
|
# See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
|
|
|
import argparse
|
|
import io
|
|
import os
|
|
import platform
|
|
import re
|
|
import subprocess
|
|
import sys
|
|
|
|
# LLVM Lit performs realpath with the config path, so all paths are relative
|
|
# to the real path. Paths that come from CMake (like cmake_binary_dir and
|
|
# swift_src_root), might not do real path. Use realpath to normalize. Because
|
|
# this normalizes Windows paths to use backslashes, we have to replace them
|
|
# back to forward slashes.
|
|
def normalize_if_path(s):
|
|
# Check dirname for cases like a file named `%t.out.txt`
|
|
# There won't be a `%t` path, but we still want to match this path substring.
|
|
if not os.path.exists(s) and not os.path.exists(os.path.dirname(s)):
|
|
return s
|
|
if platform.system() == "Windows":
|
|
return os.path.abspath(s).replace('\\', '/')
|
|
else:
|
|
return os.path.realpath(s)
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser(
|
|
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
description="""
|
|
PathSanitizingFileCheck is a wrapper around LLVM's FileCheck. In addition
|
|
to all FileCheck features, PathSanitizingFileCheck can replace given
|
|
strings in the input with other strings. This feature is used to replace
|
|
paths to the source and build directories with path-independent
|
|
constants.""")
|
|
|
|
parser.add_argument(
|
|
"--sanitize",
|
|
help="replace the given string with another string",
|
|
metavar="REPLACEMENT=SOURCE",
|
|
action="append",
|
|
dest="sanitize_strings",
|
|
default=[])
|
|
|
|
parser.add_argument(
|
|
"--use-filecheck",
|
|
help="path to LLVM FileCheck executable",
|
|
metavar="PATH",
|
|
action="store",
|
|
dest="file_check_path",
|
|
default="FileCheck")
|
|
|
|
parser.add_argument(
|
|
"--enable-windows-compatibility",
|
|
help="Enable Windows path compatibility, which checks against both "
|
|
"forward slashes and backward slashes.",
|
|
action="store_true")
|
|
|
|
parser.add_argument(
|
|
"--enable-yaml-compatibility",
|
|
help="Enable YAML path compatibility. Since YAML double escapes "
|
|
"backward slashes, we need to check for them escaped. Only "
|
|
"available if Windows compatibility is enabled.",
|
|
action="store_true")
|
|
|
|
parser.add_argument(
|
|
"--dry-run",
|
|
help="Apply the replacements to the input and print the result "
|
|
"to standard output",
|
|
action="store_true")
|
|
|
|
parser.add_argument(
|
|
"--ignore-runtime-warnings",
|
|
help="Ignore warnings from the Swift runtime",
|
|
action="store_true")
|
|
|
|
args, unknown_args = parser.parse_known_args()
|
|
|
|
if args.enable_windows_compatibility:
|
|
if args.enable_yaml_compatibility:
|
|
slashes_re = r'(/|\\\\|\\\\\\\\)'
|
|
else:
|
|
slashes_re = r'(/|\\\\)'
|
|
else:
|
|
slashes_re = r'/'
|
|
|
|
stdin = io.open(sys.stdin.fileno(), 'r', encoding='utf-8', errors='ignore').read()
|
|
|
|
for s in sorted(args.sanitize_strings, key=len, reverse=True):
|
|
replacement, pattern = s.split('=', 1)
|
|
# Since we want to use pattern as a regex in some platforms, we need
|
|
# to escape it first, and then replace the escaped slash
|
|
# literal (r'\\/') for our platform-dependent slash regex.
|
|
stdin = re.sub(re.sub(r'\\/' if sys.version_info[0] < 3 else r'/',
|
|
slashes_re, re.escape(normalize_if_path(pattern))),
|
|
replacement, stdin)
|
|
|
|
# Because we force the backtracer on in the tests, we can get runtime
|
|
# warnings about privileged programs. Suppress those, and also the
|
|
# warning it might emit if backtracing isn't supported on the test platform.
|
|
# Additionally, suppress warnings about unknown backtracer options, since
|
|
# we might want to add new ones to the lit tests and we should ignore
|
|
# messages from the system copy of the runtime in that case.
|
|
if args.ignore_runtime_warnings:
|
|
stdin = re.sub(r'^swift runtime: (backtrace-on-crash is not '
|
|
r'supported|unknown) .*\n', "", stdin, flags=re.M)
|
|
|
|
if args.dry_run:
|
|
print(stdin)
|
|
return 0
|
|
else:
|
|
p = subprocess.Popen(
|
|
[args.file_check_path] + unknown_args, stdin=subprocess.PIPE)
|
|
stdout, stderr = p.communicate(stdin.encode('utf-8'))
|
|
if stdout is not None:
|
|
print(stdout)
|
|
if stderr is not None:
|
|
print(stderr, file=sys.stderr)
|
|
return p.wait()
|
|
|
|
|
|
if __name__ == '__main__':
|
|
exit(main())
|