155 lines
5.5 KiB
Python
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}")
|