summary refs log tree commit diff
path: root/lib/modules.nix
diff options
context:
space:
mode:
authorNicolas B. Pierron <nicolas.b.pierron@gmail.com>2015-03-11 23:30:30 +0100
committerNicolas B. Pierron <nicolas.b.pierron@gmail.com>2015-03-12 23:42:58 +0100
commit83dc60456e44082b4f13c2be19c5e9fbcfd57f74 (patch)
tree373f4dda866fc61d58cef584119d96ff5cae1173 /lib/modules.nix
parent9f2865515de2148dd35b720d4592783617e4e177 (diff)
downloadnixpkgs-83dc60456e44082b4f13c2be19c5e9fbcfd57f74.tar
nixpkgs-83dc60456e44082b4f13c2be19c5e9fbcfd57f74.tar.gz
nixpkgs-83dc60456e44082b4f13c2be19c5e9fbcfd57f74.tar.bz2
nixpkgs-83dc60456e44082b4f13c2be19c5e9fbcfd57f74.tar.lz
nixpkgs-83dc60456e44082b4f13c2be19c5e9fbcfd57f74.tar.xz
nixpkgs-83dc60456e44082b4f13c2be19c5e9fbcfd57f74.tar.zst
nixpkgs-83dc60456e44082b4f13c2be19c5e9fbcfd57f74.zip
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.nix34
1 files changed, 27 insertions, 7 deletions
diff --git a/lib/modules.nix b/lib/modules.nix
index 9ed2917df50..ca88b28a779 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 //