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(batteries): den._.bidirectional uses fixedTo to include from host. (#298)

Fixes #297

cc @drupol see changes at bidirectional documentation

authored by

Victor Borja and committed by
GitHub
e62bc38b 0c7ee5ec

+145 -37
+17 -1
docs/src/content/docs/guides/bidirectional.mdx
··· 124 124 125 125 ``` 126 126 127 - <Aside title="Potential duplicates by igloo.includes Functions" type="caution"> 127 + <Aside title="Potential Duplicates by Host Aspect" type="caution"> 128 + **Under Bidirectionality**, the igloo aspect is activated more than once! 129 + 128 130 Notice that `den.aspects.igloo.includes` functions are called **with** `{ host }` and **later with** `{ host, user }` **per-user**. 129 131 130 132 Because the list of functions at `igloo.includes` get invoked more than once, with different contexts, ··· 136 138 137 139 # avoid being called with `{host}` 138 140 den.lib.perUser ({ host, user }: ...) 141 + ``` 142 + 143 + Static aspects (plain-attrsets) or host-owned classes at a Host-aspect 144 + have **no way** to distinguish when the calling context is 145 + `{host}` or `{host,user}`, **only functions** are context-aware. 146 + 147 + ``` 148 + # Lists, packages, options at host-level would cause duplicates 149 + # den.aspects.igloo.nixos.options.foo = lib.mkOption {}; 150 + 151 + # Instead, use perHost to define unique values: 152 + den.aspects.igloo.includes = [ 153 + (perHost { nixos.options.foo = lib.mkOption {}; }) 154 + ]; 139 155 ``` 140 156 141 157 Read the documentation at [`context/user.nix`](https://github.com/vic/den/blob/main/modules/context/user.nix) for all the details.
+22 -22
modules/context/user.nix
··· 33 33 Enable for all users: 34 34 den.ctx.user.includes = [ den._.bidirectional ]; 35 35 36 - IMPORTANT: Enabling bidirectionality means that the following piepline is enabled: 36 + IMPORTANT: Enabling bidirectionality means that the following pipeline is enabled: 37 37 38 38 host-aspect{host} => user-aspect{host,user} => host-aspect{host,user} 39 39 40 - This means that any function at host-aspect.includes can be called: 40 + Notice that the host-aspect is being activated more than once! 41 + 42 + This means that host configurations are obtained 41 43 - once when the host is obtaining its own configuration with context {host} 42 44 - once PER user that has bidirectionality enabled with context {host,user} 43 45 44 - Because of this, parametric aspects at host-aspect must be careful 45 - 46 - Instead of -in Nix both of these have the same functionArgs- 47 - 48 - ({host}: ...) 49 - 50 - or 46 + Due to Nix `lib.functionArgs` not distinguishing between `{host}` and `{host, ...}`, 47 + Den provides these utilities built upon `den.lib.take.exactly`: 51 48 52 - ({host, ...}: ...) 53 - 54 - Do this to prevent the function being invoked with `{host,user}` 55 - 49 + # Do this to prevent being invoked with `{host,user}` 56 50 den.lib.perHost ({host}: ...) 57 51 58 - Or this to avoid it being invoked with `{host}` 59 - 52 + # Do this to prevent being invoked with `{host}` 60 53 den.lib.perUser ({host,user}: ...) 61 54 62 - Static aspects, -functions like `{class,aspect-chain}: ...`- at host-aspect.includes 63 - have **no way** to distinguish when the calling context is `{host}` or `{host,user}` if 64 - bidirectionality is enabled. 55 + Static aspects (plain-attrsets) or host-owned classes at a Host-aspect 56 + have **no way** to distinguish when the calling context is 57 + `{host}` or `{host,user}`, only functions are context-aware. 65 58 66 - Because of this, if you have such functions, they might produce duplicate values on list or 67 - conflicting values on package types. A work around is to wrap them in a context-aware function: 59 + Because of this, a host-aspect might produce duplicate values on list, 60 + package types, or unique values like options: 68 61 69 - den.lib.perHost ({host}: {class, aspect-chain}: ...) 62 + # lists, packages and options need to be unique. 63 + # this line would produce duplicate errors IF bidirectional enabled 64 + den.aspects.igloo.nixos.options.foo = lib.mkOption {}; 70 65 66 + # Instead, wrap in perHost things that must be unique 67 + den.aspects.igloo.includes = [ 68 + (den.lib.perHost { nixos.options.foo = lib.mkOption {}; }) 69 + ] 71 70 ''; 72 71 73 72 ctx.user.into.default = lib.singleton; ··· 75 74 ctx.user.provides.bidirectional = take.exactly from-host; 76 75 77 76 from-user = { host, user }: fixedTo { inherit host user; } den.aspects.${user.aspect}; 78 - from-host = { host, user }: atLeast den.aspects.${host.aspect} { inherit host user; }; 77 + 78 + from-host = { host, user }: fixedTo { inherit host user; } den.aspects.${host.aspect}; 79 79 80 80 in 81 81 {
+1
nix/lib/ctx-apply.nix
··· 9 9 "into" 10 10 "provides" 11 11 "__functor" 12 + "__functionArgs" 12 13 "modules" 13 14 "resolve" 14 15 "_module"
+4 -4
templates/bogus/modules/test-base.nix
··· 28 28 29 29 denModule = { 30 30 imports = [ inputs.den.flakeModule ]; 31 - den.default.homeManager.home.stateVersion = "26.05"; 32 - den.default.nixos = { 33 - system.stateVersion = "26.05"; 31 + den.ctx.host.nixos = { 32 + system.stateVersion = lib.mkDefault "26.05"; 34 33 boot.loader.grub.enable = lib.mkForce false; 35 34 fileSystems."/".device = lib.mkForce "/dev/fake"; 36 35 }; 37 - den.schema.user.classes = lib.mkDefault [ "homeManager " ]; 36 + den.ctx.user.homeManager.home.stateVersion = lib.mkDefault "26.05"; 37 + den.schema.user.classes = lib.mkDefault [ "homeManager" ]; 38 38 }; 39 39 40 40 testModule = {
+4 -2
templates/ci/modules/features/context/host-propagation.nix
··· 176 176 "host-lax {host,user}" 177 177 "host-lax {host}" 178 178 179 - "host-owned" 180 - "host-static" 179 + "host-owned" # host 180 + "host-owned" # user bidirectional 181 + "host-static" # host 182 + "host-static" # user bidirectional 181 183 182 184 "user-exact" 183 185 "user-lax {host,user}"
+91
templates/ci/modules/features/deadbugs/issue-297-bidirectional-not-including-host-owned-and-included-statics.nix
··· 1 + { denTest, ... }: 2 + { 3 + flake.tests.deadbugs-issue-297 = { 4 + 5 + test-bidirectional-host-owned = denTest ( 6 + { 7 + den, 8 + lib, 9 + igloo, # igloo = nixosConfigurations.igloo.config 10 + tuxHm, # tuxHm = igloo.home-manager.users.tux 11 + ... 12 + }: 13 + { 14 + den.hosts.x86_64-linux.igloo.users.tux.classes = [ "homeManager" ]; 15 + den.ctx.user.includes = [ den._.bidirectional ]; 16 + 17 + den.aspects.igloo.homeManager.home.keyboard.model = "denkbd"; 18 + 19 + expr = tuxHm.home.keyboard.model; 20 + expected = "denkbd"; 21 + } 22 + ); 23 + 24 + test-bidirectional-host-included-statics = denTest ( 25 + { 26 + den, 27 + lib, 28 + igloo, # igloo = nixosConfigurations.igloo.config 29 + tuxHm, # tuxHm = igloo.home-manager.users.tux 30 + ... 31 + }: 32 + { 33 + den.hosts.x86_64-linux.igloo.users.tux.classes = [ "homeManager" ]; 34 + den.ctx.user.includes = [ den._.bidirectional ]; 35 + 36 + den.aspects.base.homeManager.home.keyboard.model = "denkbd"; 37 + den.aspects.igloo.includes = [ den.aspects.base ]; 38 + 39 + expr = tuxHm.home.keyboard.model; 40 + expected = "denkbd"; 41 + } 42 + ); 43 + 44 + test-bidirectional-host-owned-home-option = denTest ( 45 + { 46 + den, 47 + lib, 48 + igloo, # igloo = nixosConfigurations.igloo.config 49 + tuxHm, # tuxHm = igloo.home-manager.users.tux 50 + ... 51 + }: 52 + { 53 + den.hosts.x86_64-linux.igloo.users.tux.classes = [ "homeManager" ]; 54 + den.ctx.user.includes = [ den._.bidirectional ]; 55 + 56 + den.aspects.igloo.homeManager.options.foo = lib.mkOption { default = "foo"; }; 57 + 58 + expr = tuxHm.foo; 59 + expected = "foo"; 60 + } 61 + ); 62 + 63 + test-bidirectional-host-owned-host-option = denTest ( 64 + { 65 + den, 66 + lib, 67 + igloo, # igloo = nixosConfigurations.igloo.config 68 + tuxHm, # tuxHm = igloo.home-manager.users.tux 69 + ... 70 + }: 71 + { 72 + den.hosts.x86_64-linux.igloo.users.tux.classes = [ "homeManager" ]; 73 + den.ctx.user.includes = [ den._.bidirectional ]; 74 + 75 + # NOTE: this causes an error: Option already defined! 76 + # This is because bidirectionality includes host configs again. 77 + # den.aspects.igloo.nixos.options.foo = lib.mkOption { default = "foo"; }; 78 + # NOTE: Under bidirectionality, use perHost 79 + den.aspects.igloo.includes = [ 80 + (den.lib.perHost { 81 + nixos.options.foo = lib.mkOption { default = "foo"; }; 82 + }) 83 + ]; 84 + 85 + expr = igloo.foo; 86 + expected = "foo"; 87 + } 88 + ); 89 + 90 + }; 91 + }
+3 -1
templates/ci/modules/features/perUser-perHost.nix
··· 79 79 80 80 den.ctx.user.includes = [ den._.bidirectional ]; 81 81 82 - den.aspects.igloo.nixos.options.funny = lib.mkOption { 82 + # NOTE: Since options must be unique, include via perHost 83 + den.aspects.funMod.nixos.options.funny = lib.mkOption { 83 84 default = [ ]; 84 85 type = lib.types.listOf lib.types.str; 85 86 }; 86 87 87 88 den.aspects.igloo.includes = [ 89 + (den.lib.perHost den.aspects.funMod) 88 90 89 91 (den.lib.perHost { nixos.funny = [ "atHost perHost static" ]; }) 90 92 (den.lib.perHost (
+3 -7
templates/ci/modules/features/user-host-bidirectional-config.nix
··· 50 50 pinguHm.programs.direnv.enable 51 51 ]; 52 52 expected = [ 53 - false 54 - false 53 + true 54 + true 55 55 ]; 56 56 } 57 57 ); ··· 73 73 74 74 den.aspects.igloo.includes = [ 75 75 { 76 - homeManager.programs.direnv.enable = throw "unreachable, static includes wont be used by bidirectionality"; 77 - } 78 - # This is the way, walk in it: 79 - (den.lib.perUser { 80 76 homeManager.programs.direnv.enable = true; 81 - }) 77 + } 82 78 ]; 83 79 84 80 expr = [