Fix environment.checkConfigurationOptions

This requires delaying the declaredness check until later, otherwise
we get an infinite recursion querying
environment.checkConfigurationOptions.
This commit is contained in:
Eelco Dolstra 2013-10-29 16:14:58 +01:00
parent c407db6316
commit 89b1dd8dde
2 changed files with 26 additions and 17 deletions

View File

@ -13,9 +13,24 @@ rec {
# Note: the list of modules is reversed to maintain backward # Note: the list of modules is reversed to maintain backward
# compatibility with the old module system. Not sure if this is # compatibility with the old module system. Not sure if this is
# the most sensible policy. # the most sensible policy.
options = mergeModules check prefix (reverseList closed); options = mergeModules prefix (reverseList closed);
config = yieldConfig options; # Traverse options and extract the option values into the final
yieldConfig = mapAttrs (n: v: if isOption v then v.value else yieldConfig v); # config set. At the same time, check whether all option
# definitions have matching declarations.
config = yieldConfig [] options;
yieldConfig = prefix: set:
let res = removeAttrs (mapAttrs (n: v:
if isOption v then v.value
else yieldConfig (prefix ++ [n]) v) set) ["_definedNames"];
in
if check && set ? _definedNames then
fold (m: res:
fold (name: res:
if hasAttr name set then res else throw "The option `${showOption (prefix ++ [name])}' defined in `${m.file}' does not exist.")
res m.names)
res set._definedNames
else
res;
result = { inherit options config; }; result = { inherit options config; };
in result; in result;
@ -62,19 +77,12 @@ rec {
At the same time, for each option declaration, it will merge the At the same time, for each option declaration, it will merge the
corresponding option definitions in all machines, returning them corresponding option definitions in all machines, returning them
in the value attribute of each option. */ in the value attribute of each option. */
mergeModules = check: prefix: modules: mergeModules = prefix: modules:
mergeModules' check prefix modules mergeModules' prefix modules
(concatMap (m: map (config: { inherit (m) file; inherit config; }) (pushDownProperties m.config)) modules); (concatMap (m: map (config: { inherit (m) file; inherit config; }) (pushDownProperties m.config)) modules);
mergeModules' = check: prefix: options: configs: mergeModules' = prefix: options: configs:
let listToAttrs (map (name: {
declaredNames = concatMap (m: attrNames m.options) options;
declaredNames' = listToAttrs (map (n: { name = n; value = 1; }) declaredNames);
checkDefinedNames = res: fold (m: res: fold (n: res:
if hasAttr n declaredNames' then res else
throw "The option `${showOption (prefix ++ [n])}' defined in `${m.file}' does not exist."
) res (attrNames m.config)) res configs;
in (if check then checkDefinedNames else id) (listToAttrs (map (name: {
# We're descending into attribute name. # We're descending into attribute name.
inherit name; inherit name;
value = value =
@ -111,8 +119,9 @@ rec {
in in
throw "The option `${showOption loc}' in `${firstOption.file}' is a prefix of options in `${firstNonOption.file}'." throw "The option `${showOption loc}' in `${firstOption.file}' is a prefix of options in `${firstNonOption.file}'."
else else
mergeModules' check loc decls defns; mergeModules' loc decls defns;
}) declaredNames)); }) (concatMap (m: attrNames m.options) options))
// { _definedNames = map (m: { inherit (m) file; names = attrNames m.config; }) configs; };
/* Merge multiple option declarations into a single declaration. In /* Merge multiple option declarations into a single declaration. In
general, there should be only one declaration of each option. general, there should be only one declaration of each option.

View File

@ -19,7 +19,7 @@ rec {
inherit (pkgs.lib.evalModules { inherit (pkgs.lib.evalModules {
modules = modules ++ baseModules; modules = modules ++ baseModules;
args = extraArgs; args = extraArgs;
inherit check; check = check && options.environment.checkConfigurationOptions.value;
}) config options; }) config options;
# These are the extra arguments passed to every module. In # These are the extra arguments passed to every module. In