Files
wp-materialize/src/scaffold.py
2026-02-08 23:38:11 +00:00

155 lines
5.5 KiB
Python

from __future__ import annotations
import json
from pathlib import Path
from typing import Any, Dict, List, Optional
from .errors import MaterializeError
def create_config(path: Path) -> None:
_ensure_parent_exists(path)
if path.exists():
raise MaterializeError(f"Config already exists: {path}")
payload = {
"wordpress_root": "/path/to/wordpress",
"repo_storage_dir": "/path/to/repo-storage",
"renderer": "default",
"hard_line_breaks": False,
"block_html": False,
"git_repositories": [
{
"name": "example-repo",
"url": "https://example.com/repo.git",
"branch": "main",
"root_subdir": None,
}
],
"directories": [
{
"name": "example-dir",
"path": "/path/to/content",
"root_subdir": None,
}
],
}
path.write_text(json.dumps(payload, indent=2), encoding="utf-8")
def create_manifest(directory: Path) -> Path:
if not directory.exists():
raise MaterializeError(f"Directory does not exist: {directory}")
if not directory.is_dir():
raise MaterializeError(f"Not a directory: {directory}")
manifest_path = directory / ".wp-materialize.json"
if manifest_path.exists():
raise MaterializeError(f"Manifest already exists: {manifest_path}")
payload = {
"categories": {"content": [], "inherit": True},
"tags": {"content": [], "inherit": True},
"author": {"content": [], "inherit": True},
"renderer": "default",
"hard_line_breaks": False,
"block_html": False,
"subdirectories": {"content": [], "inherit": True},
"files": {},
}
manifest_path.write_text(json.dumps(payload, indent=2), encoding="utf-8")
return manifest_path
def add_file_to_manifest(file_path: Path, manifest_dir: Path) -> None:
if not file_path.exists():
raise MaterializeError(f"File does not exist: {file_path}")
if not file_path.is_file():
raise MaterializeError(f"Not a file: {file_path}")
manifest_path = _manifest_path(manifest_dir)
data = _load_manifest_json(manifest_path)
relative = _relative_to(file_path, manifest_dir)
files = data.setdefault("files", {})
if not isinstance(files, dict):
raise MaterializeError("Manifest files must be an object")
if relative in files:
raise MaterializeError(f"File already exists in manifest: {relative}")
files[relative] = {"title": "TODO: Title"}
_write_manifest_json(manifest_path, data)
def add_dir_to_manifest(dir_path: Path, manifest_dir: Path) -> None:
if not dir_path.exists():
raise MaterializeError(f"Directory does not exist: {dir_path}")
if not dir_path.is_dir():
raise MaterializeError(f"Not a directory: {dir_path}")
manifest_path = _manifest_path(manifest_dir)
data = _load_manifest_json(manifest_path)
relative = _relative_to(dir_path, manifest_dir)
subdirs = data.setdefault("subdirectories", {"content": [], "inherit": True})
if not isinstance(subdirs, dict):
raise MaterializeError("Manifest subdirectories must be an object")
content = subdirs.setdefault("content", [])
if not isinstance(content, list) or any(not isinstance(item, str) for item in content):
raise MaterializeError("Manifest subdirectories.content must be a list of strings")
if relative in content:
raise MaterializeError(f"Subdirectory already exists in manifest: {relative}")
content.append(relative)
_write_manifest_json(manifest_path, data)
def resolve_manifest_dir(target_path: Path, manifest_dir: Optional[Path], use_current: bool) -> Path:
if manifest_dir and use_current:
raise MaterializeError("--current cannot be used with an explicit manifest directory")
if manifest_dir:
return manifest_dir
if use_current:
return target_path.parent
return Path.cwd()
def _manifest_path(manifest_dir: Path) -> Path:
if not manifest_dir.exists():
raise MaterializeError(f"Manifest directory does not exist: {manifest_dir}")
if not manifest_dir.is_dir():
raise MaterializeError(f"Not a directory: {manifest_dir}")
manifest_path = manifest_dir / ".wp-materialize.json"
if not manifest_path.exists():
raise MaterializeError(f"Manifest not found: {manifest_path}")
return manifest_path
def _load_manifest_json(path: Path) -> Dict[str, Any]:
try:
data = json.loads(path.read_text(encoding="utf-8"))
except json.JSONDecodeError as exc:
raise MaterializeError(f"Invalid JSON in manifest: {exc}") from exc
if not isinstance(data, dict):
raise MaterializeError("Manifest must be a JSON object")
return data
def _write_manifest_json(path: Path, data: Dict[str, Any]) -> None:
path.write_text(json.dumps(data, indent=2), encoding="utf-8")
def _relative_to(path: Path, base: Path) -> str:
try:
relative = path.relative_to(base)
except ValueError as exc:
raise MaterializeError(f"Path is outside manifest directory: {path}") from exc
relative_str = relative.as_posix()
if relative_str in {".", ""}:
raise MaterializeError(f"Path must be inside manifest directory: {path}")
return relative_str
def _ensure_parent_exists(path: Path) -> None:
parent = path.parent
if not parent.exists():
raise MaterializeError(f"Directory does not exist: {parent}")
if not parent.is_dir():
raise MaterializeError(f"Not a directory: {parent}")