diff --git a/pkgs/clan-cli/clan_cli/templates/list_test.py b/pkgs/clan-cli/clan_cli/templates/list_test.py index a1c4dbd32..7d9ff8b98 100644 --- a/pkgs/clan-cli/clan_cli/templates/list_test.py +++ b/pkgs/clan-cli/clan_cli/templates/list_test.py @@ -1,3 +1,5 @@ +from pathlib import Path + import pytest from clan_cli.tests.fixtures_flakes import FlakeForTest @@ -11,7 +13,6 @@ def test_templates_list( ) -> None: with capture_output as output: cli.run(["templates", "list", "--flake", str(test_flake_with_core.path)]) - print(output.out) assert "Available 'clan' templates" in output.out assert "Available 'disko' templates" in output.out assert "Available 'machine' templates" in output.out @@ -21,3 +22,19 @@ def test_templates_list( assert "minimal:" in output.out assert "new-machine" in output.out assert "flash-installer" in output.out + + +@pytest.mark.with_core +def test_templates_list_outside_clan( + capture_output: CaptureOutput, temp_dir: Path +) -> None: + """Test templates list command when run outside a clan directory.""" + with capture_output as output: + # Use --flake pointing to a non-clan directory to trigger fallback + cli.run(["templates", "list", "--flake", str(temp_dir)]) + assert "Available 'clan' templates" in output.out + assert "Available 'disko' templates" in output.out + assert "Available 'machine' templates" in output.out + assert "" in output.out + # Should NOT show any custom templates + assert "inputs." not in output.out diff --git a/pkgs/clan-cli/clan_lib/templates/__init__.py b/pkgs/clan-cli/clan_lib/templates/__init__.py index 2e61406da..b75530a1f 100644 --- a/pkgs/clan-cli/clan_lib/templates/__init__.py +++ b/pkgs/clan-cli/clan_lib/templates/__init__.py @@ -1,6 +1,7 @@ import logging from dataclasses import dataclass +from clan_lib.dirs import clan_templates from clan_lib.flake import Flake from clan_lib.nix_models.clan import ClanTemplatesType @@ -13,11 +14,35 @@ class TemplateList: custom: dict[str, ClanTemplatesType] -def list_templates(flake: Flake) -> TemplateList: +def get_builtin_template_list() -> TemplateList: + """ + Fallback to get only builtin clan templates with no custom templates. + """ + builtin_flake = Flake(str(clan_templates())) + builtin_templates = builtin_flake.select("clanInternals.templates") + custom_templates: dict[str, ClanTemplatesType] = {} + return TemplateList(builtin_templates, custom_templates) + + +def list_templates(flake: Flake | None) -> TemplateList: """ Show information about a module """ - custom_templates = flake.select("clanInternals.inventoryClass.templatesPerSource") - builtin_templates = flake.select("clanInternals.templates") + if flake is None: + log.debug("No flake provided, falling back to clan-core builtin templates") + return get_builtin_template_list() - return TemplateList(builtin_templates, custom_templates) + try: + custom_templates = flake.select( + "clanInternals.inventoryClass.templatesPerSource" + ) + builtin_templates = flake.select("clanInternals.templates") + + return TemplateList(builtin_templates, custom_templates) + + except (AttributeError, KeyError, Exception): + log.debug( + "Failed to get templates from clan inputs, " + "falling back to clan-core builtin templates" + ) + return get_builtin_template_list()