mirror of
https://github.com/NixOS/nixpkgs.git
synced 2024-11-27 01:13:05 +00:00
Merge pull request #242812 from hercules-ci/modules-remove-byName-obfuscation
module system: Clean up and improve an error message
This commit is contained in:
commit
0b339c824c
113
lib/modules.nix
113
lib/modules.nix
@ -539,59 +539,74 @@ let
|
||||
|
||||
mergeModules' = prefix: options: configs:
|
||||
let
|
||||
/* byName is like foldAttrs, but will look for attributes to merge in the
|
||||
specified attribute name.
|
||||
|
||||
byName "foo" (module: value: ["module.hidden=${module.hidden},value=${value}"])
|
||||
[
|
||||
{
|
||||
hidden="baz";
|
||||
foo={qux="bar"; gla="flop";};
|
||||
}
|
||||
{
|
||||
hidden="fli";
|
||||
foo={qux="gne"; gli="flip";};
|
||||
}
|
||||
]
|
||||
===>
|
||||
{
|
||||
gla = [ "module.hidden=baz,value=flop" ];
|
||||
gli = [ "module.hidden=fli,value=flip" ];
|
||||
qux = [ "module.hidden=baz,value=bar" "module.hidden=fli,value=gne" ];
|
||||
}
|
||||
*/
|
||||
byName = attr: f: modules:
|
||||
zipAttrsWith (n: concatLists)
|
||||
(map (module: let subtree = module.${attr}; in
|
||||
# an attrset 'name' => list of submodules that declare ‘name’.
|
||||
declsByName =
|
||||
zipAttrsWith
|
||||
(n: concatLists)
|
||||
(map
|
||||
(module: let subtree = module.options; in
|
||||
if !(builtins.isAttrs subtree) then
|
||||
throw (if attr == "config" then ''
|
||||
You're trying to define a value of type `${builtins.typeOf subtree}'
|
||||
rather than an attribute set for the option
|
||||
`${builtins.concatStringsSep "." prefix}'!
|
||||
|
||||
This usually happens if `${builtins.concatStringsSep "." prefix}' has option
|
||||
definitions inside that are not matched. Please check how to properly define
|
||||
this option by e.g. referring to `man 5 configuration.nix'!
|
||||
'' else ''
|
||||
throw ''
|
||||
An option declaration for `${builtins.concatStringsSep "." prefix}' has type
|
||||
`${builtins.typeOf subtree}' rather than an attribute set.
|
||||
Did you mean to define this outside of `options'?
|
||||
'')
|
||||
''
|
||||
else
|
||||
mapAttrs (n: f module) subtree
|
||||
) modules);
|
||||
# an attrset 'name' => list of submodules that declare ‘name’.
|
||||
declsByName = byName "options" (module: option:
|
||||
[{ inherit (module) _file; options = option; }]
|
||||
) options;
|
||||
mapAttrs
|
||||
(n: option:
|
||||
[{ inherit (module) _file; options = option; }]
|
||||
)
|
||||
subtree
|
||||
)
|
||||
options);
|
||||
|
||||
# The root of any module definition must be an attrset.
|
||||
checkedConfigs =
|
||||
assert
|
||||
lib.all
|
||||
(c:
|
||||
# TODO: I have my doubts that this error would occur when option definitions are not matched.
|
||||
# The implementation of this check used to be tied to a superficially similar check for
|
||||
# options, so maybe that's why this is here.
|
||||
isAttrs c.config || throw ''
|
||||
In module `${c.file}', you're trying to define a value of type `${builtins.typeOf c.config}'
|
||||
rather than an attribute set for the option
|
||||
`${builtins.concatStringsSep "." prefix}'!
|
||||
|
||||
This usually happens if `${builtins.concatStringsSep "." prefix}' has option
|
||||
definitions inside that are not matched. Please check how to properly define
|
||||
this option by e.g. referring to `man 5 configuration.nix'!
|
||||
''
|
||||
)
|
||||
configs;
|
||||
configs;
|
||||
|
||||
# an attrset 'name' => list of submodules that define ‘name’.
|
||||
defnsByName = byName "config" (module: value:
|
||||
map (config: { inherit (module) file; inherit config; }) (pushDownProperties value)
|
||||
) configs;
|
||||
pushedDownDefinitionsByName =
|
||||
zipAttrsWith
|
||||
(n: concatLists)
|
||||
(map
|
||||
(module:
|
||||
mapAttrs
|
||||
(n: value:
|
||||
map (config: { inherit (module) file; inherit config; }) (pushDownProperties value)
|
||||
)
|
||||
module.config
|
||||
)
|
||||
checkedConfigs);
|
||||
# extract the definitions for each loc
|
||||
defnsByName' = byName "config" (module: value:
|
||||
[{ inherit (module) file; inherit value; }]
|
||||
) configs;
|
||||
rawDefinitionsByName =
|
||||
zipAttrsWith
|
||||
(n: concatLists)
|
||||
(map
|
||||
(module:
|
||||
mapAttrs
|
||||
(n: value:
|
||||
[{ inherit (module) file; inherit value; }]
|
||||
)
|
||||
module.config
|
||||
)
|
||||
checkedConfigs);
|
||||
|
||||
# Convert an option tree decl to a submodule option decl
|
||||
optionTreeToOption = decl:
|
||||
@ -613,8 +628,8 @@ let
|
||||
# We're descending into attribute ‘name’.
|
||||
let
|
||||
loc = prefix ++ [name];
|
||||
defns = defnsByName.${name} or [];
|
||||
defns' = defnsByName'.${name} or [];
|
||||
defns = pushedDownDefinitionsByName.${name} or [];
|
||||
defns' = rawDefinitionsByName.${name} or [];
|
||||
optionDecls = filter (m: isOption m.options) decls;
|
||||
in
|
||||
if length optionDecls == length decls then
|
||||
@ -657,7 +672,7 @@ let
|
||||
# Propagate all unmatched definitions from nested option sets
|
||||
mapAttrs (n: v: v.unmatchedDefns) resultsByName
|
||||
# Plus the definitions for the current prefix that don't have a matching option
|
||||
// removeAttrs defnsByName' (attrNames matchedOptions);
|
||||
// removeAttrs rawDefinitionsByName (attrNames matchedOptions);
|
||||
in {
|
||||
inherit matchedOptions;
|
||||
|
||||
|
@ -207,7 +207,7 @@ checkConfigOutput '^"foo"$' config.submodule.foo ./declare-submoduleWith-special
|
||||
## shorthandOnlyDefines config behaves as expected
|
||||
checkConfigOutput '^true$' config.submodule.config ./declare-submoduleWith-shorthand.nix ./define-submoduleWith-shorthand.nix
|
||||
checkConfigError 'is not of type `boolean' config.submodule.config ./declare-submoduleWith-shorthand.nix ./define-submoduleWith-noshorthand.nix
|
||||
checkConfigError "You're trying to define a value of type \`bool'\n\s*rather than an attribute set for the option" config.submodule.config ./declare-submoduleWith-noshorthand.nix ./define-submoduleWith-shorthand.nix
|
||||
checkConfigError "In module ..*define-submoduleWith-shorthand.nix., you're trying to define a value of type \`bool'\n\s*rather than an attribute set for the option" config.submodule.config ./declare-submoduleWith-noshorthand.nix ./define-submoduleWith-shorthand.nix
|
||||
checkConfigOutput '^true$' config.submodule.config ./declare-submoduleWith-noshorthand.nix ./define-submoduleWith-noshorthand.nix
|
||||
|
||||
## submoduleWith should merge all modules in one swoop
|
||||
|
Loading…
Reference in New Issue
Block a user