Refuse to write a bundle whose parens we unbalanced
Commit47cdf72shipped a pattern that matched one closing paren and emitted one, netting an extra `)` in the Angular bundle: c(2,"filterByProviders",["STORJ_IX","S3","B2"]))("required",!0) ^^ syntax error The TrueNAS web UI went blank. Worse, MARKER was now present in the file, so every later run reported "already patched" and skipped -- the patch could not heal itself, and the bundle had to be hand-restored from the .pre-truecloud-patch backup. patch_ui.py now compares the parenthesis balance before and after substitution and refuses to write if it changed. A bundle we cannot patch correctly is left exactly as it was: an unpatched UI is a missing dropdown entry, a corrupted one is a dead web UI. Tests cover the real regression (verbatim47cdf72pattern) end to end: it still matches, the balance still shifts, main() refuses, and the file on disk is byte-for-byte unchanged. README documents the manual recovery for anyone who already hit it. 93 tests, ruff and shellcheck clean.
This commit is contained in:
@@ -65,6 +65,11 @@ def _match_pattern(content):
|
||||
return None, None
|
||||
|
||||
|
||||
def _paren_delta(s):
|
||||
"""Net parenthesis balance. Patching must not change it — see main()."""
|
||||
return s.count("(") - s.count(")")
|
||||
|
||||
|
||||
def find_bundle():
|
||||
"""
|
||||
Search WEBUI_CANDIDATES for the JS chunk containing the filterByProviders
|
||||
@@ -135,6 +140,24 @@ def main():
|
||||
)
|
||||
return
|
||||
|
||||
# Never write JS whose parentheses we have unbalanced. A pattern that eats one
|
||||
# paren too many is a syntax error in the bundle and the entire TrueNAS web UI
|
||||
# goes blank -- and because MARKER is then present, every later run reports
|
||||
# "already patched" and skips, so the patch cannot heal itself. Recovery means
|
||||
# hand-restoring the .pre-truecloud-patch backup.
|
||||
#
|
||||
# This is not hypothetical: it shipped once. Refuse instead.
|
||||
if _paren_delta(patched) != _paren_delta(content):
|
||||
print(
|
||||
"[truecloud-patch] ERROR: the replacement would unbalance the bundle's "
|
||||
"parentheses — refusing to write.\n"
|
||||
"[truecloud-patch] The UI is UNCHANGED and still works. This means the "
|
||||
"pattern no longer fits this TrueNAS build.\n"
|
||||
"[truecloud-patch] File an issue at "
|
||||
"https://github.com/sudolulo/truenas-truecloud-patch"
|
||||
)
|
||||
return
|
||||
|
||||
tmp = path + ".tmp"
|
||||
try:
|
||||
with open(tmp, "w", encoding="utf-8") as fh:
|
||||
|
||||
Reference in New Issue
Block a user