"""Shared helpers for Spec Kit Python scripts.""" from __future__ import annotations import json import os import sys from dataclasses import dataclass from pathlib import Path def _trim_trailing_separators(value: Path) -> str: text = str(value) while len(text) > 1 and text.endswith((os.sep, "/")): text = text[:-1] return text def find_specify_root(start_dir: Path | None = None) -> Path | None: current = (start_dir or Path.cwd()).resolve() while True: if (current / ".specify").is_dir(): return current parent = current.parent if parent == current: return None current = parent def resolve_specify_init_dir() -> Path: raw = os.environ.get("SPECIFY_INIT_DIR", "") candidate = Path(raw) if not candidate.is_absolute(): candidate = Path.cwd() / candidate try: init_root = candidate.resolve(strict=True) except OSError: print( f"ERROR: SPECIFY_INIT_DIR does not point to an existing directory: {raw}", file=sys.stderr, ) raise SystemExit(1) if not init_root.is_dir(): print( f"ERROR: SPECIFY_INIT_DIR does not point to an existing directory: {raw}", file=sys.stderr, ) raise SystemExit(1) if not (init_root / ".specify").is_dir(): print( "ERROR: SPECIFY_INIT_DIR is not a Spec Kit project " f"(no .specify/ directory): {init_root}", file=sys.stderr, ) raise SystemExit(1) return init_root def get_repo_root(script_file: Path | None = None) -> Path: if os.environ.get("SPECIFY_INIT_DIR"): return resolve_specify_init_dir() specify_root = find_specify_root() if specify_root is not None: return specify_root if script_file is not None: script_root = find_specify_root(script_file.resolve().parent) if script_root is not None: return script_root # Installed scripts live at .specify/scripts/python/