diff --git a/.vscode/launch.json b/.vscode/launch.json
new file mode 100644
index 0000000..b180193
--- /dev/null
+++ b/.vscode/launch.json
@@ -0,0 +1,15 @@
+{
+ // Use IntelliSense to learn about possible attributes.
+ // Hover to view descriptions of existing attributes.
+ // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
+ "version": "0.2.0",
+ "configurations": [
+ {
+ "name": "Python Debugger: Current File",
+ "type": "debugpy",
+ "request": "launch",
+ "program": "test.py",
+ "console": "integratedTerminal"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/buildtool/patcher/filepatcher.py b/buildtool/patcher/filepatcher.py
index 77d8656..6f9efad 100644
--- a/buildtool/patcher/filepatcher.py
+++ b/buildtool/patcher/filepatcher.py
@@ -1,26 +1,48 @@
-from polly import parse_patch_file
-from polly import parse_location
+from .polly import parse_patch_file
+from .polly import resolve_position
from pathlib import Path
from ..task.util import *
-def read_insertion(action, patch_file):
- with open(patch_file, 'r') as f:
- src = f.read()
- location = parse_location(action["at"], src)
+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_dest = (PATCHED_RSC_DIR / patch["target"])
+ 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"]:
- # Patch skipped
+ print(f"Skipping patch {patch['target']}...")
continue
- insertions = [read_insertion(action) for action in patch["actions"]]
+ 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]
-
\ No newline at end of file
+ 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)
\ No newline at end of file
diff --git a/buildtool/patcher/polly.py b/buildtool/patcher/polly.py
index b6011a2..948e4f7 100644
--- a/buildtool/patcher/polly.py
+++ b/buildtool/patcher/polly.py
@@ -30,22 +30,26 @@ def parse_location(location: Token):
m = re.match(r"ln([0-9]+)(?:c([0-9]+))?", location.value)
if m:
ln, col = m.groups()
- return {"type": "lncol", "line": ln, "column": col}
+ return {"type": "lncol", "line": int(ln), "column": int(col) if col else 0}
m = re.match(r"ch([0-9]+)", location.value)
if m:
ch = m.groups()[0]
- return {"type": "char", "index": ch}
+ return {"type": "char", "index": int(ch)}
raise RuntimeError("Cannot parse location")
-def absolute_location(location, src: str):
+def resolve_position(location, src: str):
if location["type"] == "char":
return location["index"]
elif location["type"] == "lncol":
j = 0
for i, x in enumerate(src.split('\n')):
- if i ==
+ if (i+1) == location["line"]:
+ if location["column"] > len(x):
+ print(f"Cannot insert at line {location['line']} column {location['column']}. The line is not that long.")
+ exit(-1)
+ return j + location["column"]
j += len(x) + 1
print(f"Cannot insert at line {location['line']}. The file is not long enough.")
diff --git a/src/patches/public.patch b/src/patches/public.patch
index ce3524f..730ed5c 100644
--- a/src/patches/public.patch
+++ b/src/patches/public.patch
@@ -1,12 +1,16 @@
file 'res/values/public.xml'
insert ln17595 << @end
+
+
+
+
@end
#17595
\ No newline at end of file
diff --git a/src/patches/public.xml b/src/patches/public.xml
index d98e644..e84d585 100644
--- a/src/patches/public.xml
+++ b/src/patches/public.xml
@@ -6817,7 +6817,6 @@
-
@@ -7851,8 +7850,6 @@
-
-
@@ -10820,7 +10817,6 @@
-
@@ -11525,7 +11521,6 @@
-
@@ -12554,7 +12549,6 @@
-
diff --git a/test.py b/test.py
new file mode 100644
index 0000000..1458932
--- /dev/null
+++ b/test.py
@@ -0,0 +1,3 @@
+from buildtool.patcher.filepatcher import process_patch_file
+
+process_patch_file('src/patches/public.patch', check_date=True)
\ No newline at end of file