diff --git a/lib/modules.nix b/lib/modules.nix index 17bc1f1d766479c..f7711261998a2e6 100644 --- a/lib/modules.nix +++ b/lib/modules.nix @@ -807,6 +807,9 @@ let in warnDeprecation opt // { value = builtins.addErrorContext "while evaluating the option `${showOption loc}':" value; + # The merged value before applying the options `apply` function to it. + # In general though, `apply` should not be used, it's an anti-pattern. + beforeApply = res.mergedValue; inherit (res.defsFinal') highestPrio; definitions = map (def: def.value) res.defsFinal; files = map (def: def.file) res.defsFinal; diff --git a/lib/tests/modules.sh b/lib/tests/modules.sh index 750b1d025e02614..a571f6a963624a3 100755 --- a/lib/tests/modules.sh +++ b/lib/tests/modules.sh @@ -69,6 +69,8 @@ checkConfigOutput '^"one two"$' config.result ./shorthand-meta.nix checkConfigOutput '^true$' config.result ./test-mergeAttrDefinitionsWithPrio.nix +checkConfigOutput '^true$' config.okChecks ./before-apply.nix + # Check that a module argument is passed, also when a default is available # (but not needed) # diff --git a/lib/tests/modules/before-apply.nix b/lib/tests/modules/before-apply.nix new file mode 100644 index 000000000000000..cb0f917e5e77755 --- /dev/null +++ b/lib/tests/modules/before-apply.nix @@ -0,0 +1,24 @@ +{ options, lib, ... }: + +# Tests wheter a apply function properly generates the `beforeApply` option attribute + +{ + options = { + optionWithoutApply = lib.mkOption { + default = false; + type = lib.types.bool; + }; + + optionWithApply = lib.mkOption { + default = false; + type = lib.types.bool; + apply = x: !x; + }; + + okChecks = lib.mkOption {}; + }; + config.okChecks = builtins.addErrorContext "while evaluating the assertions" ( + assert options.optionWithoutApply.beforeApply == options.optionWithoutApply.value; + assert options.optionWithApply.beforeApply == !options.optionWithApply.value; + true); +}