feat(storage): resolve portable workspace roots
This commit is contained in:
@@ -0,0 +1,50 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass
|
||||
from pathlib import Path
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from tht.config import ConfigError
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from tht.config import Config
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class ResolvedPaths:
|
||||
workspace: Path
|
||||
sessions: Path
|
||||
artifacts: Path
|
||||
indexes: Path
|
||||
corpus: Path
|
||||
|
||||
|
||||
def _resolve_root(path: Path, workspace: Path, name: str) -> Path:
|
||||
if path.is_absolute():
|
||||
# Existing deployments commonly point at an external workspace checkout. Keep
|
||||
# those paths working while `tht doctor` identifies them for migration.
|
||||
return path
|
||||
|
||||
resolved = (workspace / path).resolve()
|
||||
if not resolved.is_relative_to(workspace):
|
||||
raise ConfigError(f"paths.{name} resolves outside workspace root")
|
||||
return resolved
|
||||
|
||||
|
||||
def resolve_workspace_paths(
|
||||
config_path: Path, cfg: Config, data_root: Path
|
||||
) -> ResolvedPaths:
|
||||
"""Resolve portable paths under ``<data_root>/workspaces/<config stem>``.
|
||||
|
||||
Relative roots are sandboxed to the logical workspace. Absolute roots are a
|
||||
compatibility bridge for existing installations and are never rewritten.
|
||||
"""
|
||||
workspace = (data_root / "workspaces" / config_path.stem).resolve()
|
||||
roots = cfg.roots
|
||||
return ResolvedPaths(
|
||||
workspace=workspace,
|
||||
sessions=_resolve_root(roots.sessions, workspace, "sessions"),
|
||||
artifacts=_resolve_root(roots.artifacts, workspace, "artifacts"),
|
||||
indexes=_resolve_root(roots.indexes, workspace, "indexes"),
|
||||
corpus=(workspace / "corpus").resolve(),
|
||||
)
|
||||
Reference in New Issue
Block a user