48 lines
1.7 KiB
Python
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) |