summary refs log tree commit diff
path: root/lib/modules.nix
diff options
context:
space:
mode:
authorEric Sagnes <eric.sagnes@gmail.com>2016-09-07 10:03:32 +0900
committerNicolas B. Pierron <nicolas.b.pierron@gmail.com>2016-11-06 00:05:58 +0100
commite14de56613fc8e42fb6249031efe9e7abbb65286 (patch)
tree4a0d884bf0b5698cf42705ff25c5806ace87951f /lib/modules.nix
parentd10356b82558fe50e1ad0fa1fb5e151c43ed3e0a (diff)
downloadnixpkgs-e14de56613fc8e42fb6249031efe9e7abbb65286.tar
nixpkgs-e14de56613fc8e42fb6249031efe9e7abbb65286.tar.gz
nixpkgs-e14de56613fc8e42fb6249031efe9e7abbb65286.tar.bz2
nixpkgs-e14de56613fc8e42fb6249031efe9e7abbb65286.tar.lz
nixpkgs-e14de56613fc8e42fb6249031efe9e7abbb65286.tar.xz
nixpkgs-e14de56613fc8e42fb6249031efe9e7abbb65286.tar.zst
nixpkgs-e14de56613fc8e42fb6249031efe9e7abbb65286.zip
module system: extensible option types
Diffstat (limited to 'lib/modules.nix')
-rw-r--r--lib/modules.nix32
1 files changed, 21 insertions, 11 deletions
diff --git a/lib/modules.nix b/lib/modules.nix
index 8db17c60579..e66d6a6926c 100644
--- a/lib/modules.nix
+++ b/lib/modules.nix
@@ -231,12 +231,20 @@ rec {
      correspond to the definition of 'loc' in 'opt.file'. */
   mergeOptionDecls = loc: opts:
     foldl' (res: opt:
-      if opt.options ? default && res ? default ||
-         opt.options ? example && res ? example ||
-         opt.options ? description && res ? description ||
-         opt.options ? apply && res ? apply ||
-         # Accept to merge options which have identical types.
-         opt.options ? type && res ? type && opt.options.type.name != res.type.name
+      let t  = res.type;
+          t' = opt.options.type;
+          mergedType = t.typeMerge t'.functor;
+          typesMergeable = mergedType != null;
+          typeSet = if (bothHave "type") && typesMergeable
+                       then { type = mergedType; }
+                       else {};
+          bothHave = k: opt.options ? ${k} && res ? ${k};
+      in
+      if bothHave "default" ||
+         bothHave "example" ||
+         bothHave "description" ||
+         bothHave "apply" ||
+         (bothHave "type" && (! typesMergeable))
       then
         throw "The option `${showOption loc}' in `${opt.file}' is already declared in ${showFiles res.declarations}."
       else
@@ -258,7 +266,7 @@ rec {
         in opt.options // res //
           { declarations = res.declarations ++ [opt.file];
             options = submodules;
-          }
+          } // typeSet
     ) { inherit loc; declarations = []; options = []; } opts;
 
   /* Merge all the definitions of an option to produce the final
@@ -422,12 +430,14 @@ rec {
       options = opt.options or
         (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 tp.name == "attribute set of option sets" then types.attrsOf (types.submodule options)
-        else if tp.name == "list or attribute set of option sets" then types.loaOf (types.submodule options)
-        else if tp.name == "list of option sets" then types.listOf (types.submodule options)
-        else if tp.name == "null or option set" then types.nullOr (types.submodule options)
+        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;
     in
       if opt.type.getSubModules or null == null