📦 deps(thirdparty): update snapshots

This commit is contained in:
ci[bot]
2026-08-31 05:00:46 +08:00
parent 8fea3d18fe
commit 0b2b056032
347 changed files with 38446 additions and 136 deletions
@@ -0,0 +1,85 @@
#!/usr/bin/env python3
"""apply_skill_patch.py — 最小补丁事务:快照 → 覆盖补丁文件 → 校验 → 可回滚(Phase 2B/3)。
repair/update 的落盘环节。补丁是"文件覆盖层"(patch 目录里的文件按相对路径覆盖目标),
不做自由重写;应用前自动快照,校验失败自动回滚。
用法:
python3 scripts/apply_skill_patch.py apply --target <skill-dir> --patch-dir <dir> --snapshots <dir>
python3 scripts/apply_skill_patch.py restore --target <skill-dir> --snapshot <snapshot-dir>
"""
from __future__ import annotations
import argparse
import shutil
import subprocess
import sys
from pathlib import Path
sys.path.insert(0, str(Path(__file__).parent))
from cangjie_common import WriterLock, snapshot_dir # noqa: E402
SCRIPTS = Path(__file__).parent
def apply_patch(target: Path, patch_dir: Path, snapshots: Path) -> int:
patch_files = [p for p in patch_dir.rglob("*") if p.is_file()]
if not patch_files:
raise SystemExit(f"补丁目录为空: {patch_dir}")
with WriterLock(target):
snap = snapshot_dir(target, snapshots, "pre-patch")
print(f"已快照: {snap}")
diff_lines = []
for pf in patch_files:
rel = pf.relative_to(patch_dir)
dest = target / rel
old = dest.read_text(encoding="utf-8") if dest.exists() else ""
new = pf.read_text(encoding="utf-8")
diff_lines.append(f"### {rel}: {'修改' if dest.exists() else '新增'}{len(old)}{len(new)} 字符)")
dest.parent.mkdir(parents=True, exist_ok=True)
shutil.copyfile(pf, dest)
check = subprocess.run([sys.executable, str(SCRIPTS / "validate_skill_pack.py"), str(target)],
capture_output=True, text=True)
if check.returncode != 0:
shutil.rmtree(target)
shutil.copytree(snap, target)
print(check.stdout + check.stderr)
raise SystemExit("[rollback] 补丁后校验失败,已自动恢复快照")
print("\n".join(diff_lines))
print(f"补丁已应用并通过校验({len(patch_files)} 个文件)。回滚: apply_skill_patch.py restore --snapshot {snap}")
return 0
def restore(target: Path, snapshot: Path) -> int:
if not snapshot.is_dir():
raise SystemExit(f"快照不存在: {snapshot}")
with WriterLock(target):
if target.exists():
shutil.rmtree(target)
shutil.copytree(snapshot, target)
print(f"已恢复 {target}{snapshot}")
return 0
def main() -> int:
ap = argparse.ArgumentParser(description=__doc__)
sub = ap.add_subparsers(dest="mode", required=True)
a = sub.add_parser("apply")
a.add_argument("--target", required=True)
a.add_argument("--patch-dir", required=True)
a.add_argument("--snapshots", required=True)
r = sub.add_parser("restore")
r.add_argument("--target", required=True)
r.add_argument("--snapshot", required=True)
args = ap.parse_args()
if args.mode == "apply":
return apply_patch(Path(args.target), Path(args.patch_dir), Path(args.snapshots))
return restore(Path(args.target), Path(args.snapshot))
if __name__ == "__main__":
raise SystemExit(main())