2023-10-18 16:29:51 +00:00
|
|
|
import logging
|
2023-07-26 12:34:39 +00:00
|
|
|
import os
|
|
|
|
import sys
|
2023-12-31 12:51:13 +00:00
|
|
|
import urllib
|
2023-07-26 12:34:39 +00:00
|
|
|
from pathlib import Path
|
|
|
|
|
2023-10-17 21:49:16 +00:00
|
|
|
log = logging.getLogger(__name__)
|
2023-07-26 12:34:39 +00:00
|
|
|
|
2023-10-18 16:29:51 +00:00
|
|
|
|
2024-04-30 10:00:47 +00:00
|
|
|
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()
|
|
|
|
|
|
|
|
|
2023-11-29 11:40:48 +00:00
|
|
|
def get_clan_flake_toplevel() -> Path | None:
|
2023-10-29 19:48:09 +00:00
|
|
|
return find_toplevel([".clan-flake", ".git", ".hg", ".svn", "flake.nix"])
|
2023-09-22 11:24:25 +00:00
|
|
|
|
2023-12-01 14:46:27 +00:00
|
|
|
|
2023-11-29 11:40:48 +00:00
|
|
|
def find_git_repo_root() -> Path | None:
|
2023-11-15 13:28:40 +00:00
|
|
|
return find_toplevel([".git"])
|
2023-09-22 11:24:25 +00:00
|
|
|
|
|
|
|
|
2024-02-09 12:46:32 +00:00
|
|
|
def clan_key_safe(flake_url: str) -> str:
|
|
|
|
"""
|
|
|
|
only embed the url in the path, not the clan name, as it would involve eval.
|
|
|
|
"""
|
2024-01-09 09:53:52 +00:00
|
|
|
quoted_url = urllib.parse.quote_plus(flake_url)
|
2024-02-09 12:46:32 +00:00
|
|
|
return f"{quoted_url}"
|
2024-01-09 09:53:52 +00:00
|
|
|
|
|
|
|
|
2023-11-29 11:40:48 +00:00
|
|
|
def find_toplevel(top_level_files: list[str]) -> Path | None:
|
2023-10-29 19:48:09 +00:00
|
|
|
"""Returns the path to the toplevel of the clan flake"""
|
|
|
|
for project_file in top_level_files:
|
|
|
|
initial_path = Path(os.getcwd())
|
|
|
|
path = Path(initial_path)
|
|
|
|
while path.parent != path:
|
|
|
|
if (path / project_file).exists():
|
|
|
|
return path
|
|
|
|
path = path.parent
|
2023-11-03 11:51:17 +00:00
|
|
|
return None
|
2023-07-26 12:34:39 +00:00
|
|
|
|
|
|
|
|
2023-07-29 12:21:28 +00:00
|
|
|
def user_config_dir() -> Path:
|
2023-07-26 12:34:39 +00:00
|
|
|
if sys.platform == "win32":
|
2023-07-29 12:21:28 +00:00
|
|
|
return Path(os.getenv("APPDATA", os.path.expanduser("~\\AppData\\Roaming\\")))
|
2023-07-26 12:34:39 +00:00
|
|
|
elif sys.platform == "darwin":
|
|
|
|
return Path(os.path.expanduser("~/Library/Application Support/"))
|
|
|
|
else:
|
2023-07-29 12:21:28 +00:00
|
|
|
return Path(os.getenv("XDG_CONFIG_HOME", os.path.expanduser("~/.config")))
|
2023-08-26 09:23:15 +00:00
|
|
|
|
|
|
|
|
2024-01-30 05:07:27 +00:00
|
|
|
def user_data_dir() -> Path:
|
|
|
|
if sys.platform == "win32":
|
|
|
|
return Path(
|
|
|
|
os.getenv("LOCALAPPDATA", os.path.expanduser("~\\AppData\\Local\\"))
|
|
|
|
)
|
|
|
|
elif sys.platform == "darwin":
|
|
|
|
return Path(os.path.expanduser("~/Library/Application Support/"))
|
|
|
|
else:
|
|
|
|
return Path(os.getenv("XDG_DATA_HOME", os.path.expanduser("~/.local/share")))
|
|
|
|
|
|
|
|
|
|
|
|
def user_cache_dir() -> Path:
|
|
|
|
if sys.platform == "win32":
|
|
|
|
return Path(
|
|
|
|
os.getenv("LOCALAPPDATA", os.path.expanduser("~\\AppData\\Local\\"))
|
|
|
|
)
|
|
|
|
elif sys.platform == "darwin":
|
|
|
|
return Path(os.path.expanduser("~/Library/Caches/"))
|
|
|
|
else:
|
|
|
|
return Path(os.getenv("XDG_CACHE_HOME", os.path.expanduser("~/.cache")))
|
|
|
|
|
|
|
|
|
2023-12-30 23:49:57 +00:00
|
|
|
def user_gcroot_dir() -> Path:
|
|
|
|
p = user_config_dir() / "clan" / "gcroots"
|
|
|
|
p.mkdir(parents=True, exist_ok=True)
|
|
|
|
return p
|
|
|
|
|
|
|
|
|
2024-02-09 12:46:32 +00:00
|
|
|
def machine_gcroot(flake_url: str) -> Path:
|
2023-12-30 23:49:57 +00:00
|
|
|
# Always build icon so that we can symlink it to the gcroot
|
|
|
|
gcroot_dir = user_gcroot_dir()
|
2024-02-09 12:46:32 +00:00
|
|
|
clan_gcroot = gcroot_dir / clan_key_safe(flake_url)
|
2023-12-30 23:49:57 +00:00
|
|
|
clan_gcroot.mkdir(parents=True, exist_ok=True)
|
|
|
|
return clan_gcroot
|
|
|
|
|
|
|
|
|
2023-11-17 10:05:15 +00:00
|
|
|
def user_history_file() -> Path:
|
|
|
|
return user_config_dir() / "clan" / "history"
|
|
|
|
|
|
|
|
|
2024-02-09 12:46:32 +00:00
|
|
|
def vm_state_dir(flake_url: str, vm_name: str) -> Path:
|
|
|
|
clan_key = clan_key_safe(flake_url)
|
2024-01-30 05:07:27 +00:00
|
|
|
return user_data_dir() / "clan" / "vmstate" / clan_key / vm_name
|
2024-01-08 11:37:50 +00:00
|
|
|
|
|
|
|
|
2023-11-15 13:28:40 +00:00
|
|
|
def machines_dir(flake_dir: Path) -> Path:
|
|
|
|
return flake_dir / "machines"
|
2023-10-24 14:54:10 +00:00
|
|
|
|
|
|
|
|
2023-11-15 13:28:40 +00:00
|
|
|
def specific_machine_dir(flake_dir: Path, machine: str) -> Path:
|
|
|
|
return machines_dir(flake_dir) / machine
|
2023-10-24 14:54:10 +00:00
|
|
|
|
|
|
|
|
2023-11-15 13:28:40 +00:00
|
|
|
def machine_settings_file(flake_dir: Path, machine: str) -> Path:
|
|
|
|
return specific_machine_dir(flake_dir, machine) / "settings.json"
|
2023-10-24 14:54:10 +00:00
|
|
|
|
|
|
|
|
2023-08-26 09:23:15 +00:00
|
|
|
def module_root() -> Path:
|
|
|
|
return Path(__file__).parent
|
|
|
|
|
|
|
|
|
2023-09-06 15:29:49 +00:00
|
|
|
def nixpkgs_flake() -> Path:
|
|
|
|
return (module_root() / "nixpkgs").resolve()
|
2023-08-26 09:23:15 +00:00
|
|
|
|
|
|
|
|
2023-09-06 15:29:49 +00:00
|
|
|
def nixpkgs_source() -> Path:
|
|
|
|
return (module_root() / "nixpkgs" / "path").resolve()
|