core: root discovery + status

This commit is contained in:
scawful
2025-12-30 09:05:19 -05:00
parent 000c34148d
commit aade1a6007
3 changed files with 69 additions and 1 deletions

View File

@@ -3,6 +3,14 @@
__version__ = "0.0.0" __version__ = "0.0.0"
from .config import load_config, load_config_model from .config import load_config, load_config_model
from .core import find_root, resolve_context_root
from .plugins import discover_plugins, load_plugins from .plugins import discover_plugins, load_plugins
__all__ = ["load_config", "load_config_model", "discover_plugins", "load_plugins"] __all__ = [
"load_config",
"load_config_model",
"discover_plugins",
"load_plugins",
"find_root",
"resolve_context_root",
]

View File

@@ -8,6 +8,7 @@ from pathlib import Path
from typing import Iterable from typing import Iterable
from .config import load_config_model from .config import load_config_model
from .core import find_root, resolve_context_root
from .plugins import discover_plugins, load_plugins from .plugins import discover_plugins, load_plugins
from .schema import AFSConfig, GeneralConfig, WorkspaceDirectory from .schema import AFSConfig, GeneralConfig, WorkspaceDirectory
@@ -128,6 +129,27 @@ def _plugins_command(args: argparse.Namespace) -> int:
return 0 return 0
def _status_command(args: argparse.Namespace) -> int:
start_dir = Path(args.start_dir).expanduser().resolve() if args.start_dir else None
root = find_root(start_dir)
config = load_config_model()
context_root = resolve_context_root(config, root)
print(f"context_root: {context_root}")
print(f"linked_root: {root if root else '(none)'}")
missing = []
for name in AFS_DIRS:
if not (context_root / name).exists():
missing.append(name)
if missing:
print("missing_dirs: " + ", ".join(missing))
else:
print("missing_dirs: (none)")
return 0
def build_parser() -> argparse.ArgumentParser: def build_parser() -> argparse.ArgumentParser:
parser = argparse.ArgumentParser(prog="afs") parser = argparse.ArgumentParser(prog="afs")
subparsers = parser.add_subparsers(dest="command") subparsers = parser.add_subparsers(dest="command")
@@ -147,6 +169,10 @@ def build_parser() -> argparse.ArgumentParser:
plugins_parser.add_argument("--load", action="store_true", help="Attempt to import plugins.") plugins_parser.add_argument("--load", action="store_true", help="Attempt to import plugins.")
plugins_parser.set_defaults(func=_plugins_command) plugins_parser.set_defaults(func=_plugins_command)
status_parser = subparsers.add_parser("status", help="Show context root status.")
status_parser.add_argument("--start-dir", help="Directory to search from.")
status_parser.set_defaults(func=_status_command)
return parser return parser

34
src/afs/core.py Normal file
View File

@@ -0,0 +1,34 @@
"""Core AFS helpers."""
from __future__ import annotations
import os
from pathlib import Path
from .schema import AFSConfig
def find_root(start_dir: Path | None = None) -> Path | None:
"""Find a .context directory by walking upward."""
if start_dir is None:
start_dir = Path.cwd()
current = start_dir.resolve()
for parent in [current, *current.parents]:
candidate = parent / ".context"
if candidate.exists() and candidate.is_dir():
return candidate
if (parent / "afs.toml").exists():
return parent / ".context"
return None
def resolve_context_root(config: AFSConfig | None, linked_root: Path | None) -> Path:
"""Resolve the active context root for this machine."""
env_root = os.environ.get("AFS_CONTEXT_ROOT")
if env_root:
return Path(env_root).expanduser().resolve()
if linked_root:
return linked_root.resolve()
if config:
return config.general.context_root
return (Path.home() / ".context").resolve()