clan-core/pkgs/clan-cli/clan_cli/history/add.py

120 lines
3.7 KiB
Python
Raw Normal View History

# !/usr/bin/env python3
import argparse
2023-12-02 15:16:38 +00:00
import dataclasses
2023-12-11 18:09:34 +00:00
import datetime
2023-12-02 15:16:38 +00:00
import json
import logging
2023-12-02 15:16:38 +00:00
from typing import Any
from clan_cli.clan.inspect import FlakeConfig, inspect_flake
2024-02-02 03:56:08 +00:00
from clan_cli.machines.list import list_machines
2023-12-12 20:31:47 +00:00
from ..clan_uri import ClanURI
2023-12-11 18:09:34 +00:00
from ..dirs import user_history_file
2024-01-02 05:23:55 +00:00
from ..errors import ClanError
from ..locked_open import read_history_file, write_history_file
log = logging.getLogger(__name__)
2023-12-11 18:09:34 +00:00
@dataclasses.dataclass
2023-12-02 15:16:38 +00:00
class HistoryEntry:
last_used: str
2023-12-11 18:09:34 +00:00
flake: FlakeConfig
settings: dict[str, Any] = dataclasses.field(default_factory=dict)
2023-12-02 15:16:38 +00:00
def __post_init__(self) -> None:
if isinstance(self.flake, dict):
self.flake = FlakeConfig(**self.flake)
2023-12-02 15:16:38 +00:00
def _merge_dicts(d1: dict, d2: dict) -> dict:
# create a new dictionary that copies d1
merged = dict(d1)
# iterate over the keys and values of d2
for key, value in d2.items():
# if the key is in d1 and both values are dictionaries, merge them recursively
if key in d1 and isinstance(d1[key], dict) and isinstance(value, dict):
merged[key] = _merge_dicts(d1[key], value)
# otherwise, update the value of the key in the merged dictionary
else:
merged[key] = value
# return the merged dictionary
return merged
2023-12-02 15:16:38 +00:00
def list_history() -> list[HistoryEntry]:
logs: list[HistoryEntry] = []
if not user_history_file().exists():
return []
2023-12-02 15:16:38 +00:00
try:
parsed = read_history_file()
for i, p in enumerate(parsed.copy()):
# Everything from the settings dict is merged into the flake dict, and can override existing values
parsed[i] = _merge_dicts(p, p.get("settings", {}))
logs = [HistoryEntry(**p) for p in parsed]
except (json.JSONDecodeError, TypeError) as ex:
2024-01-02 05:23:55 +00:00
raise ClanError(f"History file at {user_history_file()} is corrupted") from ex
2023-12-02 15:16:38 +00:00
return logs
2024-02-02 03:56:08 +00:00
def new_history_entry(url: str, machine: str) -> HistoryEntry:
flake = inspect_flake(url, machine)
flake.flake_url = str(flake.flake_url)
return HistoryEntry(
flake=flake,
last_used=datetime.datetime.now().isoformat(),
)
def add_all_to_history(uri: ClanURI) -> list[HistoryEntry]:
2024-02-02 03:56:08 +00:00
history = list_history()
new_entries: list[HistoryEntry] = []
2024-03-07 12:04:48 +00:00
for machine in list_machines(uri.get_url()):
new_entry = _add_maschine_to_history_list(uri.get_url(), machine, history)
new_entries.append(new_entry)
write_history_file(history)
return new_entries
2024-02-02 03:56:08 +00:00
def add_history(uri: ClanURI) -> HistoryEntry:
user_history_file().parent.mkdir(parents=True, exist_ok=True)
history = list_history()
2024-03-07 12:04:48 +00:00
new_entry = _add_maschine_to_history_list(uri.get_url(), uri.machine.name, history)
2024-02-02 03:56:08 +00:00
write_history_file(history)
return new_entry
2024-02-02 03:56:08 +00:00
2023-12-11 18:09:34 +00:00
def _add_maschine_to_history_list(
uri_path: str, uri_machine: str, entries: list[HistoryEntry]
) -> HistoryEntry:
for new_entry in entries:
if (
new_entry.flake.flake_url == str(uri_path)
and new_entry.flake.flake_attr == uri_machine
):
new_entry.last_used = datetime.datetime.now().isoformat()
return new_entry
2023-12-11 18:09:34 +00:00
new_entry = new_history_entry(uri_path, uri_machine)
entries.append(new_entry)
return new_entry
2023-12-02 15:16:38 +00:00
2023-12-11 18:09:34 +00:00
def add_history_command(args: argparse.Namespace) -> None:
if args.all:
add_all_to_history(args.uri)
else:
add_history(args.uri)
# takes a (sub)parser and configures it
2023-12-11 18:09:34 +00:00
def register_add_parser(parser: argparse.ArgumentParser) -> None:
2024-03-07 12:04:48 +00:00
parser.add_argument("uri", type=ClanURI, help="Path to the flake", default=".")
2024-02-02 03:56:08 +00:00
parser.add_argument(
"--all", help="Add all machines", default=False, action="store_true"
)
2023-12-11 18:09:34 +00:00
parser.set_defaults(func=add_history_command)