Merge pull request 'clan-cli: clan_cli.dirs -> clan_lib.dirs' (#3706) from clan_lib_dirs into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/3706
This commit is contained in:
@@ -14,6 +14,7 @@ from .clan import show, update
|
||||
# API endpoints that are not used in the cli.
|
||||
__all__ = ["directory", "disk", "mdns_discovery", "modules", "update"]
|
||||
|
||||
from clan_lib.dirs import get_clan_flake_toplevel_or_env
|
||||
from clan_lib.errors import ClanError
|
||||
from clan_lib.flake import Flake
|
||||
|
||||
@@ -26,7 +27,6 @@ from . import (
|
||||
vms,
|
||||
)
|
||||
from .custom_logger import setup_logging
|
||||
from .dirs import get_clan_flake_toplevel_or_env
|
||||
from .facts import cli as facts
|
||||
from .flash import cli as flash_cli
|
||||
from .hyperlink import help_hyperlink
|
||||
|
||||
@@ -4,6 +4,7 @@ from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
from clan_lib.cmd import run
|
||||
from clan_lib.dirs import machine_gcroot
|
||||
from clan_lib.errors import ClanError
|
||||
from clan_lib.flake import Flake
|
||||
from clan_lib.nix import (
|
||||
@@ -14,7 +15,6 @@ from clan_lib.nix import (
|
||||
nix_metadata,
|
||||
)
|
||||
|
||||
from clan_cli.dirs import machine_gcroot
|
||||
from clan_cli.machines.list import list_machines
|
||||
from clan_cli.machines.machines import Machine
|
||||
from clan_cli.vms.inspect import VmConfig, inspect_vm
|
||||
|
||||
@@ -27,7 +27,7 @@ COMPLETION_TIMEOUT: int = 3
|
||||
|
||||
|
||||
def clan_dir(flake: str | None) -> str | None:
|
||||
from .dirs import get_clan_flake_toplevel_or_env
|
||||
from clan_lib.dirs import get_clan_flake_toplevel_or_env
|
||||
|
||||
path_result = get_clan_flake_toplevel_or_env()
|
||||
return str(path_result) if path_result is not None else None
|
||||
|
||||
@@ -1,166 +0,0 @@
|
||||
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_lib.flake import Flake
|
||||
|
||||
from clan_cli.machines.machines import Machine
|
||||
|
||||
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
|
||||
|
||||
|
||||
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()
|
||||
@@ -1,9 +1,9 @@
|
||||
import logging
|
||||
from pathlib import Path
|
||||
|
||||
from clan_lib.dirs import vm_state_dir
|
||||
from clan_lib.errors import ClanError
|
||||
|
||||
from clan_cli.dirs import vm_state_dir
|
||||
from clan_cli.machines.machines import Machine
|
||||
|
||||
from . import FactStoreBase
|
||||
|
||||
@@ -2,7 +2,8 @@ import shutil
|
||||
from pathlib import Path
|
||||
from typing import override
|
||||
|
||||
from clan_cli.dirs import vm_state_dir
|
||||
from clan_lib.dirs import vm_state_dir
|
||||
|
||||
from clan_cli.machines.machines import Machine
|
||||
|
||||
from . import SecretStoreBase
|
||||
|
||||
@@ -5,7 +5,8 @@ from contextlib import contextmanager
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
from .dirs import user_history_file
|
||||
from clan_lib.dirs import user_history_file
|
||||
|
||||
from .jsonrpc import ClanJSONEncoder
|
||||
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ from dataclasses import dataclass
|
||||
from pathlib import Path
|
||||
|
||||
from clan_lib.api import API
|
||||
from clan_lib.dirs import get_clan_flake_toplevel_or_env
|
||||
from clan_lib.errors import ClanError
|
||||
from clan_lib.flake import Flake
|
||||
from clan_lib.nix_models.inventory import (
|
||||
@@ -17,7 +18,6 @@ from clan_lib.persist.inventory_store import InventoryStore
|
||||
from clan_lib.persist.util import apply_patch
|
||||
|
||||
from clan_cli.completions import add_dynamic_completer, complete_tags
|
||||
from clan_cli.dirs import get_clan_flake_toplevel_or_env
|
||||
from clan_cli.git import commit_file
|
||||
from clan_cli.machines.list import list_machines
|
||||
from clan_cli.templates import (
|
||||
|
||||
@@ -4,10 +4,10 @@ import shutil
|
||||
from pathlib import Path
|
||||
|
||||
from clan_lib.api import API
|
||||
from clan_lib.dirs import specific_machine_dir
|
||||
|
||||
from clan_cli import inventory
|
||||
from clan_cli.completions import add_dynamic_completer, complete_machines
|
||||
from clan_cli.dirs import specific_machine_dir
|
||||
from clan_cli.machines.machines import Machine
|
||||
from clan_cli.secrets.folders import sops_secrets_folder
|
||||
from clan_cli.secrets.machines import has_machine as secrets_has_machine
|
||||
|
||||
@@ -7,11 +7,11 @@ from pathlib import Path
|
||||
|
||||
from clan_lib.api import API
|
||||
from clan_lib.cmd import RunOpts, run
|
||||
from clan_lib.dirs import specific_machine_dir
|
||||
from clan_lib.errors import ClanCmdError, ClanError
|
||||
from clan_lib.nix import nix_config, nix_eval
|
||||
|
||||
from clan_cli.completions import add_dynamic_completer, complete_machines
|
||||
from clan_cli.dirs import specific_machine_dir
|
||||
from clan_cli.git import commit_file
|
||||
from clan_cli.machines.machines import Machine
|
||||
|
||||
|
||||
@@ -6,13 +6,13 @@ from dataclasses import dataclass
|
||||
from clan_lib.api import API
|
||||
from clan_lib.api.disk import MachineDiskMatter
|
||||
from clan_lib.api.modules import parse_frontmatter
|
||||
from clan_lib.dirs import specific_machine_dir
|
||||
from clan_lib.errors import ClanError
|
||||
from clan_lib.flake import Flake
|
||||
from clan_lib.nix_models.inventory import Machine as InventoryMachine
|
||||
from clan_lib.persist.inventory_store import InventoryStore
|
||||
|
||||
from clan_cli.completions import add_dynamic_completer, complete_tags
|
||||
from clan_cli.dirs import specific_machine_dir
|
||||
from clan_cli.machines.hardware import HardwareConfig
|
||||
from clan_cli.machines.inventory import get_machine
|
||||
from clan_cli.machines.machines import Machine
|
||||
|
||||
@@ -8,12 +8,12 @@ from pathlib import Path
|
||||
from tempfile import TemporaryDirectory
|
||||
|
||||
from clan_lib.cmd import Log, RunOpts, run
|
||||
from clan_lib.dirs import get_clan_flake_toplevel_or_env
|
||||
from clan_lib.errors import ClanError
|
||||
from clan_lib.flake import Flake
|
||||
from clan_lib.nix import nix_build, nix_command
|
||||
from clan_lib.nix_models.inventory import Machine as InventoryMachine
|
||||
|
||||
from clan_cli.dirs import get_clan_flake_toplevel_or_env
|
||||
from clan_cli.machines.create import CreateOptions, create_machine
|
||||
from clan_cli.machines.machines import Machine
|
||||
from clan_cli.vars.generate import generate_vars
|
||||
|
||||
@@ -15,12 +15,11 @@ from typing import IO, Any
|
||||
|
||||
from clan_lib.api import API
|
||||
from clan_lib.cmd import Log, RunOpts, run
|
||||
from clan_lib.dirs import user_config_dir
|
||||
from clan_lib.errors import ClanError
|
||||
from clan_lib.flake import Flake
|
||||
from clan_lib.nix import nix_shell
|
||||
|
||||
from clan_cli.dirs import user_config_dir
|
||||
|
||||
from .folders import sops_users_folder
|
||||
|
||||
AGE_RECIPIENT_REGEX = re.compile(r"^.*((age1|ssh-(rsa|ed25519) ).*?)(\s|$)")
|
||||
|
||||
@@ -4,6 +4,7 @@ import logging
|
||||
from pathlib import Path
|
||||
|
||||
from clan_lib.cmd import RunOpts, run
|
||||
from clan_lib.dirs import get_clan_flake_toplevel_or_env
|
||||
from clan_lib.errors import ClanCmdError, ClanError
|
||||
from clan_lib.nix import nix_eval
|
||||
|
||||
@@ -12,7 +13,6 @@ from clan_cli.completions import (
|
||||
complete_machines,
|
||||
complete_state_services_for_machine,
|
||||
)
|
||||
from clan_cli.dirs import get_clan_flake_toplevel_or_env
|
||||
from clan_cli.machines.machines import Machine
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
@@ -4,11 +4,10 @@ from pathlib import Path
|
||||
from typing import Any, Literal, NewType, TypedDict, cast
|
||||
|
||||
from clan_lib.cmd import run
|
||||
from clan_lib.dirs import clan_templates
|
||||
from clan_lib.errors import ClanCmdError, ClanError
|
||||
from clan_lib.flake import Flake
|
||||
|
||||
from clan_cli.dirs import clan_templates
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
|
||||
@@ -10,18 +10,18 @@ from pathlib import Path
|
||||
from typing import Any, NamedTuple
|
||||
|
||||
import pytest
|
||||
from clan_cli.dirs import (
|
||||
TemplateType,
|
||||
clan_templates,
|
||||
nixpkgs_source,
|
||||
specific_machine_dir,
|
||||
)
|
||||
from clan_cli.locked_open import locked_open
|
||||
from clan_cli.machines.machines import Machine
|
||||
from clan_cli.tests import age_keys
|
||||
from clan_cli.tests.fixture_error import FixtureError
|
||||
from clan_cli.tests.root import CLAN_CORE
|
||||
from clan_cli.tests.temporary_dir import TEMPDIR
|
||||
from clan_lib.dirs import (
|
||||
TemplateType,
|
||||
clan_templates,
|
||||
nixpkgs_source,
|
||||
specific_machine_dir,
|
||||
)
|
||||
from clan_lib.flake import Flake
|
||||
from clan_lib.nix import nix_test_store
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# from clan_cli.dirs import _get_clan_flake_toplevel
|
||||
# from clan_lib.dirs import _get_clan_flake_toplevel
|
||||
|
||||
# TODO: Reimplement test?
|
||||
# def test_get_clan_flake_toplevel(
|
||||
@@ -16,7 +16,7 @@
|
||||
# (subdir / ".clan-flake").touch()
|
||||
# assert _get_clan_flake_toplevel() == subdir
|
||||
|
||||
from clan_cli.dirs import clan_key_safe, vm_state_dir
|
||||
from clan_lib.dirs import clan_key_safe, vm_state_dir
|
||||
|
||||
|
||||
def test_clan_key_safe() -> None:
|
||||
|
||||
@@ -3,11 +3,11 @@ import shutil
|
||||
from collections.abc import Iterable
|
||||
from pathlib import Path
|
||||
|
||||
from clan_cli.dirs import vm_state_dir
|
||||
from clan_cli.machines.machines import Machine
|
||||
from clan_cli.ssh.host import Host
|
||||
from clan_cli.vars._types import StoreBase
|
||||
from clan_cli.vars.generate import Generator, Var
|
||||
from clan_lib.dirs import vm_state_dir
|
||||
from clan_lib.errors import ClanError
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
@@ -2,11 +2,11 @@ import shutil
|
||||
from collections.abc import Iterable
|
||||
from pathlib import Path
|
||||
|
||||
from clan_cli.dirs import vm_state_dir
|
||||
from clan_cli.machines.machines import Machine
|
||||
from clan_cli.ssh.host import Host
|
||||
from clan_cli.vars._types import StoreBase
|
||||
from clan_cli.vars.generate import Generator, Var
|
||||
from clan_lib.dirs import vm_state_dir
|
||||
|
||||
|
||||
class SecretStore(StoreBase):
|
||||
|
||||
@@ -13,11 +13,11 @@ from pathlib import Path
|
||||
from tempfile import TemporaryDirectory
|
||||
|
||||
from clan_lib.cmd import CmdOut, Log, RunOpts, handle_io, run
|
||||
from clan_lib.dirs import module_root, user_cache_dir, vm_state_dir
|
||||
from clan_lib.errors import ClanCmdError, ClanError
|
||||
from clan_lib.nix import nix_shell
|
||||
|
||||
from clan_cli.completions import add_dynamic_completer, complete_machines
|
||||
from clan_cli.dirs import module_root, user_cache_dir, vm_state_dir
|
||||
from clan_cli.facts.generate import generate_facts
|
||||
from clan_cli.machines.machines import Machine
|
||||
from clan_cli.qemu.qga import QgaSession
|
||||
|
||||
Reference in New Issue
Block a user