diff options
author | Alyssa Ross <hi@alyssa.is> | 2021-08-04 10:43:07 +0000 |
---|---|---|
committer | Alyssa Ross <hi@alyssa.is> | 2021-08-04 10:43:07 +0000 |
commit | 62614cbef7da005c1eda8c9400160f6bcd6546b8 (patch) | |
tree | c2630f69080637987b68acb1ee8676d2681fe304 /lib/modules.nix | |
parent | d9c82ed3044c72cecf01c6ea042489d30914577c (diff) | |
parent | e24069138dfec3ef94f211f1da005bb5395adc11 (diff) | |
download | nixpkgs-62614cbef7da005c1eda8c9400160f6bcd6546b8.tar nixpkgs-62614cbef7da005c1eda8c9400160f6bcd6546b8.tar.gz nixpkgs-62614cbef7da005c1eda8c9400160f6bcd6546b8.tar.bz2 nixpkgs-62614cbef7da005c1eda8c9400160f6bcd6546b8.tar.lz nixpkgs-62614cbef7da005c1eda8c9400160f6bcd6546b8.tar.xz nixpkgs-62614cbef7da005c1eda8c9400160f6bcd6546b8.tar.zst nixpkgs-62614cbef7da005c1eda8c9400160f6bcd6546b8.zip |
Merge branch 'nixpkgs-update' into master
Diffstat (limited to 'lib/modules.nix')
-rw-r--r-- | lib/modules.nix | 134 |
1 files changed, 106 insertions, 28 deletions
diff --git a/lib/modules.nix b/lib/modules.nix index 2ec34699809..ab2bc4f7f8e 100644 --- a/lib/modules.nix +++ b/lib/modules.nix @@ -1,12 +1,54 @@ { lib }: -with lib.lists; -with lib.strings; -with lib.trivial; -with lib.attrsets; -with lib.options; -with lib.debug; -with lib.types; +let + inherit (lib) + all + any + attrByPath + attrNames + catAttrs + concatLists + concatMap + count + elem + filter + findFirst + flip + foldl + foldl' + getAttrFromPath + head + id + imap1 + isAttrs + isBool + isFunction + isList + isString + length + mapAttrs + mapAttrsToList + mapAttrsRecursiveCond + min + optional + optionalAttrs + optionalString + recursiveUpdate + reverseList sort + setAttrByPath + toList + types + warnIf + ; + inherit (lib.options) + isOption + mkOption + showDefs + showFiles + showOption + unknownModule + ; +in rec { @@ -86,7 +128,7 @@ rec { let collected = collectModules (specialArgs.modulesPath or "") (modules ++ [ internalModule ]) - ({ inherit lib options config; } // specialArgs); + ({ inherit lib options config specialArgs; } // specialArgs); in mergeModules prefix (reverseList collected); options = merged.matchedOptions; @@ -117,7 +159,7 @@ rec { if config._module.check && config._module.freeformType == null && merged.unmatchedDefns != [] then let firstDef = head merged.unmatchedDefns; - baseMsg = "The option `${showOption (prefix ++ firstDef.prefix)}' defined in `${firstDef.file}' does not exist."; + baseMsg = "The option `${showOption (prefix ++ firstDef.prefix)}' does not exist. Definition values:${showDefs [ firstDef ]}"; in if attrNames options == [ "_module" ] then throw '' @@ -147,6 +189,9 @@ rec { loadModule = args: fallbackFile: fallbackKey: m: if isFunction m || isAttrs m then unifyModuleSyntax fallbackFile fallbackKey (applyIfFunction fallbackKey m args) + else if isList m then + let defs = [{ file = fallbackFile; value = m; }]; in + throw "Module imports can't be nested lists. Perhaps you meant to remove one level of lists? Definitions: ${showDefs defs}" else unifyModuleSyntax (toString m) (toString m) (applyIfFunction (toString m) (import m) args); /* @@ -224,7 +269,7 @@ rec { if badAttrs != {} then throw "Module `${key}' has an unsupported attribute `${head (attrNames badAttrs)}'. This is caused by introducing a top-level `config' or `options' attribute. Add configuration attributes immediately on the top level instead, or move all of them (namely: ${toString (attrNames badAttrs)}) into the explicit `config' attribute." else - { _file = m._file or file; + { _file = toString m._file or file; key = toString m.key or key; disabledModules = m.disabledModules or []; imports = m.imports or []; @@ -232,7 +277,7 @@ rec { config = addFreeformType (addMeta (m.config or {})); } else - { _file = m._file or file; + { _file = toString m._file or file; key = toString m.key or key; disabledModules = m.disabledModules or []; imports = m.require or [] ++ m.imports or []; @@ -254,13 +299,11 @@ rec { # a module will resolve strictly the attributes used as argument but # not their values. The values are forwarding the result of the # evaluation of the option. - requiredArgs = builtins.attrNames (lib.functionArgs f); context = name: ''while evaluating the module argument `${name}' in "${key}":''; - extraArgs = builtins.listToAttrs (map (name: { - inherit name; - value = builtins.addErrorContext (context name) - (args.${name} or config._module.args.${name}); - }) requiredArgs); + extraArgs = builtins.mapAttrs (name: _: + builtins.addErrorContext (context name) + (args.${name} or config._module.args.${name}) + ) (lib.functionArgs f); # Note: we append in the opposite order such that we can add an error # context on the explicited arguments of "args" too. This update @@ -320,6 +363,17 @@ rec { */ byName = attr: f: modules: foldl' (acc: module: + if !(builtins.isAttrs module.${attr}) then + throw '' + You're trying to declare a value of type `${builtins.typeOf module.${attr}}' + 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 acc // (mapAttrs (n: v: (acc.${n} or []) ++ f module v ) module.${attr} @@ -449,7 +503,13 @@ rec { # Handle properties, check types, and merge everything together. res = if opt.readOnly or false && length defs' > 1 then - throw "The option `${showOption loc}' is read-only, but it's set multiple times." + let + # For a better error message, evaluate all readOnly definitions as + # if they were the only definition. + separateDefs = map (def: def // { + value = (mergeDefinitions loc opt.type [ def ]).mergedValue; + }) defs'; + in throw "The option `${showOption loc}' is read-only, but it's set multiple times. Definition values:${showDefs separateDefs}" else mergeDefinitions loc opt.type defs'; @@ -457,7 +517,11 @@ rec { # yield a value computed from the definitions value = if opt ? apply then opt.apply res.mergedValue else res.mergedValue; - in opt // + warnDeprecation = + warnIf (opt.type.deprecationMessage != null) + "The type `types.${opt.type.name}' of option `${showOption loc}' defined in ${showFiles opt.declarations} is deprecated. ${opt.type.deprecationMessage}"; + + in warnDeprecation opt // { value = builtins.addErrorContext "while evaluating the option `${showOption loc}':" value; inherit (res.defsFinal') highestPrio; definitions = map (def: def.value) res.defsFinal; @@ -493,8 +557,8 @@ rec { mergedValue = if isDefined then if all (def: type.check def.value) defsFinal then type.merge loc defsFinal - else let firstInvalid = findFirst (def: ! type.check def.value) null defsFinal; - in throw "The option value `${showOption loc}' in `${firstInvalid.file}' is not of type `${type.description}'." + else let allInvalid = filter (def: ! type.check def.value) defsFinal; + in throw "A definition for option `${showOption loc}' is not of type `${type.description}'. Definition values:${showDefs allInvalid}" else # (nixos-option detects this specific error message and gives it special # handling. If changed here, please change it there too.) @@ -606,14 +670,13 @@ rec { fixupOptionType = loc: opt: let options = opt.options or - (throw "Option `${showOption loc'}' has type optionSet but has no option attribute, in ${showFiles opt.declarations}."); + (throw "Option `${showOption loc}' has type optionSet but has no option attribute, in ${showFiles opt.declarations}."); f = tp: let optionSetIn = type: (tp.name == type) && (tp.functor.wrapped.name == "optionSet"); in if tp.name == "option set" || tp.name == "submodule" then throw "The option ${showOption loc} uses submodules without a wrapping type, in ${showFiles opt.declarations}." else if optionSetIn "attrsOf" then types.attrsOf (types.submodule options) - else if optionSetIn "loaOf" then types.loaOf (types.submodule options) else if optionSetIn "listOf" then types.listOf (types.submodule options) else if optionSetIn "nullOr" then types.nullOr (types.submodule options) else tp; @@ -650,9 +713,7 @@ rec { mkForce = mkOverride 50; mkVMOverride = mkOverride 10; # used by ‘nixos-rebuild build-vm’ - mkStrict = builtins.trace "`mkStrict' is obsolete; use `mkOverride 0' instead." (mkOverride 0); - - mkFixStrictness = id; # obsolete, no-op + mkFixStrictness = lib.warn "lib.mkFixStrictness has no effect and will be removed. It returns its argument unmodified, so you can just remove any calls." id; mkOrder = priority: content: { _type = "order"; @@ -710,7 +771,7 @@ rec { mkRemovedOptionModule [ "boot" "loader" "grub" "bootDevice" ] "<replacement instructions>" - causes a warning if the user defines boot.loader.grub.bootDevice. + causes a assertion if the user defines boot.loader.grub.bootDevice. replacementInstructions is a string that provides instructions on how to achieve the same functionality without the removed option, @@ -845,7 +906,7 @@ rec { fromOpt = getAttrFromPath from options; toOf = attrByPath to (abort "Renaming error: option `${showOption to}' does not exist."); - toType = let opt = attrByPath to {} options; in opt.type or null; + toType = let opt = attrByPath to {} options; in opt.type or (types.submodule {}); in { options = setAttrByPath from (mkOption { @@ -866,4 +927,21 @@ rec { ]; }; + /* Use this function to import a JSON file as NixOS configuration. + + importJSON -> path -> attrs + */ + importJSON = file: { + _file = file; + config = lib.importJSON file; + }; + + /* Use this function to import a TOML file as NixOS configuration. + + importTOML -> path -> attrs + */ + importTOML = file: { + _file = file; + config = lib.importTOML file; + }; } |