"""Push generated wiki tree into a Gitea wiki git repository.""" from __future__ import annotations import shutil import subprocess from pathlib import Path class WikiPushError(RuntimeError): pass def _run(cmd: list[str], *, cwd: Path) -> str: proc = subprocess.run( cmd, cwd=cwd, capture_output=True, text=True, check=False, ) if proc.returncode != 0: raise WikiPushError( f"$ {' '.join(cmd)}\n{proc.stdout}\n{proc.stderr}".strip() ) return proc.stdout def push_wiki( content_dir: Path, wiki_url: str, *, work_dir: Path, message: str, branch: str = "main", keep_unmanaged: bool = False, ) -> None: """ Clone/fetch wiki repo into work_dir, replace managed pages, commit, push. Managed pages = all *.md from content_dir plus images and manifest.json. If keep_unmanaged=False, removes other *.md (except maybe custom) before copy. """ content_dir = content_dir.resolve() work_dir = work_dir.resolve() if work_dir.exists() and (work_dir / ".git").exists(): _run(["git", "fetch", "origin"], cwd=work_dir) _run(["git", "checkout", branch], cwd=work_dir) _run(["git", "reset", "--hard", f"origin/{branch}"], cwd=work_dir) else: if work_dir.exists(): shutil.rmtree(work_dir) work_dir.parent.mkdir(parents=True, exist_ok=True) _run( ["git", "clone", "--branch", branch, "--single-branch", wiki_url, str(work_dir)], cwd=work_dir.parent, ) if not keep_unmanaged: for path in work_dir.iterdir(): if path.name == ".git": continue if path.is_file() and path.suffix.lower() in {".md", ".json"}: path.unlink() elif path.is_file() and path.suffix.lower() in { ".png", ".jpg", ".jpeg", ".gif", ".bmp", ".webp", }: path.unlink() for src in content_dir.iterdir(): if src.name == ".git": continue dst = work_dir / src.name if src.is_dir(): if dst.exists(): shutil.rmtree(dst) shutil.copytree(src, dst) else: shutil.copy2(src, dst) _run(["git", "add", "-A"], cwd=work_dir) status = _run(["git", "status", "--porcelain"], cwd=work_dir) if not status.strip(): return _run(["git", "commit", "-m", message], cwd=work_dir) _run(["git", "push", "origin", f"HEAD:{branch}"], cwd=work_dir)