mirror of
https://github.com/mjallen18/snowfall-lib.git
synced 2026-04-18 00:55:58 -05:00
fix(home): forward exported hm args
Resolve exported home configurations against their parent system config so hosted and bare-name homes keep the same Home Manager specialArgs on package and homeConfiguration export paths. This restores arbitrary home-manager.extraSpecialArgs keys instead of only hardcoded aliases and adds regression coverage for the export resolver.
This commit is contained in:
72
flake.nix
72
flake.nix
@@ -107,6 +107,54 @@
|
||||
inherit system;
|
||||
};
|
||||
standalone-special-args = standalone-home.specialArgs;
|
||||
exported-home-name = "test@${system}";
|
||||
resolved-exported-home = lib.snowfall.flake.resolve-exported-home {
|
||||
home-name = exported-home-name;
|
||||
home = {
|
||||
modules = [ ];
|
||||
inherit system;
|
||||
specialArgs = {
|
||||
host = "";
|
||||
user = "test";
|
||||
standaloneOnly = true;
|
||||
};
|
||||
builder = args: args.specialArgs;
|
||||
};
|
||||
systems = {
|
||||
test-host = {
|
||||
output = "nixosConfigurations";
|
||||
inherit system;
|
||||
};
|
||||
};
|
||||
flake-outputs = {
|
||||
nixosConfigurations = {
|
||||
test-host = {
|
||||
config = {
|
||||
hostName = "test-host";
|
||||
home-manager = {
|
||||
users.test = { };
|
||||
extraSpecialArgs = {
|
||||
arbitraryName = "ok";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
homeConfigurations = {
|
||||
${exported-home-name} = {
|
||||
fallback = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
bare-name-package-alias =
|
||||
"homeConfigurations-"
|
||||
+ (
|
||||
if pkgs.lib.hasSuffix "@${system}" exported-home-name then
|
||||
pkgs.lib.removeSuffix "@${system}" exported-home-name
|
||||
else
|
||||
exported-home-name
|
||||
);
|
||||
eval = builtins.tryEval {
|
||||
snowfall-attrs = builtins.attrNames lib.snowfall;
|
||||
has-standalone-home-placeholders =
|
||||
@@ -115,13 +163,33 @@
|
||||
&& (standalone-special-args ? systemConfig)
|
||||
&& (standalone-special-args.systemConfig == null);
|
||||
has-system-config-aliases =
|
||||
(builtins.length (builtins.split "systemConfig = config;" (builtins.readFile ./modules/nixos/user/default.nix)) > 1)
|
||||
&& (builtins.length (builtins.split "systemConfig = config;" (builtins.readFile ./modules/darwin/user/default.nix)) > 1);
|
||||
(
|
||||
builtins.length (
|
||||
builtins.split "systemConfig = config;" (builtins.readFile ./modules/nixos/user/default.nix)
|
||||
) > 1
|
||||
)
|
||||
&& (
|
||||
builtins.length (
|
||||
builtins.split "systemConfig = config;" (builtins.readFile ./modules/darwin/user/default.nix)
|
||||
) > 1
|
||||
);
|
||||
resolves-exported-home-extra-special-args =
|
||||
resolved-exported-home ? arbitraryName
|
||||
&& (resolved-exported-home.arbitraryName == "ok")
|
||||
&& (resolved-exported-home ? systemConfig)
|
||||
&& (resolved-exported-home.systemConfig.hostName == "test-host")
|
||||
&& (resolved-exported-home ? osConfig)
|
||||
&& (resolved-exported-home.osConfig.hostName == "test-host")
|
||||
&& (resolved-exported-home ? standaloneOnly)
|
||||
&& resolved-exported-home.standaloneOnly;
|
||||
strips-bare-home-package-alias = bare-name-package-alias == "homeConfigurations-test";
|
||||
};
|
||||
in
|
||||
assert eval.success;
|
||||
assert eval.value.has-standalone-home-placeholders;
|
||||
assert eval.value.has-system-config-aliases;
|
||||
assert eval.value.resolves-exported-home-extra-special-args;
|
||||
assert eval.value.strips-bare-home-package-alias;
|
||||
{
|
||||
snowfall-lib-eval = pkgs.runCommand "snowfall-lib-eval" { } "mkdir -p $out";
|
||||
}
|
||||
|
||||
@@ -86,6 +86,89 @@ let
|
||||
"snowfall"
|
||||
];
|
||||
|
||||
## Resolve the parent system config for an exported home configuration.
|
||||
## Explicit `user@host` names map directly. Hostless names end up normalized
|
||||
## to `user@system`, so fall back to a unique system-target match.
|
||||
#@ Attrs -> Attrs | Null
|
||||
resolve-exported-home-host-config =
|
||||
{
|
||||
home,
|
||||
systems,
|
||||
flake-outputs,
|
||||
}:
|
||||
let
|
||||
get-host-config =
|
||||
host-name:
|
||||
let
|
||||
system-output = systems.${host-name}.output;
|
||||
in
|
||||
flake-outputs.${system-output}.${host-name}.config;
|
||||
|
||||
requested-host = home.specialArgs.host or "";
|
||||
requested-system = home.system or "";
|
||||
requested-user = home.specialArgs.user or "";
|
||||
host-candidates =
|
||||
if requested-host != "" && systems ? ${requested-host} then
|
||||
[ requested-host ]
|
||||
else
|
||||
pipe systems [
|
||||
(filterAttrs (
|
||||
host-name: system-config:
|
||||
let
|
||||
host-config = get-host-config host-name;
|
||||
matches-explicit-target =
|
||||
requested-host != ""
|
||||
&& system-config.system == requested-host
|
||||
&& requested-user != ""
|
||||
&& builtins.hasAttr requested-user (host-config.home-manager.users or { });
|
||||
matches-hostless-home =
|
||||
requested-host == ""
|
||||
&& system-config.system == requested-system
|
||||
&& requested-user != ""
|
||||
&& builtins.hasAttr requested-user (host-config.home-manager.users or { });
|
||||
in
|
||||
matches-explicit-target || matches-hostless-home
|
||||
))
|
||||
builtins.attrNames
|
||||
];
|
||||
in
|
||||
if builtins.length host-candidates == 1 then
|
||||
get-host-config (builtins.head host-candidates)
|
||||
else
|
||||
null;
|
||||
|
||||
## Rebuild a hosted home export with the resolved parent system config so
|
||||
## Home Manager module arguments stay consistent on export paths.
|
||||
#@ Attrs -> Attrs
|
||||
resolve-exported-home =
|
||||
{
|
||||
home-name,
|
||||
home,
|
||||
systems,
|
||||
flake-outputs,
|
||||
}:
|
||||
let
|
||||
host-config = flake.resolve-exported-home-host-config {
|
||||
inherit home systems flake-outputs;
|
||||
};
|
||||
hosted-special-args =
|
||||
if host-config != null then
|
||||
{
|
||||
osConfig = host-config;
|
||||
systemConfig = host-config;
|
||||
}
|
||||
// (host-config.home-manager.extraSpecialArgs or { })
|
||||
else
|
||||
{ };
|
||||
in
|
||||
if host-config != null then
|
||||
home.builder {
|
||||
inherit (home) modules;
|
||||
specialArgs = home.specialArgs // hosted-special-args;
|
||||
}
|
||||
else
|
||||
flake-outputs.homeConfigurations.${home-name};
|
||||
|
||||
## Transform an attribute set of inputs into an attribute set where the values are the inputs' `lib` attribute. Entries without a `lib` attribute are removed.
|
||||
## Example Usage:
|
||||
## ```nix
|
||||
@@ -208,30 +291,15 @@ let
|
||||
|
||||
flake-utils-plus-outputs = core-inputs.flake-utils-plus.lib.mkFlake flake-options;
|
||||
|
||||
resolve-hosted-home =
|
||||
home-name: home:
|
||||
let
|
||||
host = home.specialArgs.host or "";
|
||||
has-hosted-system = host != "" && systems ? ${host};
|
||||
in
|
||||
if has-hosted-system then
|
||||
let
|
||||
system-output = systems.${host}.output;
|
||||
host-config = flake-utils-plus-outputs.${system-output}.${host}.config;
|
||||
in
|
||||
home.builder {
|
||||
inherit (home) modules;
|
||||
specialArgs = home.specialArgs // {
|
||||
osConfig = host-config;
|
||||
systemConfig = host-config;
|
||||
};
|
||||
}
|
||||
else
|
||||
flake-utils-plus-outputs.homeConfigurations.${home-name};
|
||||
|
||||
# Hosted homes need their parent system config injected before standalone
|
||||
# homeConfigurations or activation packages are forced.
|
||||
home-configurations = mapAttrs resolve-hosted-home homes;
|
||||
home-configurations = mapAttrs (
|
||||
home-name: home:
|
||||
flake.resolve-exported-home {
|
||||
inherit home-name home systems;
|
||||
flake-outputs = flake-utils-plus-outputs;
|
||||
}
|
||||
) homes;
|
||||
|
||||
flake-outputs = flake-utils-plus-outputs // {
|
||||
inherit overlays;
|
||||
|
||||
Reference in New Issue
Block a user