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

test accessing namespaces from inputs (#114)

Fix #113

authored by oeiuwq.com and committed by

GitHub 10da3d7c c8174a1e

+103 -18
+2 -1
nix/den-brackets.nix
··· 28 28 readFromAspects = lib.getAttrFromPath aspectsPath config; 29 29 30 30 headIsDenful = lib.hasAttrByPath [ "ful" head ] config.den; 31 - denfulTail = if lib.head tail == "provides" then lib.tail tail else tail; 31 + denfulTail = 32 + if builtins.length tail > 0 && lib.head tail == "provides" then lib.tail tail else tail; 32 33 denfulPath = [ 33 34 "den" 34 35 "ful"
+15 -8
nix/namespace.nix
··· 1 - name: input: 1 + name: sources: 2 2 { config, lib, ... }: 3 3 let 4 - isLocal = !builtins.isAttrs input; 5 - isOutput = isLocal && input == true; 4 + from = lib.flatten [ sources ]; 5 + isOutput = builtins.any (x: x == true) from; 6 + denfuls = map (lib.getAttrFromPath [ 7 + "denful" 8 + name 9 + ]) (builtins.filter builtins.isAttrs from); 10 + 11 + sourceModule = { 12 + config.den.ful.${name} = lib.mkMerge denfuls; 13 + }; 6 14 7 15 aliasModule = lib.mkAliasOptionModule [ name ] [ "den" "ful" name ]; 8 16 9 17 type = lib.types.attrsOf config.den.lib.aspects.types.providerType; 10 18 11 - source = if isLocal then { } else input.denful.${name}; 12 - output = 19 + outputModule = 13 20 if isOutput then 14 21 { 15 22 config.flake.denful.${name} = config.den.ful.${name}; 16 - options.flake.denful.${name} = lib.mkOption { inherit type; }; 23 + options.flake.denful.${name} = lib.mkOption { type = lib.types.raw; }; 17 24 } 18 25 else 19 26 { }; 20 27 in 21 28 { 22 29 imports = [ 30 + sourceModule 23 31 aliasModule 24 - output 32 + outputModule 25 33 ]; 26 34 config._module.args.${name} = config.den.ful.${name}; 27 - config.den.ful.${name} = source; 28 35 options.den.ful.${name} = lib.mkOption { inherit type; }; 29 36 }
+7 -6
templates/default/modules/namespace.nix
··· 1 1 { inputs, den, ... }: 2 2 { 3 - # create an `eg` (example!) namespace. 4 - imports = [ (inputs.den.namespace "eg" false) ]; 3 + # create an `eg` (example!) namespace. (flake exposed) 4 + imports = [ (inputs.den.namespace "eg" true) ]; 5 5 6 - # you can have more than one namespace, create yours. 7 - # imports = [ (inputs.den.namespace "yours" true) ]; 6 + # you can have more than one namespace (false = not flake exposed) 7 + # imports = [ (inputs.den.namespace "my" false) ]; 8 8 9 - # you can also import namespaces from remote flakes. 10 - # imports = [ (inputs.den.namespace "ours" inputs.theirs) ]; 9 + # you can also merge many namespaces from remote flakes. 10 + # keep in mind a namespace is defined only once, so give it an array: 11 + # imports = [ (inputs.den.namespace "ours" [inputs.ours inputs.theirs]) ]; 11 12 12 13 # this line enables den angle brackets syntax in modules. 13 14 _module.args.__findFile = den.lib.__findFile;
+1 -1
templates/examples/modules/_example/ci/builds.nix
··· 22 22 }; 23 23 in 24 24 { 25 - checks = checks.${pkgs.system} or { }; 25 + checks = checks.${pkgs.stdenv.hostPlatform.system} or { }; 26 26 }; 27 27 }
+78 -2
templates/examples/modules/_example/ci/namespace.nix
··· 1 - { inputs, den, ... }: 2 1 { 3 - imports = [ (inputs.den.namespace "eg" false) ]; 2 + inputs, 3 + den, 4 + lib, 5 + eg, 6 + # deadnix: skip 7 + __findFile ? __findFile, 8 + ... 9 + }: 10 + let 11 + # module for testing inclusion of namespaces 12 + simsModule.nixos.options.sims = lib.mkOption { 13 + type = lib.types.listOf lib.types.str; 14 + }; 15 + in 16 + { 17 + # enable <angle/bracket> syntax for finding aspects. 4 18 _module.args.__findFile = den.lib.__findFile; 19 + 20 + imports = [ 21 + # create a local namespace and output at flake.denful.eg 22 + (inputs.den.namespace "eg" true) 23 + 24 + # you can also mount a namespace from many input sources. 25 + # the second argument becomes an array of inputs. 26 + ( 27 + let 28 + # NOTE: here we simulate inputA and inputB are flakes. 29 + inputA.denful.sim.ul._.a._.tion.nixos.sims = [ "from inputA" ]; 30 + inputB.denful.sim.ul._.a._.tion.nixos.sims = [ "from inputB" ]; 31 + exposeToFlake = true; 32 + in 33 + inputs.den.namespace "sim" [ 34 + inputA 35 + inputB 36 + exposeToFlake 37 + ] 38 + ) 39 + ]; 40 + 41 + # define nested aspects in local namespace 42 + eg.foo.provides.bar.provides.baz = { 43 + nixos.sims = [ "local <eg/foo/bar/baz>" ]; 44 + }; 45 + 46 + # augment aspects on a mounted namespace 47 + sim.ul._.a._.tion.nixos.sims = [ "augmented <sim/ul/a/tion>" ]; 48 + 49 + den.aspects.rockhopper.includes = [ 50 + simsModule 51 + <eg/foo/bar/baz> 52 + <sim/ul/a/tion> 53 + ]; 54 + 55 + perSystem = 56 + { checkCond, rockhopper, ... }: 57 + { 58 + checks.namespace-eg-flake-output = checkCond "namespace enabled as flake output" ( 59 + eg == den.ful.eg && eg == <eg> && eg == inputs.self.denful.eg 60 + ); 61 + 62 + checks.namespace-eg-provides-accessible = checkCond "exact same value" ( 63 + eg.foo._.bar._.baz == <eg/foo/bar/baz> 64 + && eg.foo._.bar._.baz == inputs.self.denful.eg.foo._.bar._.baz 65 + ); 66 + 67 + checks.namespace-sim-merged = checkCond "merges from all sources" ( 68 + let 69 + expected = [ 70 + "augmented <sim/ul/a/tion>" 71 + "from inputA" 72 + "from inputB" 73 + "local <eg/foo/bar/baz>" 74 + ]; 75 + actual = lib.sort (a: b: a < b) rockhopper.config.sims; 76 + in 77 + expected == actual 78 + ); 79 + 80 + }; 5 81 }