66 lines
2.3 KiB
Python
66 lines
2.3 KiB
Python
#!/usr/bin/env python3
|
|
"""根据扫描报告更新迁移台账;默认预览,显式 --apply 才写入。"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import argparse
|
|
import hashlib
|
|
import json
|
|
from datetime import date
|
|
from pathlib import Path
|
|
|
|
VALID_STATUS = {
|
|
"pending", "specified", "rewriting", "review",
|
|
"migrated", "excluded", "superseded",
|
|
}
|
|
|
|
|
|
def merge(lock: dict, report: dict) -> dict:
|
|
"""保留人工维护字段,仅同步来源提交、数量和 Skill 指纹。"""
|
|
lock.setdefault("schemaVersion", 1)
|
|
lock["updatedAt"] = date.today().isoformat()
|
|
lock.setdefault("sources", {})
|
|
lock.setdefault("skills", {})
|
|
for source in report.get("sources", []):
|
|
source_id = source["id"]
|
|
lock["sources"][source_id] = {
|
|
"commit": source.get("commit"),
|
|
"skillCount": source["skillCount"],
|
|
}
|
|
for skill in source["skills"]:
|
|
# 发布台账不保存来源名称和路径;本地扫描报告负责提供可读映射。
|
|
path_hash = hashlib.sha256(skill["relativePath"].encode("utf-8")).hexdigest()
|
|
key = f"{source_id}:{path_hash[:16]}"
|
|
current = lock["skills"].get(key, {})
|
|
status = current.get("status", "pending")
|
|
if status not in VALID_STATUS:
|
|
raise ValueError(f"非法迁移状态:{key}={status}")
|
|
lock["skills"][key] = {
|
|
**current,
|
|
"sourcePathHash": path_hash,
|
|
"sourceSha256": skill["sha256"],
|
|
"status": status,
|
|
}
|
|
return lock
|
|
|
|
|
|
def main() -> None:
|
|
parser = argparse.ArgumentParser(description="更新 Skill 迁移台账")
|
|
parser.add_argument("--lock", required=True, type=Path)
|
|
parser.add_argument("--report", required=True, type=Path)
|
|
parser.add_argument("--apply", action="store_true", help="确认写入台账")
|
|
args = parser.parse_args()
|
|
lock = json.loads(args.lock.read_text(encoding="utf-8"))
|
|
report = json.loads(args.report.read_text(encoding="utf-8"))
|
|
content = json.dumps(merge(lock, report), ensure_ascii=False, indent=2) + "\n"
|
|
if args.apply:
|
|
temporary = args.lock.with_suffix(args.lock.suffix + ".tmp")
|
|
temporary.write_text(content, encoding="utf-8")
|
|
temporary.replace(args.lock)
|
|
else:
|
|
print(content, end="")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|