api: refactor create flake into create clan

This commit is contained in:
Johannes Kirschbauer 2024-06-11 12:10:55 +02:00
parent 9f0f44b470
commit 8dcb009e5b
Signed by: hsjobeki
SSH Key Fingerprint: SHA256:vX3utDqig7Ph5L0JPv87ZTPb/w7cMzREKVZzzLFg9qU
8 changed files with 83 additions and 44 deletions

View File

@ -1,22 +1,21 @@
import argparse import argparse
import logging import logging
import sys import sys
from collections.abc import Sequence
from pathlib import Path from pathlib import Path
from types import ModuleType from types import ModuleType
from typing import Any
# These imports are unused, but necessary for @API.register to run once. # These imports are unused, but necessary for @API.register to run once.
from clan_cli.api import directory 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"] __all__ = ["directory"]
from . import ( from . import (
backups, backups,
clan,
config, config,
facts, facts,
flakes,
flash, flash,
flatpak, flatpak,
history, history,
@ -39,24 +38,6 @@ except ImportError:
pass 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: def flake_path(arg: str) -> str | Path:
flake_dir = Path(arg).resolve() flake_dir = Path(arg).resolve()
if flake_dir.exists() and flake_dir.is_dir(): 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, formatter_class=argparse.RawTextHelpFormatter,
) )
flakes.register_parser(parser_flake) clan.register_parser(parser_flake)
parser_config = subparsers.add_parser( parser_config = subparsers.add_parser(
"config", "config",

View File

@ -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])

View File

@ -1,7 +1,7 @@
# !/usr/bin/env python3 # !/usr/bin/env python3
import argparse 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 from .create import register_create_parser
@ -14,7 +14,7 @@ def register_parser(parser: argparse.ArgumentParser) -> None:
help="the command to run", help="the command to run",
required=True, 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) 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) register_inspect_parser(inspect_parser)

View File

@ -1,9 +1,11 @@
# !/usr/bin/env python3 # !/usr/bin/env python3
import argparse import argparse
from dataclasses import dataclass import json
from dataclasses import dataclass, fields
from pathlib import Path from pathlib import Path
from clan_cli.api import API from clan_cli.api import API
from clan_cli.arg_actions import AppendOptionAction
from ..cmd import CmdOut, run from ..cmd import CmdOut, run
from ..errors import ClanError from ..errors import ClanError
@ -21,10 +23,27 @@ class CreateClanResponse:
flake_update: CmdOut 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 @API.register
def create_clan( def create_clan(options: CreateOptions) -> CreateClanResponse:
directory: Path, template_url: str = minimal_template_url directory = options.directory
) -> CreateClanResponse: template_url = options.template_url
if not directory.exists(): if not directory.exists():
directory.mkdir() directory.mkdir()
else: else:
@ -45,6 +64,13 @@ def create_clan(
) )
out = run(command, cwd=directory) 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"]) command = nix_shell(["nixpkgs#git"], ["git", "init"])
out = run(command, cwd=directory) out = run(command, cwd=directory)
cmd_responses["git init"] = out cmd_responses["git init"] = out
@ -83,11 +109,26 @@ def register_create_parser(parser: argparse.ArgumentParser) -> None:
help="url to the clan template", help="url to the clan template",
default=default_template_url, 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( parser.add_argument(
"path", type=Path, help="Path to the clan directory", default=Path(".") "path", type=Path, help="Path to the clan directory", default=Path(".")
) )
def create_flake_command(args: argparse.Namespace) -> None: 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) parser.set_defaults(func=create_flake_command)

View File

@ -1,10 +1,10 @@
import argparse import argparse
import dataclasses
import json import json
import logging import logging
from pathlib import Path from pathlib import Path
from clan_cli.api import API from clan_cli.api import API
from clan_cli.clan.create import ClanMetaInfo
from clan_cli.errors import ClanCmdError, ClanError from clan_cli.errors import ClanCmdError, ClanError
from ..cmd import run_no_stdout from ..cmd import run_no_stdout
@ -13,15 +13,8 @@ from ..nix import nix_eval
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@dataclasses.dataclass
class ClanMeta:
name: str
description: str | None
icon: str | None
@API.register @API.register
def show_clan(uri: str | Path) -> ClanMeta: def show_clan_meta(uri: str | Path) -> ClanMetaInfo:
cmd = nix_eval( cmd = nix_eval(
[ [
f"{uri}#clanInternals.meta", f"{uri}#clanInternals.meta",
@ -40,7 +33,7 @@ def show_clan(uri: str | Path) -> ClanMeta:
) )
clan_meta = json.loads(res) clan_meta = json.loads(res)
return ClanMeta( return ClanMetaInfo(
name=clan_meta.get("name"), name=clan_meta.get("name"),
description=clan_meta.get("description", None), description=clan_meta.get("description", None),
icon=clan_meta.get("icon", 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: def show_command(args: argparse.Namespace) -> None:
flake_path = Path(args.flake).resolve() flake_path = Path(args.flake).resolve()
meta = show_clan(flake_path) meta = show_clan_meta(flake_path)
print(f"Name: {meta.name}") print(f"Name: {meta.name}")
print(f"Description: {meta.description or ''}") print(f"Description: {meta.description or ''}")

View File

@ -6,7 +6,7 @@ import json
import logging import logging
from typing import Any 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_cli.machines.list import list_machines
from ..clan_uri import ClanURI from ..clan_uri import ClanURI

View File

@ -2,7 +2,7 @@
import argparse import argparse
import datetime import datetime
from clan_cli.flakes.inspect import inspect_flake from clan_cli.clan.inspect import inspect_flake
from ..clan_uri import ClanURI from ..clan_uri import ClanURI
from ..errors import ClanCmdError from ..errors import ClanCmdError