from __future__ import annotations import argparse, shutil, subprocess, tarfile, tempfile from pathlib import Path import sys ROOT=Path(__file__).resolve().parents[1] sys.path.insert(0,str(ROOT)) from sourcehub.config import Settings p=argparse.ArgumentParser() p.add_argument("--db",required=True) p.add_argument("--storage") p.add_argument("--yes-really-restore",action="store_true") a=p.parse_args() if not a.yes_really_restore: raise SystemExit("복구는 파괴적 작업입니다. --yes-really-restore를 추가하세요.") settings=Settings.from_env() if settings.database_kind=="sqlite": target=Path(settings.database_url.replace("sqlite:///","",1)) target.parent.mkdir(parents=True,exist_ok=True) shutil.copy2(a.db,target) elif settings.database_kind=="postgresql": subprocess.run(["pg_restore","--clean","--if-exists","--no-owner","--dbname",settings.database_url,a.db],check=True) else: raise SystemExit("지원하지 않는 DB backend") if a.storage: if settings.storage_backend!="local": raise SystemExit("MinIO 복구는 mc mirror/versioning 절차를 사용하세요.") with tempfile.TemporaryDirectory(prefix="sourcehub_restore_") as td: temp_root=Path(td) with tarfile.open(a.storage,"r:gz") as tar: tar.extractall(temp_root,filter="data") extracted=temp_root/"storage" if not extracted.exists(): raise SystemExit("백업 파일에 storage 디렉터리가 없습니다.") shutil.rmtree(settings.local_storage_dir,ignore_errors=True) settings.local_storage_dir.parent.mkdir(parents=True,exist_ok=True) shutil.copytree(extracted,settings.local_storage_dir) print("restore complete")