ykit/buildtool/patcher/filepatcher.py
2024-08-17 19:38:31 +02:00

48 lines
1.7 KiB
Python

from .polly import parse_patch_file
from .polly import resolve_position
from pathlib import Path
from ..task.util import *
def read_insertion(action, src):
position = resolve_position(action["at"], src)
return {"content": action["content"], "pos": position}
def process_patch_file(patch_file: str, check_date: bool = True):
patches = parse_patch_file(patch_file)
for patch in patches:
target_src = EXTRACTED_DIR / patch["target"]
target_dest = PATCHED_RSC_DIR / patch["target"]
# Skip old patches
if check_date and target_dest.exists() and target_dest.stat().st_mtime > patch["timestamp"]:
print(f"Skipping patch {patch['target']}...")
continue
print(f"Patching {patch['target']} with {len(patch['actions'])} actions")
# Read the source of the file
with open(target_src, 'r') as f:
src = f.read()
# Resolve the actual char locations in the patches
insertions = [read_insertion(action, src) for action in patch["actions"]]
insertions = [x for x in insertions if x is not None]
for insertion in insertions:
src = src[:insertion["pos"]] + insertion["content"] + src[insertion["pos"]:]
# Correct insertions that follow this one
for i2 in insertions:
# Only update insertions that come *after* this one
if i2 == insertion or i2["pos"] < insertion["pos"]:
continue
i2["pos"] += len(insertion["content"])
# Write the changed output
with open(target_dest, 'w') as f:
f.write(src)