diff options
author | Nicolas B. Pierron <nicolas.b.pierron@gmail.com> | 2015-03-11 23:30:30 +0100 |
---|---|---|
committer | Nicolas B. Pierron <nicolas.b.pierron@gmail.com> | 2015-03-12 23:42:58 +0100 |
commit | 83dc60456e44082b4f13c2be19c5e9fbcfd57f74 (patch) | |
tree | 373f4dda866fc61d58cef584119d96ff5cae1173 /lib/modules.nix | |
parent | 9f2865515de2148dd35b720d4592783617e4e177 (diff) |
Expose submodule arguments to builtins.functionArgs before applying the arguments.
The current implementation of the ApplyIfFunction is looking at the
arguments of a module to decide which arguments should be given to each
module. This patch make sure that we do not wrap a submodule function in
order to keep functionArgs working as expected.
Diffstat (limited to 'lib/modules.nix')
-rw-r--r-- | lib/modules.nix | 34 |
1 files changed, 27 insertions, 7 deletions
diff --git a/lib/modules.nix b/lib/modules.nix index 9ed2917df50a..ca88b28a7791 100644 --- a/lib/modules.nix +++ b/lib/modules.nix @@ -87,7 +87,7 @@ rec { let toClosureList = file: parentKey: imap (n: x: if isAttrs x || isFunction x then - unifyModuleSyntax file "${parentKey}:anon-${toString n}" (applyIfFunction x args) + unifyModuleSyntax file "${parentKey}:anon-${toString n}" (unpackSubmodule applyIfFunction x args) else unifyModuleSyntax (toString x) (toString x) (applyIfFunction (import x) args)); in @@ -120,6 +120,18 @@ rec { applyIfFunction = f: arg@{ config, options, lib }: if isFunction f then let + # Module arguments are resolved in a strict manner when attribute set + # deconstruction is used. As the arguments are now defined with the + # config.__interanl.args option, the strictness used on the attribute + # set argument would cause an infinite loop, if the result of the + # option is given as argument. + # + # To work-around the strictness issue on the deconstruction of the + # attributes set argument, we create a new attribute set which is + # constructed to satisfy the expected set of attributes. Thus calling + # 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 (builtins.functionArgs f); extraArgs = builtins.listToAttrs (map (name: { inherit name; @@ -129,6 +141,17 @@ rec { else f; + /* We have to pack and unpack submodules. We cannot wrap the expected + result of the function as we would no longer be able to list the arguments + of the submodule. (see applyIfFunction) */ + unpackSubmodule = unpack: m: args: + if isType "submodule" m then + { _file = m.file; } // (unpack m.submodule args) + else unpack m args; + + packSubmodule = file: m: + { _type = "submodule"; file = file; submodule = m; }; + /* Merge a list of modules. This will recurse over the option declarations in all modules, combining them into a single set. At the same time, for each option declaration, it will merge the @@ -206,15 +229,12 @@ rec { current option declaration as the file use for the submodule. If the submodule defines any filename, then we ignore the enclosing option file. */ options' = toList opt.options.options; - addModuleFile = m: - if isFunction m then args: { _file = opt.file; } // (m args) - else { _file = opt.file; } // m; coerceOption = file: opt: - if isFunction opt then args: { _file = file; } // (opt args) - else { _file = file; options = opt; }; + if isFunction opt then packSubmodule file opt + else packSubmodule file { options = opt; }; getSubModules = opt.options.type.getSubModules or null; submodules = - if getSubModules != null then map addModuleFile getSubModules ++ res.options + if getSubModules != null then map (packSubmodule opt.file) getSubModules ++ res.options else if opt.options ? options then map (coerceOption opt.file) options' ++ res.options else res.options; in opt.options // res // |