From fdd007fdd778c60aa008af73bccc845770b6b5bb Mon Sep 17 00:00:00 2001 From: Atemu Date: Sun, 13 Oct 2024 19:33:19 +0200 Subject: [PATCH] lib: add option parameter for default value priority When you define an option's default value, the expectation is that whenever the option is set somewhere, the default value will be overridden by that setting rather than merged. It's sometimes the case however that your option's default value should be merged with what is being set rather than overwritten by it; only allowing explicit overrides via `mkForce`. Creating such an option was not possible previously as all options' default values were forcefully clamped via mkOptionDefault. There were some workarounds such as creating additional options ("things" + "extraThings") which you'd then have to explain to users and generally aren't ergonomical to use. Another workaround was to explicitly set options value to the default value in the implementation but those two lines of code might be many lines apart from another and it's generally an odd pattern. Example: { options.foo = lib.mkOption { default = [ "foo" ]; }; # Many more lines of code config.foo = options.foo.default; } It is now possible to control this behaviour at option declaration which is much clearer in the code and is introspect-able. { options.foo = lib.mkOption { default = [ "foo" ]; defaultPriority = lib.modules.priorities.baseline; }; # Many more lines of code } The implementation is trivial. If this becomes used more widely, it should be rendered in the generated options manual and nixos-search. --- lib/modules.nix | 8 +++++--- lib/options.nix | 2 ++ 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/lib/modules.nix b/lib/modules.nix index 9ec0a7351c3c7..ad3595218ce0a 100644 --- a/lib/modules.nix +++ b/lib/modules.nix @@ -787,9 +787,11 @@ let evalOptionValue = loc: opt: defs: let # Add in the default value for this option, if any. - defs' = - (optional (opt ? default) - { file = head opt.declarations; value = mkOptionDefault opt.default; }) ++ defs; + defs' = (optional (opt ? default) { + file = head opt.declarations; + value = mkOverride (opt.defaultPriority or priorities.optionDefault) opt.default; + }) + ++ defs; # Handle properties, check types, and merge everything together. res = diff --git a/lib/options.nix b/lib/options.nix index f4d0d9d36cfc9..4d37783c8ab11 100644 --- a/lib/options.nix +++ b/lib/options.nix @@ -67,6 +67,8 @@ rec { { # Default value used when no definition is given in the configuration. default ? null, + # Which priority to assign to the default value. This can be used to control whether the default is be merged or overridden when the option is set. + defaultPriority ? lib.modules.priorities.optionDefault, # Textual representation of the default, for the manual. defaultText ? null, # Example value used in the manual.