mirror of
https://github.com/Shu-Ying/main_plugin_farm.git
synced 2026-10-30 14:20:01 +08:00
update # 初始化仓库
This commit is contained in:
@@ -0,0 +1,117 @@
|
||||
"""Validate the preserved legacy source without starting a bot."""
|
||||
|
||||
import argparse
|
||||
import ast
|
||||
from contextlib import closing
|
||||
import hashlib
|
||||
import json
|
||||
from pathlib import Path, PurePosixPath
|
||||
import sqlite3
|
||||
import sys
|
||||
|
||||
|
||||
def check(root):
|
||||
manifest = json.loads(
|
||||
(root / "docs/legacy-manifest.json").read_text(encoding="utf-8")
|
||||
)
|
||||
if manifest.get("schema") != "farm.legacy-baseline.v1":
|
||||
raise ValueError("Unsupported baseline manifest schema")
|
||||
baseline = (root / manifest["destination"]).resolve()
|
||||
if not baseline.is_relative_to(root.resolve()):
|
||||
raise ValueError("Baseline destination escapes repository")
|
||||
errors = []
|
||||
expected = set()
|
||||
python_count = 0
|
||||
json_count = 0
|
||||
for entry in manifest["files"]:
|
||||
name = entry["path"]
|
||||
relative = PurePosixPath(name)
|
||||
if relative.is_absolute() or ".." in relative.parts:
|
||||
raise ValueError("Invalid manifest path")
|
||||
if name in expected:
|
||||
raise ValueError("Duplicate manifest path")
|
||||
expected.add(name)
|
||||
path = (baseline / name).resolve()
|
||||
if not path.is_relative_to(baseline):
|
||||
raise ValueError("Manifest path escapes baseline")
|
||||
if not path.is_file():
|
||||
errors.append({"path": name, "error": "missing file"})
|
||||
continue
|
||||
content = path.read_bytes()
|
||||
digest = hashlib.sha256(content).hexdigest()
|
||||
if digest != entry["copied_sha256"]:
|
||||
errors.append({"path": name, "error": "SHA-256 mismatch"})
|
||||
if len(content) != entry["bytes"]:
|
||||
errors.append({"path": name, "error": "size mismatch"})
|
||||
if path.suffix == ".py":
|
||||
python_count += 1
|
||||
try:
|
||||
ast.parse(content, filename=name, feature_version=(3, 10))
|
||||
except SyntaxError as exc:
|
||||
errors.append(
|
||||
{"path": name, "error": "syntax", "line": exc.lineno}
|
||||
)
|
||||
if path.suffix == ".json":
|
||||
json_count += 1
|
||||
try:
|
||||
json.loads(content)
|
||||
except (ValueError, UnicodeError):
|
||||
errors.append({"path": name, "error": "invalid JSON"})
|
||||
actual = {
|
||||
path.relative_to(baseline).as_posix()
|
||||
for path in baseline.rglob("*")
|
||||
if path.is_file()
|
||||
and "__pycache__" not in path.parts
|
||||
and path.suffix != ".pyc"
|
||||
}
|
||||
for name in sorted(actual - expected):
|
||||
errors.append({"path": name, "error": "unmanifested file"})
|
||||
catalogues = []
|
||||
for name in ("plant.db", "plant-test.db"):
|
||||
path = baseline / "resource/db" / name
|
||||
with closing(
|
||||
sqlite3.connect(
|
||||
path.resolve().as_uri() + "?mode=ro", uri=True
|
||||
)
|
||||
) as connection:
|
||||
integrity = connection.execute("PRAGMA quick_check").fetchone()[0]
|
||||
tables = sorted(
|
||||
row[0]
|
||||
for row in connection.execute(
|
||||
"SELECT name FROM sqlite_master WHERE type='table'"
|
||||
)
|
||||
)
|
||||
if integrity != "ok" or tables != ["plant", "sqlite_sequence"]:
|
||||
errors.append({"path": name, "error": "unexpected catalogue"})
|
||||
catalogues.append(
|
||||
{"name": name, "quick_check": integrity, "tables": tables}
|
||||
)
|
||||
return {
|
||||
"status": "passed" if not errors else "failed",
|
||||
"files": len(expected),
|
||||
"python_syntax_files": python_count,
|
||||
"json_files": json_count,
|
||||
"catalogues": catalogues,
|
||||
"errors": errors,
|
||||
"scope": "integrity and syntax only; no host or gameplay verified",
|
||||
}
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument(
|
||||
"--root",
|
||||
type=Path,
|
||||
default=Path(__file__).resolve().parents[1],
|
||||
)
|
||||
args = parser.parse_args()
|
||||
try:
|
||||
result = check(args.root.resolve())
|
||||
except (OSError, ValueError, KeyError, sqlite3.Error) as exc:
|
||||
result = {"status": "failed", "error_type": type(exc).__name__}
|
||||
print(json.dumps(result, ensure_ascii=False, indent=2))
|
||||
return 0 if result["status"] == "passed" else 1
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
Reference in New Issue
Block a user