clan-cli: clan_cli.dirs -> clan_lib.dirs

This commit is contained in:
lassulus
2025-05-19 20:02:38 +02:00
parent 1df5dfe6d3
commit f5e9f305d0
30 changed files with 48 additions and 50 deletions

View File

@@ -5,13 +5,13 @@ from dataclasses import dataclass
from typing import Any, TypedDict
from uuid import uuid4
from clan_cli.dirs import TemplateType, clan_templates
from clan_cli.git import commit_file
from clan_cli.machines.hardware import HardwareConfig, show_machine_hardware_config
from clan_cli.machines.machines import Machine
from clan_lib.api import API
from clan_lib.api.modules import Frontmatter, extract_frontmatter
from clan_lib.dirs import TemplateType, clan_templates
from clan_lib.errors import ClanError
log = logging.getLogger(__name__)

View File

@@ -0,0 +1,166 @@
import logging
import os
import sys
import urllib.parse
from enum import Enum
from pathlib import Path
from typing import TYPE_CHECKING
from clan_lib.errors import ClanError
if TYPE_CHECKING:
from clan_cli.machines.machines import Machine
from clan_lib.flake import Flake
log = logging.getLogger(__name__)
def get_clan_flake_toplevel_or_env() -> Path | None:
if clan_dir := os.environ.get("CLAN_DIR"):
return Path(clan_dir)
return get_clan_flake_toplevel()
def get_clan_flake_toplevel() -> Path | None:
return find_toplevel([".clan-flake", ".git", ".hg", ".svn", "flake.nix"])
def find_git_repo_root() -> Path | None:
return find_toplevel([".git"])
def clan_key_safe(flake_url: str) -> str:
"""
only embed the url in the path, not the clan name, as it would involve eval.
"""
quoted_url = urllib.parse.quote_plus(flake_url)
return f"{quoted_url}"
def find_toplevel(top_level_files: list[str]) -> Path | None:
"""Returns the path to the toplevel of the clan flake"""
for project_file in top_level_files:
initial_path = Path.cwd()
path = Path(initial_path)
while path.parent != path:
if (path / project_file).exists():
return path
path = path.parent
return None
class TemplateType(Enum):
CLAN = "clan"
DISK = "disk"
MACHINE = "machine"
def clan_templates(template_type: TemplateType | None = None) -> Path:
template_path = module_root().parent.parent.parent / "templates"
if template_type is not None:
template_path /= template_type.value
if template_path.exists():
return template_path
template_path = module_root() / "templates"
if template_type is not None:
template_path /= template_type.value
if not template_path.exists():
msg = f"BUG! clan core not found at {template_path}. This is an issue with packaging the cli"
raise ClanError(msg)
return template_path
def user_config_dir() -> Path:
if sys.platform == "win32":
return Path(os.getenv("APPDATA", Path("~\\AppData\\Roaming\\").expanduser()))
xdg_config = os.getenv("XDG_CONFIG_HOME")
if xdg_config:
return Path(xdg_config)
if sys.platform == "darwin":
return Path("~/Library/Application Support/").expanduser()
return Path("~/.config").expanduser()
def user_data_dir() -> Path:
if sys.platform == "win32":
return Path(
Path(os.getenv("LOCALAPPDATA", Path("~\\AppData\\Local\\").expanduser()))
)
xdg_data = os.getenv("XDG_DATA_HOME")
if xdg_data:
return Path(xdg_data)
if sys.platform == "darwin":
return Path("~/Library/Application Support/").expanduser()
return Path("~/.local/share").expanduser()
def user_cache_dir() -> Path:
if sys.platform == "win32":
return Path(
Path(os.getenv("LOCALAPPDATA", Path("~\\AppData\\Local\\").expanduser()))
)
xdg_cache = os.getenv("XDG_CACHE_HOME")
if xdg_cache:
return Path(xdg_cache)
if sys.platform == "darwin":
return Path("~/Library/Caches/").expanduser()
return Path("~/.cache").expanduser()
def user_gcroot_dir() -> Path:
p = user_config_dir() / "clan" / "gcroots"
p.mkdir(parents=True, exist_ok=True)
return p
def machine_gcroot(flake_url: str) -> Path:
# Always build icon so that we can symlink it to the gcroot
gcroot_dir = user_gcroot_dir()
clan_gcroot = gcroot_dir / clan_key_safe(flake_url)
clan_gcroot.mkdir(parents=True, exist_ok=True)
return clan_gcroot
def user_history_file() -> Path:
return user_config_dir() / "clan" / "history"
def vm_state_dir(flake_url: str, vm_name: str) -> Path:
clan_key = clan_key_safe(str(flake_url))
return user_data_dir() / "clan" / "vmstate" / clan_key / vm_name
def machines_dir(flake: "Flake") -> Path:
if flake.is_local:
return flake.path / "machines"
store_path = flake.store_path
assert store_path is not None, "Invalid flake object. Doesn't have a store path"
return Path(store_path) / "machines"
def specific_machine_dir(machine: "Machine") -> Path:
return machines_dir(machine.flake) / machine.name
def module_root() -> Path:
return Path(__file__).parent.parent
def nixpkgs_flake() -> Path:
return (module_root() / "nixpkgs").resolve()
def nixpkgs_source() -> Path:
return (module_root() / "nixpkgs" / "path").resolve()
def select_source() -> Path:
return (module_root() / "select").resolve()

View File

@@ -649,8 +649,7 @@ class Flake:
This method is used to refresh the cache by reloading it from the flake.
"""
from clan_cli.dirs import user_cache_dir
from clan_lib.dirs import user_cache_dir
from clan_lib.nix import (
nix_metadata,
)
@@ -703,9 +702,8 @@ class Flake:
ClanError: If the number of outputs does not match the number of selectors.
AssertionError: If the cache or flake cache path is not properly initialized.
"""
from clan_cli.dirs import nixpkgs_source, select_source
from clan_lib.cmd import Log, RunOpts, run
from clan_lib.dirs import nixpkgs_source, select_source
from clan_lib.nix import (
nix_build,
nix_config,

View File

@@ -7,10 +7,10 @@ from functools import cache
from pathlib import Path
from typing import Any
from clan_cli.dirs import nixpkgs_flake, nixpkgs_source
from clan_cli.locked_open import locked_open
from clan_lib.cmd import run
from clan_lib.dirs import nixpkgs_flake, nixpkgs_source
from clan_lib.errors import ClanError
log = logging.getLogger(__name__)

View File

@@ -8,7 +8,6 @@ from typing import Any
import clan_cli.clan.create
import pytest
from clan_cli.dirs import specific_machine_dir
from clan_cli.inventory import patch_inventory_with
from clan_cli.machines.create import CreateOptions as ClanCreateOptions
from clan_cli.machines.create import create_machine
@@ -23,6 +22,7 @@ from clan_cli.vars.generate import generate_vars_for_machine, get_generators_clo
from clan_lib.api.disk import hw_main_disk_options, set_machine_disk_schema
from clan_lib.api.network import check_machine_online
from clan_lib.cmd import RunOpts, run
from clan_lib.dirs import specific_machine_dir
from clan_lib.errors import ClanError
from clan_lib.flake import Flake
from clan_lib.nix import nix_command