45 lines
2.2 KiB
Python
45 lines
2.2 KiB
Python
"""Generate current command names from a local PearlSR checkout; no network I/O."""
|
|||
|
|
import argparse
|
||
|
|
import pathlib
|
||
|
|
import re
|
||
|
|
import subprocess
|
||
|
|
|
||
|
|
parser = argparse.ArgumentParser(description=__doc__)
|
||
|
|
parser.add_argument("upstream", type=pathlib.Path)
|
||
|
|
args = parser.parse_args()
|
||
|
|
checkout = args.upstream.resolve()
|
||
|
|
revision = subprocess.check_output(
|
||
|
|
["git", "-C", str(checkout), "rev-parse", "HEAD"], text=True
|
||
|
|
).strip()
|
||
|
|
source = (checkout / "protocol/src/root.zig").read_text(encoding="utf-8")
|
||
|
|
enum = source.split("pub const CmdID = enum(u16) {", 1)[1].split("};", 1)[0]
|
||
|
|
commands = re.findall(r"\bCmd(\w+)\s*=\s*(\d+)\s*,", enum)
|
||
|
|
if not commands or len({name for name, _ in commands}) != len(commands):
|
||
|
|
raise SystemExit("Missing or duplicate upstream command names")
|
||
|
|
if len({int(value) for _, value in commands}) != len(commands):
|
||
|
|
raise SystemExit("Duplicate upstream command IDs")
|
||
|
|
lines = [
|
||
|
|
"// Code generated by tools/sync_protocol_commands.py. DO NOT EDIT.",
|
||
|
|
"// Source: https://git.xeondev.com/HonkaiSlopRail/pearl-sr protocol/src/root.zig",
|
||
|
|
"// Revision: " + revision,
|
||
|
|
"package proto", "",
|
||
|
|
'const CommandSourceRevision = "' + revision + '"', "",
|
||
|
|
"var upstreamCmdIDByName = map[string]uint16{",
|
||
|
|
]
|
||
|
|
lines += [f'\t"{name}": {value},' for name, value in commands]
|
||
|
|
lines += ["}", "", "func init() {",
|
||
|
|
"\tfor name, id := range upstreamCmdIDByName {",
|
||
|
|
"\t\tif previous, ok := CmdIDByName[name]; ok && previous != id {",
|
||
|
|
'\t\t\tpanic("command ID conflict between schema and upstream: " + name)',
|
||
|
|
"\t\t}", "\t\tCmdIDByName[name] = id", "\t\tNameByCmdID[id] = name",
|
||
|
|
"\t}", "}", ""]
|
||
|
|
root = pathlib.Path(__file__).resolve().parents[1]
|
||
|
|
base_source = (root / "protocol/proto/cmdid.go").read_text(encoding="utf-8")
|
||
|
|
base_commands = {n: int(v) for n, v in re.findall(r'^\s*"(\w+)":\s*(\d+),', base_source, re.M)}
|
||
|
|
conflicts = [n for n, v in commands if n in base_commands and base_commands[n] != int(v)]
|
||
|
|
if conflicts:
|
||
|
|
raise SystemExit("Update the base schema command IDs first: " + ", ".join(conflicts))
|
||
|
|
target = root / "protocol/proto/upstream_cmdids.go"
|
||
|
|
target.write_text("\n".join(lines), encoding="utf-8")
|
||
|
|
subprocess.run(["gofmt", "-w", str(target)], check=True)
|
||
|
|
print(f"Generated {len(commands)} commands from {revision}")
|