diff --git a/modules/dynamicism/dynamicism.nix b/modules/dynamicism/dynamicism.nix index 482b364..1060f85 100644 --- a/modules/dynamicism/dynamicism.nix +++ b/modules/dynamicism/dynamicism.nix @@ -23,6 +23,8 @@ let subOpts = lib.mapAttrs (_: metaAttr: metaAttr.configuration.options) options.dynamicism.for.valueMeta.attrs; + seqTrue = v: lib.seq v true; + finalSettingsFor = { ... }@submod: recUpdateFoldl (optPath: lib.setAttrByPath optPath (lib.getAttrFromPath optPath config) ) submod.source-options; @@ -55,7 +57,9 @@ in type = t.attrsOf (t.submoduleWith { modules = [ ./submodule.nix ]; shorthandOnlyDefinesConfig = false; - specialArgs = { inherit pkgs; }; + specialArgs = { + host = { inherit pkgs options config; }; + }; }); default = { }; }; @@ -69,6 +73,12 @@ in ''; }; + applyDynamicConfiguration = mkOption { + #type = t.functionTo t.pathInStore; + type = t.functionTo t.raw; + readOnly = true; + }; + doChange = mkOption { type = t.functionTo t.pathInStore; readOnly = true; @@ -95,6 +105,45 @@ in ''; }; config.dynamicism = { + + applyDynamicConfiguration = { + baseConfiguration ? builtins.getEnv "NIXOS_CONFIG", + newConfiguration ? baseConfiguration + "/dynamic.nix", + }: let + locFor = appendage: lib.concatLists [ + opts.applyDynamicConfiguration.loc + [ "(function argument)" ] + (lib.toList appendage) + ]; + + _file = "«inline module in ${showOption opts.applyDynamicConfiguration.loc}»"; + + nixosBefore = evalNixos { + configuration = { ... }: { + inherit _file; + imports = [ baseConfiguration ]; + }; + }; + + nixosAfter = evalNixos { + configuration = { ... }: { + inherit _file; + imports = [ baseConfiguration newConfiguration ]; + }; + }; + + submodulesChanged = lib.filter (submodName: + nixosBefore.config.dynamicism.for.${submodName}.finalSettings + != + nixosAfter.config.dynamicism.for.${submodName}.finalSettings + ) (lib.attrNames config.dynamicism.for); + in + assert seqTrue (typeCheck (locFor "baseConfiguration") t.deferredModule baseConfiguration); + assert seqTrue (typeCheck (locFor "newConfiguration") t.deferredModule newConfiguration); + { + inherit submodulesChanged; + }; + doChange = { option, value, diff --git a/modules/dynamicism/lib.nix b/modules/dynamicism/lib.nix index a988ae4..a957f38 100644 --- a/modules/dynamicism/lib.nix +++ b/modules/dynamicism/lib.nix @@ -4,12 +4,12 @@ t = lib.types; in lib.fix (self: { /** Perform module-system type checking and resolving on a single option value. */ - typeCheck = loc: option: value: - assert lib.isOptionType option; + typeCheck = loc: optionType: value: + assert lib.isOptionType optionType; assert lib.isList loc; assert lib.all lib.isString loc; let - merged = lib.modules.mergeDefinitions loc option [ { + merged = lib.modules.mergeDefinitions loc optionType [ { inherit value; file = "«inline»"; } ]; diff --git a/modules/dynamicism/submodule.nix b/modules/dynamicism/submodule.nix index 50e0889..bf26b2a 100644 --- a/modules/dynamicism/submodule.nix +++ b/modules/dynamicism/submodule.nix @@ -1,8 +1,8 @@ { name, - pkgs, lib, config, + host, ... }: let @@ -19,6 +19,12 @@ let ; t = lib.types; + inherit (import ./lib.nix { inherit lib; }) + recUpdateFoldl + ; + + pkgs = host.pkgs; + /** Either a list of strings, or a dotted string that will be split. */ convenientAttrPath = t.coercedTo t.str (lib.splitString ".") (t.listOf t.str); @@ -59,6 +65,14 @@ in default = lib.attrNames config.unitDropins; }; + finalSettings = mkOption { + type = t.attrsOf t.raw; + internal = true; + default = recUpdateFoldl (optPath: + lib.setAttrByPath optPath (lib.getAttrFromPath optPath host.config) + ) config.source-options; + }; + configFile = mkOption { type = t.pathInStore; internal = true;