Modular, context-aware and aspect-oriented dendritic Nix configurations. Discussions: https://oeiuwq.zulipchat.com/join/nqp26cd4kngon6mo3ncgnuap/ den.oeiuwq.com
configurations den dendritic nix aspect oriented
8
fork

Configure Feed

Select the types of activity you want to include in your feed.

fix: perHost/perUser/perHome preserve aspect identity (#410)

Return { includes = [fn] } instead of a bare function, matching the POC
pattern. The function result lives in includes where
parametric.applyIncludes handles it with withIdentity, preserving the
aspect name through resolution. Fixes #408.

authored by

Jason Bowman and committed by
GitHub
d266c3a0 737843b6

+97 -5
+3 -3
modules/context/perHost-perUser.nix
··· 7 7 let 8 8 inherit (config.den.lib) take parametric; 9 9 fixed = ctx: aspect: parametric.fixedTo ctx { includes = [ aspect ]; }; 10 - perHost = aspect: take.exactly ({ host }@ctx: fixed ctx aspect); 11 - perUser = aspect: take.exactly ({ host, user }@ctx: fixed ctx aspect); 12 - perHome = aspect: take.exactly ({ home }@ctx: fixed ctx aspect); 10 + perHost = aspect: { includes = [ (take.exactly ({ host }@ctx: fixed ctx aspect)) ]; }; 11 + perUser = aspect: { includes = [ (take.exactly ({ host, user }@ctx: fixed ctx aspect)) ]; }; 12 + perHome = aspect: { includes = [ (take.exactly ({ home }@ctx: fixed ctx aspect)) ]; }; 13 13 in 14 14 { 15 15 den.lib = { inherit perHome perUser perHost; };
+13 -1
nix/lib/aspects/types.nix
··· 154 154 } 155 155 ); 156 156 157 - aspectsType = cnf: lib.types.submodule { freeformType = lib.types.lazyAttrsOf (providerType cnf); }; 157 + # Wrap non-module functions into { includes = [fn] } so they don't get 158 + # treated as module functions by aspectType's submodule merge. 159 + coercedProviderType = 160 + cnf: 161 + let 162 + pt = providerType cnf; 163 + in 164 + lib.types.coercedTo (lib.types.addCheck lib.types.raw ( 165 + v: builtins.isFunction v && !isSubmoduleFn v 166 + )) (fn: { includes = [ fn ]; }) pt; 167 + 168 + aspectsType = 169 + cnf: lib.types.submodule { freeformType = lib.types.lazyAttrsOf (coercedProviderType cnf); }; 158 170 159 171 in 160 172 {
+10 -1
nix/lib/take.nix
··· 3 3 asIs = _: lib.id; 4 4 upTo = f: builtins.intersectAttrs (lib.functionArgs f); 5 5 6 + # Carry name from the function to its result when the result doesn't 7 + # already have one. This preserves aspect identity through take calls. 8 + carryAttrs = 9 + fn: result: 10 + if builtins.isAttrs result then 11 + result // lib.optionalAttrs ((fn.name or null) != null && !(result ? name)) { inherit (fn) name; } 12 + else 13 + result; 14 + 6 15 take.unused = _unused: used: used; 7 16 8 17 take.exactly = take den.lib.canTake.exactly asIs; ··· 14 23 let 15 24 ctx = argAdapter fn args; 16 25 in 17 - if canTake ctx fn then fn ctx else { }; 26 + if canTake ctx fn then carryAttrs fn (fn ctx) else { }; 18 27 in 19 28 take
+28
templates/ci/modules/features/aspect-path.nix
··· 195 195 } 196 196 ); 197 197 198 + # perHost parametric aspects should appear in trace by name 199 + test-perHost-visible-in-trace = denTest ( 200 + { den, ... }: 201 + { 202 + den.aspects.role.includes = with den.aspects; [ 203 + leaf 204 + param 205 + ]; 206 + den.aspects.leaf.nixos = { }; 207 + den.aspects.param = den.lib.perHost ( 208 + { host }: 209 + { 210 + nixos = { }; 211 + } 212 + ); 213 + 214 + expr = with den.lib.aspects; resolve.withAdapter adapters.trace "nixos" den.aspects.role; 215 + expected.trace = [ 216 + "role" 217 + [ "leaf" ] 218 + [ 219 + "param" 220 + [ "[definition 1-entry 1]" ] 221 + ] 222 + ]; 223 + } 224 + ); 225 + 198 226 }; 199 227 }
+43
templates/ci/modules/features/deadbugs/issue-408-bare-function-aspect.nix
··· 1 + # Bare function aspect merged with static config. 2 + # https://github.com/vic/den/pull/408 3 + { denTest, lib, ... }: 4 + { 5 + flake.tests.deadbugs-issue-408 = { 6 + test-function-aspect-with-static-merge = denTest ( 7 + { den, igloo, ... }: 8 + { 9 + den.hosts.x86_64-linux.igloo.users.tux = { }; 10 + den.aspects.igloo.includes = [ den.aspects.foo ]; 11 + 12 + imports = 13 + let 14 + one = { 15 + den.aspects.foo = 16 + { host, ... }: 17 + { 18 + nixos.environment.sessionVariables.FOO = host.name; 19 + }; 20 + }; 21 + two = { 22 + den.aspects.foo.nixos = 23 + { pkgs, ... }: 24 + { 25 + environment.systemPackages = [ pkgs.hello ]; 26 + }; 27 + }; 28 + in 29 + [ 30 + one 31 + two 32 + ]; 33 + 34 + expr = { 35 + hello = lib.elem "hello" (map lib.getName igloo.environment.systemPackages); 36 + FOO = igloo.environment.sessionVariables.FOO; 37 + }; 38 + expected.FOO = "igloo"; 39 + expected.hello = true; 40 + } 41 + ); 42 + }; 43 + }