Files
swift-mirror/utils/lit_support/split_file.py
T
Henrik G. Olsson b2ecb53bfe [utils] add split-file --leading-lines support to test updaters
This adds support in update-verify-tests and update-generated-tests.
DiffUpdater is in upstream LLVM, so it needs to be updated separately.
2026-03-04 13:38:54 -08:00

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