Barebones patching system

This commit is contained in:
Your Name 2024-08-17 19:38:23 +02:00
parent e8ffddf93f
commit f2ada0e2fe
6 changed files with 62 additions and 20 deletions

15
.vscode/launch.json vendored Normal file
View file

@ -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"
}
]
}

View file

@ -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]
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)

View file

@ -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.")

View file

@ -1,12 +1,16 @@
file 'res/values/public.xml'
insert ln17595 << @end
<!-- Ykit -->
<public type="drawable" name="oval_yellow" id="0x7f08f001" /> <!-- YKit-BringBackPhoebe -->
<public type="id" name="ykit_settings" id="0x7f0bf001" /> <!-- YKit-Settings -->
<public type="id" name="ykit_version" id="0x7f0bf003" /> <!-- YKit-Settings -->
<public type="id" name="text_color_yellow" id="0x7f0bf002" /> <!-- YKit-BringBackPhoebe -->
<public type="layout" name="activity_ykit_settings" id="0x7f0ef001" /> <!-- YKit-Settings -->
<public type="raw" name="ykit_meow" id="0x7f12f001" /> <!-- YKit-Settings -->
@end
#17595

View file

@ -6817,7 +6817,6 @@
<public type="drawable" name="oval_pink_glow" id="0x7f080750" />
<public type="drawable" name="oval_purple" id="0x7f080751" />
<public type="drawable" name="oval_red" id="0x7f080752" />
<public type="drawable" name="overlay" id="0x7f080754" />
<public type="drawable" name="overlay_black" id="0x7f080755" />
<public type="drawable" name="pause_button" id="0x7f080756" />
@ -7851,8 +7850,6 @@
<public type="id" name="account_row_tag" id="0x7f0b0034" />
<public type="id" name="account_row_viewholder_tag" id="0x7f0b0035" />
<public type="id" name="account_settings" id="0x7f0b0036" />
<public type="id" name="action" id="0x7f0b0037" />
<public type="id" name="action0" id="0x7f0b0038" />
<public type="id" name="actionDone" id="0x7f0b0039" />
@ -10820,7 +10817,6 @@
<public type="id" name="text_color_pink" id="0x7f0b0bcb" />
<public type="id" name="text_color_purple" id="0x7f0b0bcc" />
<public type="id" name="text_color_red" id="0x7f0b0bcd" />
<public type="id" name="text_commercial" id="0x7f0b0bce" />
<public type="id" name="text_count" id="0x7f0b0bcf" />
<public type="id" name="text_editing_controls" id="0x7f0b0bd0" />
@ -11525,7 +11521,6 @@
<public type="layout" name="activity_tip_jar_setup_complete" id="0x7f0e0039" />
<public type="layout" name="activity_video_hub" id="0x7f0e003a" />
<public type="layout" name="activity_webview" id="0x7f0e003b" />
<public type="layout" name="ad_dialog" id="0x7f0e003c" />
<public type="layout" name="ad_free_prompt" id="0x7f0e003d" />
<public type="layout" name="ad_settings_popup_window" id="0x7f0e003e" />
@ -12554,7 +12549,6 @@
<public type="raw" name="messaging_notification" id="0x7f12000b" />
<public type="raw" name="messaging_receive" id="0x7f12000c" />
<public type="raw" name="messaging_send_click" id="0x7f12000d" />
<public type="raw" name="notification_algo_push" id="0x7f12000e" />
<public type="raw" name="omsdk_v1" id="0x7f12000f" />
<public type="raw" name="premium_payment_method_tumblrpay" id="0x7f120010" />

3
test.py Normal file
View file

@ -0,0 +1,3 @@
from buildtool.patcher.filepatcher import process_patch_file
process_patch_file('src/patches/public.patch', check_date=True)