mirror of
https://github.com/apple/swift.git
synced 2026-06-20 15:42:51 +02:00
b2ecb53bfe
This adds support in update-verify-tests and update-generated-tests. DiffUpdater is in upstream LLVM, so it needs to be updated separately.
109 lines
3.4 KiB
Python
109 lines
3.4 KiB
Python
import os
|
|
import shlex
|
|
import pathlib
|
|
|
|
|
|
class SplitFileTarget:
|
|
def __init__(self, slice_start_idx, test_path, lines, name):
|
|
self.slice_start_idx = slice_start_idx
|
|
self.test_path = test_path
|
|
self.lines = lines
|
|
self.name = name
|
|
|
|
def copyFrom(self, source, leading_lines=False):
|
|
lines_before = self.lines[: self.slice_start_idx + 1]
|
|
self.lines = self.lines[self.slice_start_idx + 1 :]
|
|
slice_end_idx = None
|
|
for i, l in enumerate(self.lines):
|
|
if SplitFileTarget._get_split_line_path(l) != None:
|
|
slice_end_idx = i
|
|
break
|
|
if slice_end_idx is not None:
|
|
lines_after = self.lines[slice_end_idx:]
|
|
else:
|
|
lines_after = []
|
|
with open(source, "r") as f:
|
|
source_lines = f.readlines()
|
|
if leading_lines:
|
|
# Strip the leading blank lines added by split-file --leading-lines
|
|
source_lines = source_lines[self.slice_start_idx + 1 :]
|
|
new_lines = lines_before + source_lines + lines_after
|
|
with open(self.test_path, "w") as f:
|
|
for l in new_lines:
|
|
f.write(l)
|
|
|
|
def __str__(self):
|
|
return f"slice {self.name} in {self.test_path}"
|
|
|
|
@staticmethod
|
|
def get_target_dir(commands, test_path):
|
|
# posix=True breaks Windows paths because \ is treated as an escaping character
|
|
for cmd in commands:
|
|
split = shlex.split(cmd, posix=False)
|
|
if "split-file" not in split:
|
|
continue
|
|
start_idx = split.index("split-file")
|
|
split = split[start_idx:]
|
|
# Skip flags like --leading-lines
|
|
leading_lines = "--leading-lines" in split
|
|
args = [s for s in split[1:] if not s.startswith("-")]
|
|
if len(args) < 2:
|
|
continue
|
|
p = unquote(args[0].strip())
|
|
if not test_path.samefile(p):
|
|
continue
|
|
return (unquote(args[1].strip()), leading_lines)
|
|
return None
|
|
|
|
@staticmethod
|
|
def create(path, commands, test_path, target_dir):
|
|
path = pathlib.Path(path)
|
|
with open(test_path, "r") as f:
|
|
lines = f.readlines()
|
|
for i, l in enumerate(lines):
|
|
p = SplitFileTarget._get_split_line_path(l)
|
|
if p and path.samefile(os.path.join(target_dir, p)):
|
|
idx = i
|
|
break
|
|
else:
|
|
return None
|
|
return SplitFileTarget(idx, test_path, lines, p)
|
|
|
|
@staticmethod
|
|
def _get_split_line_path(l):
|
|
if len(l) < 6:
|
|
return None
|
|
if l.startswith("//"):
|
|
l = l[2:]
|
|
else:
|
|
l = l[1:]
|
|
if l.startswith("--- "):
|
|
l = l[4:]
|
|
else:
|
|
return None
|
|
return l.rstrip()
|
|
|
|
|
|
def unquote(s):
|
|
if len(s) > 1 and s[0] == s[-1] and (s[0] == '"' or s[0] == "'"):
|
|
return s[1:-1]
|
|
return s
|
|
|
|
|
|
def propagate_split_files(test_path, updated_files, commands):
|
|
test_path = pathlib.Path(test_path)
|
|
result = SplitFileTarget.get_target_dir(commands, test_path)
|
|
if not result:
|
|
return updated_files
|
|
split_target_dir, leading_lines = result
|
|
|
|
new = []
|
|
for file in updated_files:
|
|
target = SplitFileTarget.create(file, commands, test_path, split_target_dir)
|
|
if target:
|
|
target.copyFrom(file, leading_lines)
|
|
new.append(str(target))
|
|
else:
|
|
new.append(file)
|
|
return new
|