so much more shit man
This commit is contained in:
parent
9e065cd638
commit
e8ffddf93f
buildtool
src/patches
|
@ -1,39 +0,0 @@
|
||||||
from lark import Lark
|
|
||||||
from lark.lexer import Token
|
|
||||||
from lark.tree import Branch
|
|
||||||
|
|
||||||
import re
|
|
||||||
|
|
||||||
def parse_string(token: Token):
|
|
||||||
if token.type == 'STRING':
|
|
||||||
string = token.value[1:-1]
|
|
||||||
string = re.sub(r"\\n","\n", string)
|
|
||||||
string = re.sub(r"\\t","\t", string)
|
|
||||||
string = re.sub(r"\\r","\r", string)
|
|
||||||
string = re.sub(r"\\(.)",r"\1", string)
|
|
||||||
return string
|
|
||||||
elif token.type == 'RAW_STRING':
|
|
||||||
string = token.value[1:-1]
|
|
||||||
return string
|
|
||||||
elif token.type == 'LONG_STRING':
|
|
||||||
string = re.match(re.compile(r"<<\s*(?P<terminator>[^\n]+)\n(.*)\n(?P=terminator)", re.MULTILINE + re.DOTALL),token.value)
|
|
||||||
assert string is not None
|
|
||||||
string = string.group(2)
|
|
||||||
return string
|
|
||||||
|
|
||||||
def process_patch(branch: Branch[Token]):
|
|
||||||
# First instruction is always file declaration
|
|
||||||
target_file = parse_string(branch.children[0].children[0]) # pyright: ignore[reportUnknownMemberType, reportArgumentType]
|
|
||||||
|
|
||||||
for inst in branch.children[1:]:
|
|
||||||
match inst.data:
|
|
||||||
case "insert":
|
|
||||||
print(f"Inserting {parse_string(inst.children[1])} at {inst.children[0]} in {target_file}")
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
lark = Lark.open('grammar.lark', rel_to=__file__)
|
|
||||||
|
|
||||||
with open('test.txt', 'r') as f:
|
|
||||||
result = lark.parse(f.read())
|
|
||||||
for patch in result.children:
|
|
||||||
process_patch(patch)
|
|
26
buildtool/patcher/filepatcher.py
Normal file
26
buildtool/patcher/filepatcher.py
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
from polly import parse_patch_file
|
||||||
|
from polly import parse_location
|
||||||
|
|
||||||
|
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 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"])
|
||||||
|
if check_date and target_dest.exists() and target_dest.stat().st_mtime > patch["timestamp"]:
|
||||||
|
# Patch skipped
|
||||||
|
continue
|
||||||
|
|
||||||
|
insertions = [read_insertion(action) for action in patch["actions"]]
|
||||||
|
insertions = [x for x in insertions if x is not None]
|
||||||
|
|
||||||
|
|
|
@ -38,4 +38,7 @@ LINE_COLUMN: /ln\d+c\d+/
|
||||||
IDENTIFIER: /[a-zA-Z_][a-zA-Z0-9_]*/
|
IDENTIFIER: /[a-zA-Z_][a-zA-Z0-9_]*/
|
||||||
PATTERN: /\/([^\/\\]|\\.)*\//
|
PATTERN: /\/([^\/\\]|\\.)*\//
|
||||||
|
|
||||||
%ignore /[\t \f\n]+/
|
COMMENT: /#[^\r\n]+/
|
||||||
|
|
||||||
|
%ignore /[\t \f\n]+/
|
||||||
|
%ignore COMMENT
|
77
buildtool/patcher/polly.py
Normal file
77
buildtool/patcher/polly.py
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
from lark import Lark
|
||||||
|
from lark.lexer import Token
|
||||||
|
from lark.tree import Branch
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
import re
|
||||||
|
|
||||||
|
from math import floor
|
||||||
|
|
||||||
|
def parse_string(token: Token):
|
||||||
|
if token.type == 'STRING':
|
||||||
|
string = token.value[1:-1]
|
||||||
|
string = re.sub(r"\\n","\n", string)
|
||||||
|
string = re.sub(r"\\t","\t", string)
|
||||||
|
string = re.sub(r"\\r","\r", string)
|
||||||
|
string = re.sub(r"\\(.)",r"\1", string)
|
||||||
|
return string
|
||||||
|
elif token.type == 'RAW_STRING':
|
||||||
|
string = token.value[1:-1]
|
||||||
|
return string
|
||||||
|
elif token.type == 'LONG_STRING':
|
||||||
|
string = re.match(re.compile(r"<<\s*(?P<terminator>[^\n]+)\n(.*)\n(?P=terminator)", re.MULTILINE + re.DOTALL),token.value)
|
||||||
|
assert string is not None
|
||||||
|
string = string.group(2)
|
||||||
|
return string
|
||||||
|
|
||||||
|
def parse_location(location: Token):
|
||||||
|
assert isinstance(location.value, str)
|
||||||
|
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}
|
||||||
|
|
||||||
|
m = re.match(r"ch([0-9]+)", location.value)
|
||||||
|
if m:
|
||||||
|
ch = m.groups()[0]
|
||||||
|
return {"type": "char", "index": ch}
|
||||||
|
|
||||||
|
raise RuntimeError("Cannot parse location")
|
||||||
|
|
||||||
|
def absolute_location(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 ==
|
||||||
|
j += len(x) + 1
|
||||||
|
|
||||||
|
print(f"Cannot insert at line {location['line']}. The file is not long enough.")
|
||||||
|
exit(-1)
|
||||||
|
|
||||||
|
def parse_patch(branch: Branch[Token], mtime: float):
|
||||||
|
# First instruction is always file declaration
|
||||||
|
target_file = parse_string(branch.children[0].children[0]) # pyright: ignore[reportUnknownMemberType, reportArgumentType]
|
||||||
|
|
||||||
|
actions = []
|
||||||
|
|
||||||
|
for inst in branch.children[1:]:
|
||||||
|
match inst.data:
|
||||||
|
case "insert":
|
||||||
|
actions.append({"type": "insert", "at": parse_location(inst.children[0]), "content": parse_string(inst.children[1])})
|
||||||
|
# print(f"Inserting {parse_string(inst.children[1])} at {inst.children[0]} in {target_file}")
|
||||||
|
|
||||||
|
return {"target": target_file, "actions": actions, "timestamp": mtime}
|
||||||
|
|
||||||
|
def parse_patch_file(file: str):
|
||||||
|
lark = Lark.open('grammar.lark', rel_to=__file__)
|
||||||
|
|
||||||
|
mtime = os.path.getmtime(file)
|
||||||
|
|
||||||
|
with open(file, 'r') as f:
|
||||||
|
result = lark.parse(f.read())
|
||||||
|
patches = [parse_patch(patch, mtime) for patch in result.children]
|
||||||
|
|
||||||
|
return patches
|
|
@ -1,7 +1,7 @@
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
import shutil
|
import shutil
|
||||||
|
|
||||||
def merge_into(src: Path | str, dest: Path | str):
|
def merge_into(src: Path | str, dest: Path | str, check_date: bool = True):
|
||||||
src = Path(src)
|
src = Path(src)
|
||||||
dest = Path(dest)
|
dest = Path(dest)
|
||||||
|
|
||||||
|
@ -13,12 +13,11 @@ def merge_into(src: Path | str, dest: Path | str):
|
||||||
dest_file = dest / src_file.relative_to(src)
|
dest_file = dest / src_file.relative_to(src)
|
||||||
|
|
||||||
# Don't update if dest is newer than source
|
# Don't update if dest is newer than source
|
||||||
if dest_file.exists() and src_file.stat().st_mtime < dest_file.stat().st_mtime:
|
if check_date and dest_file.exists() and src_file.stat().st_mtime < dest_file.stat().st_mtime:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
dest_file.parent.mkdir(parents=True, exist_ok=True)
|
dest_file.parent.mkdir(parents=True, exist_ok=True)
|
||||||
_ = shutil.copyfile(src_file, dest_file)
|
_ = shutil.copyfile(src_file, dest_file)
|
||||||
changed = True
|
changed = True
|
||||||
|
|
||||||
return changed
|
return changed
|
||||||
|
|
|
@ -9,33 +9,18 @@ from .extract import extract
|
||||||
def patch_resources():
|
def patch_resources():
|
||||||
_ = extract()
|
_ = extract()
|
||||||
|
|
||||||
# The way we merge resources is as follows:
|
first_time = False
|
||||||
# First, we copy our raw-resources from src/resources
|
|
||||||
# Second, we apply our patches, which are handled by polly
|
# Copy original resources only the first time
|
||||||
# Finally, we populate all missing entries from build/extracted
|
if not PATCHED_RSC_DIR.exists():
|
||||||
# The reason we do this is that build/extracted will always have a date greater than src/resources
|
print("Copying original resources...")
|
||||||
# until the files are modified after first build, which makes simply merging-by-date impossible.
|
shutil.copytree(EXTRACTED_DIR, PATCHED_RSC_DIR, ignore=shutil.ignore_patterns("smali*"))
|
||||||
|
first_time = True
|
||||||
s = fileutil.merge_into(SRC_RESOURCES_DIR, PATCHED_RSC_DIR)
|
|
||||||
|
s = fileutil.merge_into(SRC_RESOURCES_DIR, PATCHED_RSC_DIR, check_date=not first_time)
|
||||||
if s:
|
if s:
|
||||||
print("Copied custom resources from src/resources")
|
print("Copied custom resources from src/resources")
|
||||||
else:
|
else:
|
||||||
print("Skipped copying resources from src/resources")
|
print("Skipped copying resources from src/resources")
|
||||||
|
|
||||||
print("Copying original resources...")
|
|
||||||
for (cd, _, files) in EXTRACTED_DIR.walk():
|
|
||||||
for file in files:
|
|
||||||
# Don't copy smali code
|
|
||||||
if file.startswith("smali"):
|
|
||||||
continue
|
|
||||||
|
|
||||||
src_file = cd / file
|
|
||||||
dest_file = PATCHED_RSC_DIR / src_file.relative_to(EXTRACTED_DIR)
|
|
||||||
|
|
||||||
# Don't update if dest is newer than source
|
|
||||||
if dest_file.exists() and src_file.stat().st_mtime < dest_file.stat().st_mtime:
|
|
||||||
continue
|
|
||||||
|
|
||||||
dest_file.parent.mkdir(parents=True, exist_ok=True)
|
|
||||||
_ = shutil.copyfile(src_file, dest_file)
|
|
||||||
|
|
12
src/patches/public.patch
Normal file
12
src/patches/public.patch
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
file 'res/values/public.xml'
|
||||||
|
|
||||||
|
insert ln17595 << @end
|
||||||
|
<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
|
17601
src/patches/public.xml
Normal file
17601
src/patches/public.xml
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue