#!/usr/bin/env python3 """CLI: restore files from backup after failed post-update health check.""" from __future__ import annotations import argparse import json import sys from pathlib import Path ROOT = Path(__file__).resolve().parent.parent if str(ROOT) not in sys.path: sys.path.insert(0, str(ROOT)) from app.services.update_rollback import restore_from_backup from app.services.update_state_store import mark_rolled_back, read_update_state def _pending_path(base: Path) -> Path: return base / "data" / ".pending_restart.json" def main() -> int: parser = argparse.ArgumentParser(description="Rollback WESP from OTA backup") parser.add_argument("--root", type=Path, default=ROOT) args = parser.parse_args() base = args.root.resolve() state = read_update_state(str(base)) backup_path = state.get("backup_path") previous_version = state.get("previous_version") or "?" pending = _pending_path(base) if pending.is_file(): try: data = json.loads(pending.read_text(encoding="utf-8")) if isinstance(data, dict): backup_path = backup_path or data.get("backup_path") previous_version = data.get("previous_version") or previous_version except json.JSONDecodeError: pass if not backup_path: print("rollback_update: no backup_path in state", file=sys.stderr) return 1 if not restore_from_backup(str(base), str(backup_path)): return 1 mark_rolled_back( str(base), previous_version=str(previous_version), message=f"Обновление отменено, восстановлена версия {previous_version}", ) try: pending.unlink(missing_ok=True) except OSError: pass print(f"rollback_update: restored from {backup_path}") return 0 if __name__ == "__main__": raise SystemExit(main())