|
| 1 | +#!/usr/bin/env python3 |
| 2 | +"""Apply hook metadata fixes for PR #2131 review feedback.""" |
| 3 | + |
| 4 | +from __future__ import annotations |
| 5 | + |
| 6 | +import json |
| 7 | +import re |
| 8 | +import sys |
| 9 | +from pathlib import Path |
| 10 | + |
| 11 | +sys.path.insert(0, str(Path(__file__).resolve().parent)) |
| 12 | + |
| 13 | +from hook_utils import ( # noqa: E402 |
| 14 | + HOOK_INDEX_PATH, |
| 15 | + REPO_ROOT, |
| 16 | + Occurrence, |
| 17 | + fix_smarty_semicolons, |
| 18 | + format_files_yaml, |
| 19 | + format_hook_aliases_yaml, |
| 20 | + git_show_upstream, |
| 21 | + infer_hook_type, |
| 22 | + load_scope_files, |
| 23 | + parse_title_from_front_matter, |
| 24 | + parse_type_from_front_matter, |
| 25 | + replace_call_snippet, |
| 26 | + replace_files_block, |
| 27 | + replace_hook_aliases_block, |
| 28 | + replace_type, |
| 29 | + restore_protected_scalar_fields, |
| 30 | + split_front_matter, |
| 31 | +) |
| 32 | + |
| 33 | +REMOVED_HOOKS = {"actionBeforeAjaxDie"} |
| 34 | + |
| 35 | + |
| 36 | +def load_index() -> dict: |
| 37 | + return json.loads(HOOK_INDEX_PATH.read_text(encoding="utf-8")) |
| 38 | + |
| 39 | + |
| 40 | +def occurrences_from_index(entry: dict) -> list[Occurrence]: |
| 41 | + seen_files: set[tuple[str, str]] = set() |
| 42 | + result: list[Occurrence] = [] |
| 43 | + for item in entry.get("occurrences", []): |
| 44 | + key = (item["repo"], item["file"]) |
| 45 | + if key in seen_files: |
| 46 | + continue |
| 47 | + seen_files.add(key) |
| 48 | + result.append( |
| 49 | + Occurrence( |
| 50 | + repo=item["repo"], |
| 51 | + file=item["file"], |
| 52 | + line=item["line"], |
| 53 | + snippet=item["snippet"], |
| 54 | + ) |
| 55 | + ) |
| 56 | + return result |
| 57 | + |
| 58 | + |
| 59 | +def fix_page(path: Path, index: dict) -> str | None: |
| 60 | + rel = path.relative_to(REPO_ROOT).as_posix() |
| 61 | + text = path.read_text(encoding="utf-8") |
| 62 | + fm, body = split_front_matter(text) |
| 63 | + if not fm: |
| 64 | + return None |
| 65 | + |
| 66 | + hook_name = parse_title_from_front_matter(fm) |
| 67 | + if not hook_name: |
| 68 | + return None |
| 69 | + |
| 70 | + entry = index.get(hook_name, {}) |
| 71 | + if hook_name in REMOVED_HOOKS and not entry.get("occurrences"): |
| 72 | + return "DELETE" |
| 73 | + |
| 74 | + upstream_text = git_show_upstream(rel) or "" |
| 75 | + upstream_fm, upstream_body = ( |
| 76 | + split_front_matter(upstream_text) if upstream_text else ("", "") |
| 77 | + ) |
| 78 | + |
| 79 | + aliases = entry.get("aliases", []) |
| 80 | + occurrences = occurrences_from_index(entry) |
| 81 | + |
| 82 | + updated_fm = fm |
| 83 | + updated_fm = replace_hook_aliases_block( |
| 84 | + updated_fm, format_hook_aliases_yaml(aliases, upstream_fm) |
| 85 | + ) |
| 86 | + |
| 87 | + upstream_type = parse_type_from_front_matter(upstream_fm or fm) |
| 88 | + hook_type = infer_hook_type(hook_name, upstream_type or None) |
| 89 | + if hook_type: |
| 90 | + updated_fm = replace_type(updated_fm, hook_type) |
| 91 | + |
| 92 | + updated_fm = restore_protected_scalar_fields(updated_fm, upstream_fm, ["hookTitle"]) |
| 93 | + updated_fm = replace_files_block( |
| 94 | + updated_fm, format_files_yaml(occurrences, upstream_fm) |
| 95 | + ) |
| 96 | + |
| 97 | + updated_body = body |
| 98 | + if occurrences: |
| 99 | + updated_body = replace_call_snippet(updated_body, occurrences[0].snippet) |
| 100 | + elif upstream_body: |
| 101 | + call_match = re.search( |
| 102 | + r"## Call of the Hook in the origin file\n\n```php\n(.*?)\n```", |
| 103 | + upstream_body, |
| 104 | + re.DOTALL, |
| 105 | + ) |
| 106 | + if call_match: |
| 107 | + updated_body = replace_call_snippet( |
| 108 | + updated_body, call_match.group(1).strip() |
| 109 | + ) |
| 110 | + |
| 111 | + updated_body = fix_smarty_semicolons(updated_body) |
| 112 | + return updated_fm + updated_body |
| 113 | + |
| 114 | + |
| 115 | +def main() -> int: |
| 116 | + if not HOOK_INDEX_PATH.exists(): |
| 117 | + print("Run build_hook_index.py first.", file=sys.stderr) |
| 118 | + return 1 |
| 119 | + |
| 120 | + index = load_index() |
| 121 | + changed = 0 |
| 122 | + deleted = 0 |
| 123 | + |
| 124 | + for path in load_scope_files(): |
| 125 | + if not path.exists(): |
| 126 | + continue |
| 127 | + result = fix_page(path, index) |
| 128 | + if result == "DELETE": |
| 129 | + path.unlink() |
| 130 | + deleted += 1 |
| 131 | + print(f"deleted {path.name}") |
| 132 | + continue |
| 133 | + if not result: |
| 134 | + continue |
| 135 | + original = path.read_text(encoding="utf-8") |
| 136 | + if result != original: |
| 137 | + path.write_text(result, encoding="utf-8") |
| 138 | + changed += 1 |
| 139 | + |
| 140 | + print(f"Updated {changed} files, deleted {deleted} files") |
| 141 | + return 0 |
| 142 | + |
| 143 | + |
| 144 | +if __name__ == "__main__": |
| 145 | + raise SystemExit(main()) |
0 commit comments