diff --git a/pkgs/clan-cli/clan_cli/flake.py b/pkgs/clan-cli/clan_cli/flake.py index 057454d60..195fe2994 100644 --- a/pkgs/clan-cli/clan_cli/flake.py +++ b/pkgs/clan-cli/clan_cli/flake.py @@ -468,6 +468,23 @@ class Flake: selectors: list[str], nix_options: list[str] | None = None, ) -> None: + """ + Retrieves specific attributes from a Nix flake using the provided selectors. + + This function interacts with the Nix build system to fetch and process + attributes from a flake. It uses the provided selectors to determine which + attributes to retrieve and optionally accepts additional Nix options for + customization. The results are cached for future use. + Used mostly as a lowlevel function for `precache` and `select` methods. + + Args: + selectors (list[str]): A list of attribute selectors to fetch from the flake. + nix_options (list[str] | None): Optional additional options to pass to the Nix build command. + + Raises: + ClanError: If the number of outputs does not match the number of selectors. + AssertionError: If the cache or flake cache path is not properly initialized. + """ if self._cache is None: self.prefetch() assert self._cache is not None @@ -481,7 +498,7 @@ class Flake: flake = builtins.getFlake("path:{self.store_path}?narHash={self.hash}"); in flake.inputs.nixpkgs.legacyPackages.{config["system"]}.writeText "clan-flake-select" ( - builtins.toJSON [ ({" ".join([f"flake.clanInternals.clanLib.select ''{attr}'' flake" for attr in selectors])}) ] + builtins.toJSON [ {" ".join([f"(flake.clanInternals.clanLib.select ''{attr}'' flake)" for attr in selectors])} ] ) """ if tmp_store := nix_test_store(): @@ -506,11 +523,46 @@ class Flake: self._cache.insert(outputs[i], selector) self._cache.save_to_file(self.flake_cache_path) + def precache( + self, + selectors: list[str], + nix_options: list[str] | None = None, + ) -> None: + """ + Ensures that the specified selectors are cached locally. + + This function checks if the given selectors are already cached. If not, it + fetches them using the Nix build system and stores them in the local cache. + It ensures that the cache is initialized before performing these operations. + + Args: + selectors (list[str]): A list of attribute selectors to check and cache. + nix_options (list[str] | None): Optional additional options to pass to the Nix build command. + """ + if self._cache is None: + self.prefetch() + assert self._cache is not None + assert self.flake_cache_path is not None + not_fetched_selectors = [] + for selector in selectors: + if not self._cache.is_cached(selector): + not_fetched_selectors.append(selector) + if not_fetched_selectors: + self.get_from_nix(not_fetched_selectors, nix_options) + def select( self, selector: str, nix_options: list[str] | None = None, ) -> Any: + """ + Selects a value from the cache based on the provided selector string. + Fetches it via nix_build if it is not already cached. + + Args: + selector (str): The attribute selector string to fetch the value for. + nix_options (list[str] | None): Optional additional options to pass to the Nix build command. + """ if self._cache is None: self.prefetch() assert self._cache is not None diff --git a/pkgs/clan-cli/clan_cli/vars/generate.py b/pkgs/clan-cli/clan_cli/vars/generate.py index 7942df2d1..d229a0ff4 100644 --- a/pkgs/clan-cli/clan_cli/vars/generate.py +++ b/pkgs/clan-cli/clan_cli/vars/generate.py @@ -17,7 +17,7 @@ from clan_cli.completions import ( from clan_cli.errors import ClanError from clan_cli.git import commit_files from clan_cli.machines.inventory import get_all_machines, get_selected_machines -from clan_cli.nix import nix_shell, nix_test_store +from clan_cli.nix import nix_config, nix_shell, nix_test_store from clan_cli.vars._types import StoreBase from .check import check_vars @@ -489,7 +489,6 @@ def generate_vars( was_regenerated |= generate_vars_for_machine( machine, generator_name, regenerate, no_sandbox=no_sandbox ) - machine.flush_caches() except Exception as exc: errors += [(machine, exc)] if len(errors) == 1: @@ -515,6 +514,18 @@ def generate_command(args: argparse.Namespace) -> None: machines = get_all_machines(args.flake, args.option) else: machines = get_selected_machines(args.flake, args.option, args.machines) + + # prefetch all vars + config = nix_config() + system = config["system"] + machine_names = [machine.name for machine in machines] + # test + args.flake.precache( + [ + f"clanInternals.machines.{system}.{{{','.join(machine_names)}}}.config.clan.core.vars.generators.*.validationHash", + f"clanInternals.machines.{system}.{{{','.join(machine_names)}}}.config.system.clan.deployment.file", + ] + ) generate_vars(machines, args.generator, args.regenerate, no_sandbox=args.no_sandbox)