#!/usr/bin/env python3 # -*- coding: utf-8 -*- """M11b-3 代码镜像同步器:modules/world_sync/ 是唯一真源, apps/scense/pkgs/world_sync/ 是打包镜像(宿主 build.sh 从应用仓库安装,禁止手工双写)。 与 sync_models_to_app.py(只管 models/)互补,本脚本同步 **Python 包与测试**: - world_sync/*.py(包源码,含 pbl_runtime_broadcast.py) - tests/*.py(含 test_m11b3_post_commit_broadcast.py) - skill/SKILL.md、README.md 用法: python modules/world_sync/scripts/sync_code_to_app.py # 同步 python modules/world_sync/scripts/sync_code_to_app.py --check # 只校验 sha256 行为:逐文件以同一份字节覆盖镜像落点,打印两两 sha256 比对;--check 不一致退出码 1。 """ from __future__ import annotations import argparse import hashlib import os import sys HERE = os.path.dirname(os.path.abspath(__file__)) WS_ROOT = os.path.abspath(os.path.join(HERE, "..", "..", "..")) SRC_ROOT = os.path.join("modules", "world_sync") DST_ROOT = os.path.join("apps", "scense", "pkgs", "world_sync") #: 需要镜像的相对路径(真源 = modules/world_sync/) MIRROR_SUBDIRS = ("world_sync", "tests") MIRROR_FILES = ("README.md", os.path.join("skill", "SKILL.md")) #: 不同步的产物/缓存 SKIP_SUFFIX = ("__pycache__", ".pyc", ".egg-info", ".pytest_cache") def sha256_of(path: str) -> str: h = hashlib.sha256() with open(path, "rb") as fh: for chunk in iter(lambda: fh.read(65536), b""): h.update(chunk) return h.hexdigest() def collect() -> list: rels = [] for sub in MIRROR_SUBDIRS: base = os.path.join(SRC_ROOT, sub) if not os.path.isdir(base): continue for name in sorted(os.listdir(base)): if any(s in name for s in SKIP_SUFFIX): continue if not name.endswith(".py"): continue rels.append(os.path.join(sub, name)) for rel in MIRROR_FILES: if os.path.isfile(os.path.join(SRC_ROOT, rel)): rels.append(rel) return rels def main() -> int: ap = argparse.ArgumentParser() ap.add_argument("--check", action="store_true", help="只校验,不写入") args = ap.parse_args() bad = 0 for rel in collect(): src = os.path.join(WS_ROOT, SRC_ROOT, rel) dst = os.path.join(WS_ROOT, DST_ROOT, rel) src_sha = sha256_of(src) same = os.path.isfile(dst) and sha256_of(dst) == src_sha if args.check: print("%-58s %s" % (rel, "OK" if same else "DRIFT")) if not same: bad += 1 continue os.makedirs(os.path.dirname(dst), exist_ok=True) with open(src, "rb") as fh: data = fh.read() with open(dst, "wb") as fh: fh.write(data) ok = sha256_of(dst) == src_sha print("%-58s %s sha256=%s" % (rel, "SYNCED" if ok else "FAIL", src_sha[:12])) if not ok: bad += 1 if bad: print("RESULT: FAIL (%d 项不一致)" % bad) return 1 print("RESULT: PASS (镜像与真源逐文件 sha256 一致)") return 0 if __name__ == "__main__": sys.exit(main())