From 8dcb009e5b22ab731894517c3138b62c1a2be736 Mon Sep 17 00:00:00 2001 From: Johannes Kirschbauer Date: Tue, 11 Jun 2024 12:10:55 +0200 Subject: [PATCH] api: refactor create flake into create clan --- pkgs/clan-cli/clan_cli/__init__.py | 27 ++-------- pkgs/clan-cli/clan_cli/arg_actions.py | 24 +++++++++ .../clan_cli/{flakes => clan}/__init__.py | 6 +-- .../clan_cli/{flakes => clan}/create.py | 51 +++++++++++++++++-- .../clan_cli/{flakes => clan}/inspect.py | 0 .../clan_cli/{flakes => clan}/show.py | 15 ++---- pkgs/clan-cli/clan_cli/history/add.py | 2 +- pkgs/clan-cli/clan_cli/history/update.py | 2 +- 8 files changed, 83 insertions(+), 44 deletions(-) create mode 100644 pkgs/clan-cli/clan_cli/arg_actions.py rename pkgs/clan-cli/clan_cli/{flakes => clan}/__init__.py (86%) rename pkgs/clan-cli/clan_cli/{flakes => clan}/create.py (63%) rename pkgs/clan-cli/clan_cli/{flakes => clan}/inspect.py (100%) rename pkgs/clan-cli/clan_cli/{flakes => clan}/show.py (85%) diff --git a/pkgs/clan-cli/clan_cli/__init__.py b/pkgs/clan-cli/clan_cli/__init__.py index 0fa94da3..2fea2d57 100644 --- a/pkgs/clan-cli/clan_cli/__init__.py +++ b/pkgs/clan-cli/clan_cli/__init__.py @@ -1,22 +1,21 @@ import argparse import logging import sys -from collections.abc import Sequence from pathlib import Path from types import ModuleType -from typing import Any # These imports are unused, but necessary for @API.register to run once. from clan_cli.api import directory -from clan_cli.flakes import show +from clan_cli.arg_actions import AppendOptionAction +from clan_cli.clan import show __all__ = ["directory"] from . import ( backups, + clan, config, facts, - flakes, flash, flatpak, history, @@ -39,24 +38,6 @@ except ImportError: pass -class AppendOptionAction(argparse.Action): - def __init__(self, option_strings: str, dest: str, **kwargs: Any) -> None: - super().__init__(option_strings, dest, **kwargs) - - def __call__( - self, - parser: argparse.ArgumentParser, - namespace: argparse.Namespace, - values: str | Sequence[str] | None, - option_string: str | None = None, - ) -> None: - lst = getattr(namespace, self.dest) - lst.append("--option") - assert isinstance(values, list), "values must be a list" - lst.append(values[0]) - lst.append(values[1]) - - def flake_path(arg: str) -> str | Path: flake_dir = Path(arg).resolve() if flake_dir.exists() and flake_dir.is_dir(): @@ -183,7 +164,7 @@ For more detailed information, visit: https://docs.clan.lol/getting-started formatter_class=argparse.RawTextHelpFormatter, ) - flakes.register_parser(parser_flake) + clan.register_parser(parser_flake) parser_config = subparsers.add_parser( "config", diff --git a/pkgs/clan-cli/clan_cli/arg_actions.py b/pkgs/clan-cli/clan_cli/arg_actions.py new file mode 100644 index 00000000..ade2ebe6 --- /dev/null +++ b/pkgs/clan-cli/clan_cli/arg_actions.py @@ -0,0 +1,24 @@ +import argparse +import logging +from collections.abc import Sequence +from typing import Any + +log = logging.getLogger(__name__) + + +class AppendOptionAction(argparse.Action): + def __init__(self, option_strings: str, dest: str, **kwargs: Any) -> None: + super().__init__(option_strings, dest, **kwargs) + + def __call__( + self, + parser: argparse.ArgumentParser, + namespace: argparse.Namespace, + values: str | Sequence[str] | None, + option_string: str | None = None, + ) -> None: + lst = getattr(namespace, self.dest) + lst.append("--option") + assert isinstance(values, list), "values must be a list" + lst.append(values[0]) + lst.append(values[1]) diff --git a/pkgs/clan-cli/clan_cli/flakes/__init__.py b/pkgs/clan-cli/clan_cli/clan/__init__.py similarity index 86% rename from pkgs/clan-cli/clan_cli/flakes/__init__.py rename to pkgs/clan-cli/clan_cli/clan/__init__.py index 7cf2ba6d..41c8ae71 100644 --- a/pkgs/clan-cli/clan_cli/flakes/__init__.py +++ b/pkgs/clan-cli/clan_cli/clan/__init__.py @@ -1,7 +1,7 @@ # !/usr/bin/env python3 import argparse -from clan_cli.flakes.inspect import register_inspect_parser +from clan_cli.clan.inspect import register_inspect_parser from .create import register_create_parser @@ -14,7 +14,7 @@ def register_parser(parser: argparse.ArgumentParser) -> None: help="the command to run", required=True, ) - create_parser = subparser.add_parser("create", help="Create a clan flake") + create_parser = subparser.add_parser("create", help="Create a clan") register_create_parser(create_parser) - inspect_parser = subparser.add_parser("inspect", help="Inspect a clan flake") + inspect_parser = subparser.add_parser("inspect", help="Inspect a clan ") register_inspect_parser(inspect_parser) diff --git a/pkgs/clan-cli/clan_cli/flakes/create.py b/pkgs/clan-cli/clan_cli/clan/create.py similarity index 63% rename from pkgs/clan-cli/clan_cli/flakes/create.py rename to pkgs/clan-cli/clan_cli/clan/create.py index 133c0c84..5a35e58f 100644 --- a/pkgs/clan-cli/clan_cli/flakes/create.py +++ b/pkgs/clan-cli/clan_cli/clan/create.py @@ -1,9 +1,11 @@ # !/usr/bin/env python3 import argparse -from dataclasses import dataclass +import json +from dataclasses import dataclass, fields from pathlib import Path from clan_cli.api import API +from clan_cli.arg_actions import AppendOptionAction from ..cmd import CmdOut, run from ..errors import ClanError @@ -21,10 +23,27 @@ class CreateClanResponse: flake_update: CmdOut +@dataclass +class ClanMetaInfo: + name: str + description: str | None + icon: str | None + + +@dataclass +class CreateOptions: + directory: Path + # Metadata for the clan + # Metadata can be shown with `clan show` + meta: ClanMetaInfo | None = None + # URL to the template to use. Defaults to the "minimal" template + template_url: str = minimal_template_url + + @API.register -def create_clan( - directory: Path, template_url: str = minimal_template_url -) -> CreateClanResponse: +def create_clan(options: CreateOptions) -> CreateClanResponse: + directory = options.directory + template_url = options.template_url if not directory.exists(): directory.mkdir() else: @@ -45,6 +64,13 @@ def create_clan( ) out = run(command, cwd=directory) + # Write meta.json file if meta is provided + if options.meta is not None: + meta_file = Path(directory / "clan/meta.json") + meta_file.parent.mkdir(parents=True, exist_ok=True) + with open(meta_file, "w") as f: + json.dump(options.meta.__dict__, f) + command = nix_shell(["nixpkgs#git"], ["git", "init"]) out = run(command, cwd=directory) cmd_responses["git init"] = out @@ -83,11 +109,26 @@ def register_create_parser(parser: argparse.ArgumentParser) -> None: help="url to the clan template", default=default_template_url, ) + + parser.add_argument( + "--meta", + help=f"""Metadata to set for the clan. Available options are: {", ".join([f.name for f in fields(ClanMetaInfo)]) }""", + nargs=2, + metavar=("name", "value"), + action=AppendOptionAction, + default=[], + ) + parser.add_argument( "path", type=Path, help="Path to the clan directory", default=Path(".") ) def create_flake_command(args: argparse.Namespace) -> None: - create_clan(args.path, args.url) + create_clan( + CreateOptions( + directory=args.path, + template_url=args.url, + ) + ) parser.set_defaults(func=create_flake_command) diff --git a/pkgs/clan-cli/clan_cli/flakes/inspect.py b/pkgs/clan-cli/clan_cli/clan/inspect.py similarity index 100% rename from pkgs/clan-cli/clan_cli/flakes/inspect.py rename to pkgs/clan-cli/clan_cli/clan/inspect.py diff --git a/pkgs/clan-cli/clan_cli/flakes/show.py b/pkgs/clan-cli/clan_cli/clan/show.py similarity index 85% rename from pkgs/clan-cli/clan_cli/flakes/show.py rename to pkgs/clan-cli/clan_cli/clan/show.py index 3bbf7bd2..5029d17b 100644 --- a/pkgs/clan-cli/clan_cli/flakes/show.py +++ b/pkgs/clan-cli/clan_cli/clan/show.py @@ -1,10 +1,10 @@ import argparse -import dataclasses import json import logging from pathlib import Path from clan_cli.api import API +from clan_cli.clan.create import ClanMetaInfo from clan_cli.errors import ClanCmdError, ClanError from ..cmd import run_no_stdout @@ -13,15 +13,8 @@ from ..nix import nix_eval log = logging.getLogger(__name__) -@dataclasses.dataclass -class ClanMeta: - name: str - description: str | None - icon: str | None - - @API.register -def show_clan(uri: str | Path) -> ClanMeta: +def show_clan_meta(uri: str | Path) -> ClanMetaInfo: cmd = nix_eval( [ f"{uri}#clanInternals.meta", @@ -40,7 +33,7 @@ def show_clan(uri: str | Path) -> ClanMeta: ) clan_meta = json.loads(res) - return ClanMeta( + return ClanMetaInfo( name=clan_meta.get("name"), description=clan_meta.get("description", None), icon=clan_meta.get("icon", None), @@ -49,7 +42,7 @@ def show_clan(uri: str | Path) -> ClanMeta: def show_command(args: argparse.Namespace) -> None: flake_path = Path(args.flake).resolve() - meta = show_clan(flake_path) + meta = show_clan_meta(flake_path) print(f"Name: {meta.name}") print(f"Description: {meta.description or ''}") diff --git a/pkgs/clan-cli/clan_cli/history/add.py b/pkgs/clan-cli/clan_cli/history/add.py index f3b5ab7a..c997bc27 100644 --- a/pkgs/clan-cli/clan_cli/history/add.py +++ b/pkgs/clan-cli/clan_cli/history/add.py @@ -6,7 +6,7 @@ import json import logging from typing import Any -from clan_cli.flakes.inspect import FlakeConfig, inspect_flake +from clan_cli.clan.inspect import FlakeConfig, inspect_flake from clan_cli.machines.list import list_machines from ..clan_uri import ClanURI diff --git a/pkgs/clan-cli/clan_cli/history/update.py b/pkgs/clan-cli/clan_cli/history/update.py index 12ecf24e..6eb23ac2 100644 --- a/pkgs/clan-cli/clan_cli/history/update.py +++ b/pkgs/clan-cli/clan_cli/history/update.py @@ -2,7 +2,7 @@ import argparse import datetime -from clan_cli.flakes.inspect import inspect_flake +from clan_cli.clan.inspect import inspect_flake from ..clan_uri import ClanURI from ..errors import ClanCmdError