diff --git a/modules/aspects/dependencies.nix b/modules/aspects/dependencies.nix index 32ac447..6b83f41 100644 --- a/modules/aspects/dependencies.nix +++ b/modules/aspects/dependencies.nix @@ -75,8 +75,6 @@ let (statics den.default) (owned HM) (statics HM) - (owned OS) - (statics OS) (parametric.fixedTo context OS) ]; }; diff --git a/nix/fn-can-take.nix b/nix/fn-can-take.nix index 69a8e06..598aa5a 100644 --- a/nix/fn-can-take.nix +++ b/nix/fn-can-take.nix @@ -3,13 +3,14 @@ let check = params: func: let + givenFn = builtins.isFunction func || (builtins.isAttrs func && func ? __functor); givenArgs = builtins.isAttrs params; fargs = lib.functionArgs func; provided = builtins.attrNames params; args = lib.mapAttrsToList (name: optional: { inherit name optional; }) fargs; required = map (x: x.name) (lib.filter (x: !x.optional) args); intersection = lib.intersectLists required provided; - satisfied = givenArgs && lib.length required == lib.length intersection; + satisfied = givenFn && givenArgs && lib.length required == lib.length intersection; noExtras = lib.length required == lib.length provided; exactly = satisfied && noExtras; in diff --git a/nix/lib.nix b/nix/lib.nix index f058dff..ef1f87c 100644 --- a/nix/lib.nix +++ b/nix/lib.nix @@ -17,7 +17,7 @@ let }; }; - isFn = f: (builtins.isFunction f) || (f ? __functor); + isFn = f: (builtins.isFunction f) || (builtins.isAttrs f && f ? __functor); canTake = import ./fn-can-take.nix lib; # an aspect producing only owned configs @@ -33,9 +33,10 @@ let // { __functor = self: - # deadnix: skip - { class, aspect-chain }@ctx: - funk applyStatics self ctx; + { class, aspect-chain }: + { + includes = map (applyStatics { inherit class aspect-chain; }) self.includes; + }; }; applyStatics = @@ -51,10 +52,7 @@ let class = ""; aspect-chain = [ ]; }; - isCtxStatic = (lib.flip canTake.exactly) ( - # deadnix: skip - { class, aspect-chain }: true - ); + isCtxStatic = (lib.flip canTake.exactly) ({ class, aspect-chain }: class aspect-chain); take.unused = _unused: used: used; take.exactly = take canTake.exactly; @@ -66,39 +64,39 @@ let parametric.atLeast = funk (lib.flip take.atLeast); parametric.exactly = funk (lib.flip take.exactly); parametric.expands = - attrs: aspect: ctx: - parametric.fixedTo (ctx // attrs) aspect; + attrs: parametric.withOwn (aspect: ctx: parametric.atLeast aspect (ctx // attrs)); parametric.fixedTo = - ctx: aspect: - { class, aspect-chain }: - { - includes = [ - (parametric.atLeast aspect ctx) - (parametricStatics aspect { inherit class aspect-chain; }) - ]; + attrs: aspect: + aspect + // { + __functor = + self: + { class, aspect-chain }: + { + includes = [ + (owned self) + (statics self { inherit class aspect-chain; }) + (parametric.atLeast self attrs) + ]; + }; }; parametric.withOwn = functor: aspect: aspect // { __functor = self: ctx: { - includes = [ - (functor self ctx) - (parametricStatics self ctx) - ]; + includes = + if isCtxStatic ctx then + [ + (owned self) + (statics self ctx) + ] + else + [ (functor self ctx) ]; }; }; parametric.__functor = _: parametric.withOwn parametric.atLeast; - parametricStatics = self: ctx: { - includes = lib.optionals (isCtxStatic ctx) [ - (owned self) - { - includes = map (applyStatics ctx) self.includes; - } - ]; - }; - aspects = inputs.flake-aspects.lib lib; __findFile = import ./den-brackets.nix { inherit lib config; }; diff --git a/templates/examples/modules/_example/ci/parametric-with-owned.nix b/templates/examples/modules/_example/ci/parametric-with-owned.nix index 708150c..d25d2c2 100644 --- a/templates/examples/modules/_example/ci/parametric-with-owned.nix +++ b/templates/examples/modules/_example/ci/parametric-with-owned.nix @@ -1,28 +1,36 @@ -{ den, lib, ... }: +{ + den, + lib, + ... +}: let # a test module to check context was forwarded - fwdModule.nixos.options.fwd = { + fwdModule.options.fwd = { a = strOpt; b = strOpt; c = strOpt; d = strOpt; e = strOpt; f = strOpt; - # unlike strings, pkgs cannot be duplicated, we use this to + # unlike strings, pkgs cannot be duplicated/merged, we use this to # ensure no-dups are created from parametric owned modules. - pkg = lib.mkOption { type = lib.types.package; }; + pkg = pkgOpt; + pkg2 = pkgOpt; + pkg3 = pkgOpt; }; strOpt = lib.mkOption { type = lib.types.str; }; + pkgOpt = lib.mkOption { type = lib.types.package; }; inherit (den.lib) parametric; in { - den.aspects.rockhopper.includes = [ - fwdModule + { nixos.imports = [ fwdModule ]; } + { homeManager.imports = [ fwdModule ]; } den.aspects.fwd._.first ]; den.aspects.rockhopper.nixos.fwd.c = "host owned C"; + den.aspects.rockhopper.homeManager.fwd.a = "host home-managed A"; # this aspect will take any context and also forward it # into any includes function that can take same context. @@ -33,6 +41,11 @@ in fwd.a = "First owned A"; fwd.pkg = pkgs.hello; }; + homeManager = + { pkgs, ... }: + { + fwd.pkg = builtins.break pkgs.vim; + }; includes = [ den.aspects.fwd._.second { nixos.fwd.d = "First static includes D"; } @@ -46,8 +59,18 @@ in den.aspects.fwd._.second = { host, ... }: parametric.fixedTo { third = "Impact"; } { - nixos.fwd.b = "Second owned B for ${host.name}"; includes = [ den.aspects.fwd._.third ]; + nixos = + { pkgs, ... }: + { + fwd.b = "Second owned B for ${host.name}"; + fwd.pkg2 = pkgs.bat; + }; + homeManager = + { pkgs, ... }: + { + fwd.pkg2 = pkgs.helix; + }; }; den.aspects.fwd._.third = @@ -58,6 +81,16 @@ in den.aspects.fwd._.fourth = parametric.expands { planet = "Earth"; } { includes = [ den.aspects.fwd._.fifth ]; + nixos = + { pkgs, ... }: + { + fwd.pkg3 = pkgs.emacs-nox; + }; + homeManager = + { pkgs, ... }: + { + fwd.pkg3 = pkgs.emacs-nox; + }; }; den.aspects.fwd._.fifth = @@ -73,7 +106,12 @@ in }; perSystem = - { checkCond, rockhopper, ... }: + { + checkCond, + rockhopper, + alice-at-rockhopper, + ... + }: { checks.parametric-fwd-a = checkCond "fwd-a" (rockhopper.config.fwd.a == "First owned A"); checks.parametric-fwd-b = checkCond "fwd-b" ( @@ -83,7 +121,25 @@ in checks.parametric-fwd-d = checkCond "fwd-d" (rockhopper.config.fwd.d == "First static includes D"); checks.parametric-fwd-e = checkCond "fwd-e" (rockhopper.config.fwd.e == "Third Impact"); checks.parametric-fwd-f = checkCond "fwd-f" (rockhopper.config.fwd.f == "Fifth Earth rockhopper"); + checks.parametric-fwd-pkg = checkCond "fwd-pkg" (lib.getName rockhopper.config.fwd.pkg == "hello"); + checks.parametric-fwd-pkg2 = checkCond "fwd-pkg2" (lib.getName rockhopper.config.fwd.pkg2 == "bat"); + checks.parametric-fwd-pkg3 = checkCond "fwd-pkg3" ( + lib.getName rockhopper.config.fwd.pkg3 == "emacs-nox" + ); + + checks.parametric-fwd-hm-a = checkCond "fwd-hm-a" ( + alice-at-rockhopper.fwd.a == "host home-managed A" + ); + checks.parametric-fwd-hm-pkg = checkCond "fwd-hm-pkg" ( + lib.getName alice-at-rockhopper.fwd.pkg == "vim" + ); + checks.parametric-fwd-hm-pkg2 = checkCond "fwd-hm-pkg2" ( + lib.getName alice-at-rockhopper.fwd.pkg2 == "helix" + ); + checks.parametric-fwd-hm-pkg3 = checkCond "fwd-hm-pkg3" ( + lib.getName alice-at-rockhopper.fwd.pkg3 == "emacs-nox" + ); }; }