From f4a418761b481b15900c78b8086e7be58b0afe4e Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Mon, 28 Oct 2013 15:48:20 +0100 Subject: Check for undeclared options --- lib/modules.nix | 28 ++++++++++++++++------------ lib/types.nix | 10 +++++----- 2 files changed, 21 insertions(+), 17 deletions(-) (limited to 'lib') diff --git a/lib/modules.nix b/lib/modules.nix index 7ad722359945..076ffdde2463 100644 --- a/lib/modules.nix +++ b/lib/modules.nix @@ -6,16 +6,14 @@ rec { /* Evaluate a set of modules. The result is a set of two attributes: ‘options’: the nested set of all option declarations, and ‘config’: the nested set of all option values. */ - evalModules = evalModules' []; - - evalModules' = prefix: modules: args: + evalModules = { modules, prefix ? [], args ? {}, check ? true }: let args' = args // result; closed = closeModules modules args'; # Note: the list of modules is reversed to maintain backward # compatibility with the old module system. Not sure if this is # the most sensible policy. - options = mergeModules prefix (reverseList closed); + options = mergeModules check prefix (reverseList closed); config = yieldConfig options; yieldConfig = mapAttrs (n: v: if isOption v then v.value else yieldConfig v); result = { inherit options config; }; @@ -52,7 +50,7 @@ rec { { inherit file key; imports = m.require or []; options = {}; - config = m; + config = removeAttrs m ["require"]; }; applyIfFunction = f: arg: if builtins.isFunction f then f arg else f; @@ -62,13 +60,19 @@ rec { At the same time, for each option declaration, it will merge the corresponding option definitions in all machines, returning them in the ‘value’ attribute of each option. */ - mergeModules = prefix: modules: - mergeModules' prefix modules + mergeModules = check: prefix: modules: + mergeModules' check prefix modules (concatMap (m: map (config: { inherit (m) file; inherit config; }) (pushDownProperties m.config)) modules); - mergeModules' = prefix: options: configs: - let names = concatMap (m: attrNames m.options) options; - in listToAttrs (map (name: { + mergeModules' = check: prefix: options: configs: + let + 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’. inherit name; value = @@ -105,8 +109,8 @@ rec { in throw "The option `${showOption loc}' in `${firstOption.file}' is a prefix of options in `${firstNonOption.file}'." else - mergeModules' loc decls defns; - }) names); + mergeModules' check loc decls defns; + }) declaredNames)); /* Merge multiple option declarations into a single declaration. In general, there should be only one declaration of each option. diff --git a/lib/types.nix b/lib/types.nix index f459cda73cb5..07a6cc69fdca 100644 --- a/lib/types.nix +++ b/lib/types.nix @@ -182,11 +182,11 @@ rec { let coerce = def: if builtins.isFunction def then def else { config = def; }; modules = opts' ++ map coerce defs; - in (evalModules' args.prefix modules args).config; - getSubOptions = prefix: (evalModules' prefix opts' - # FIXME: hack to get shit to evaluate. - { name = ""; } - ).options; + in (evalModules { inherit modules args; prefix = args.prefix; }).config; + getSubOptions = prefix: (evalModules + { modules = opts'; inherit prefix; + # FIXME: hack to get shit to evaluate. + args = { name = ""; }; }).options; }; # Obsolete alternative to configOf. It takes its option -- cgit 1.4.1