from __future__ import annotations from pathlib import Path from typing import Any from .fsutil import sha256_file from .models import Lockfile, Registry from .planner import _find_asset def check_lock( *, instance: str, registry: Registry, lockfile: Lockfile, state_root: Path, repo_root: Path, ) -> dict[str, Any]: entries: list[dict[str, Any]] = [] summary = {"ok": 0, "warnings": 0, "errors": 0} for locked in lockfile.plugins: registry_plugin = registry.get(locked.id) strategy = locked.install_strategy or (registry_plugin.install_strategy if registry_plugin else "manual") messages: list[dict[str, str]] = [] if not registry_plugin: messages.append({"level": "warning", "message": "missing registry entry"}) if strategy == "manual": messages.append({"level": "error", "message": "manual install strategy cannot be applied"}) if not locked.asset: messages.append({"level": "error", "message": "missing asset"}) else: asset_path = _find_asset(locked.asset, state_root, instance, repo_root, locked.id) if not asset_path: messages.append({"level": "error", "message": "asset not found in downloads or repo assets"}) elif locked.sha256 and sha256_file(asset_path) != locked.sha256: messages.append({"level": "error", "message": "asset sha256 mismatch"}) if any(message["level"] == "error" for message in messages): status = "error" summary["errors"] += 1 elif messages: status = "warning" summary["warnings"] += 1 else: status = "ok" summary["ok"] += 1 entries.append( { "id": locked.id, "repo": locked.repo or (registry_plugin.repo if registry_plugin else None), "tag": locked.tag, "asset": locked.asset, "installStrategy": strategy, "status": status, "messages": messages, } ) return { "instance": instance, "beatSaberVersion": lockfile.beat_saber_version, "summary": summary, "plugins": entries, }