"""从指定旧仓库和现有迁移 SQL 生成可复核的迁移清单,不访问数据库。""" import argparse import hashlib import json import re import subprocess from pathlib import Path def git(repo, *args): return subprocess.check_output(["git", "-C", str(repo), *args], text=True, encoding="utf-8").strip() def main(): parser = argparse.ArgumentParser(description=__doc__) parser.add_argument("--source", required=True, type=Path) parser.add_argument("--baseline", default="d31082f4a7816d4c83544b8f54e6f42a3b2132b1") args = parser.parse_args() root = Path(__file__).resolve().parents[1] source = args.source.resolve() sql = (root / "docs/sw6-to-kra/sw_to_kra_migrate.sql").read_text(encoding="utf-8") contracts = [dict(zip(("method", "source_path", "target_path", "permission", "controller"), row)) for row in re.findall(r"\('(GET|POST|PUT|DELETE)','([^']+)','([^']+)','([^']+)','([^']+)'\)", sql)] changes = [] for path in git(source, "diff", "--name-only", args.baseline, "main").splitlines(): # 只登记路径与摘要,不把旧配置中的凭据写入新仓库。 if not (path.endswith(".java") or "/mapper/" in path and path.endswith(".xml")): continue file = source / path changes.append({"path": path, "exists": file.is_file(), "sha256": hashlib.sha256(file.read_bytes()).hexdigest() if file.is_file() else None}) custom = [] for file in sorted((source / "ruoyi-admin/src/main/java").rglob("*Controller.java")): text = file.read_text(encoding="utf-8") if file.name == "ForgotPasswordController.java": custom.append({"path": file.relative_to(source).as_posix(), "source": text}) result = {"baseline": args.baseline, "backend_head": git(source, "rev-parse", "main"), "frontend_head": git(source / "web", "rev-parse", "dev/dev1.0"), "contracts": contracts, "changed_sources": changes, "additional_controllers": [item["path"] for item in custom]} target = root / "docs/sw6-to-kra/source-inventory.json" target.write_text(json.dumps(result, ensure_ascii=False, indent=2) + "\n", encoding="utf-8") print(f"已登记 {len(contracts)} 个 SQL 接口契约、{len(changes)} 个变更源文件。") if __name__ == "__main__": main()