summary refs log tree commit diff
path: root/pkgs
diff options
context:
space:
mode:
authorNicolas Pierron <nicolas.b.pierron@gmail.com>2012-04-15 23:31:48 +0000
committerNicolas Pierron <nicolas.b.pierron@gmail.com>2012-04-15 23:31:48 +0000
commit8a677091830176ba5e820f5421e7d6f7eb938f8c (patch)
tree9ac4d09cf8b5efbabfe8dce5b06fd7c359686cc0 /pkgs
parenta9c51d7af3bd5c6b633d56afe1cb854b967e5c57 (diff)
downloadnixlib-8a677091830176ba5e820f5421e7d6f7eb938f8c.tar
nixlib-8a677091830176ba5e820f5421e7d6f7eb938f8c.tar.gz
nixlib-8a677091830176ba5e820f5421e7d6f7eb938f8c.tar.bz2
nixlib-8a677091830176ba5e820f5421e7d6f7eb938f8c.tar.lz
nixlib-8a677091830176ba5e820f5421e7d6f7eb938f8c.tar.xz
nixlib-8a677091830176ba5e820f5421e7d6f7eb938f8c.tar.zst
nixlib-8a677091830176ba5e820f5421e7d6f7eb938f8c.zip
Add mkMerge and obsolete mkThenElse.
svn path=/nixpkgs/trunk/; revision=33796
Diffstat (limited to 'pkgs')
-rw-r--r--pkgs/lib/modules.nix46
-rw-r--r--pkgs/lib/properties.nix31
2 files changed, 62 insertions, 15 deletions
diff --git a/pkgs/lib/modules.nix b/pkgs/lib/modules.nix
index 8ecb04156e78..eb528f141fe2 100644
--- a/pkgs/lib/modules.nix
+++ b/pkgs/lib/modules.nix
@@ -41,29 +41,31 @@ rec {
   # attributes.
   unifyModuleSyntax = m:
     let
-      getImports = m:
+      delayedModule = delayProperties m;
+      getImports =
         if m ? config || m ? options then
           attrByPath ["imports"] [] m
         else
-          toList (rmProperties (attrByPath ["require"] [] (delayProperties m)));
+          toList (rmProperties (attrByPath ["require"] [] delayedModule));
 
-      getImportedPaths = m: filter isPath (getImports m);
-      getImportedSets = m: filter (x: !isPath x) (getImports m);
+      getImportedPaths = filter isPath getImports;
+      getImportedSets = filter (x: !isPath x) getImports;
+
+      getConfig =
+        removeAttrs delayedModule ["require" "key"];
 
-      getConfig = m:
-        removeAttrs (delayProperties m) ["require" "key"];
     in
       if isModule m then
         { key = "<unknown location>"; } // m
       else
         {
           key = "<unknown location>";
-          imports = getImportedPaths m;
-          config = getConfig m;
+          imports = getImportedPaths;
+          config = getConfig;
         } // (
-          if getImportedSets m != [] then
-            assert tail (getImportedSets m) == [];
-            { options = head (getImportedSets m); }
+          if getImportedSets != [] then
+            assert tail getImportedSets == [];
+            { options = head getImportedSets; }
           else
             {}
         );
@@ -124,9 +126,25 @@ rec {
         value
     ) module;
 
-
+  # Handle mkMerge function left behind after a delay property.
+  moduleFlattenMerge = module:
+    if module ? config &&
+       isProperty module.config &&
+       isMerge module.config.property
+    then
+      (map (cfg: { key = module.key; config = cfg; }) module.config.content)
+      ++ [ (module // { config = {}; }) ]
+    else
+      [ module ];
+
+  # Handle mkMerge attributes which are left behind by previous delay
+  # properties and convert them into a list of modules. Delay properties
+  # inside the config attribute of a module and create a second module if a
+  # mkMerge attribute was left behind.
+  #
+  # Module -> [ Module ]
   delayModule = module:
-    moduleApply { config = delayProperties; } module;
+    map (moduleApply { config = delayProperties; }) (moduleFlattenMerge module);
 
   evalDefinitions = opt: values:
     if opt ? type && opt.type.delayOnGlobalEval then
@@ -170,7 +188,7 @@ rec {
       addName = name:
         if path == "" then name else path + "." + name;
 
-      modules = map delayModule modules_;
+      modules = concatLists (map delayModule modules_);
 
       modulesOf = name: filterModules name modules;
       declarationsOf = name: filter (m: m ? options) (modulesOf name);
diff --git a/pkgs/lib/properties.nix b/pkgs/lib/properties.nix
index d7df14f716f5..0d864b0c553c 100644
--- a/pkgs/lib/properties.nix
+++ b/pkgs/lib/properties.nix
@@ -82,7 +82,19 @@ rec {
       attrs;
 
   delayProperties = # implicit attrs argument.
-    delayPropertiesWithIter (f: p: v: lib.mapAttrs f v) "";
+    let
+      # mapAttrs except that it also recurse into potential mkMerge
+      # functions.  This may cause a strictness issue because looking the
+      # type of a string implies evaluating it.
+      iter = fun: path: value:
+        lib.mapAttrs (attr: val:
+          if isProperty val && isMerge val.property then
+            val // { content = map (fun attr) val.content; }
+          else
+            fun attr val
+        ) value;
+    in
+      delayPropertiesWithIter iter "";
 
   # Call onDelay functions.
   triggerPropertiesDelay = name: attrs:
@@ -179,6 +191,22 @@ rec {
   copyProperties = attrs: newAttrs:
     foldProperty id (x: newAttrs) attrs;
 
+  /* Merge. */
+
+  # Create "merge" statement which is skipped by the delayProperty function
+  # and interpreted by the underlying system using properties (modules).
+
+  # Create a "Merge" property which only contains a condition.
+  isMerge = attrs: (typeOf attrs) == "merge";
+  mkMerge = content: mkProperty {
+    property = {
+      _type = "merge";
+      onDelay = name: val: throw "mkMerge is not the first of the list of properties.";
+      onEval = val: throw "mkMerge is not allowed on option definitions.";
+    };
+    inherit content;
+  };
+
   /* If. ThenElse. Always. */
 
   # create "if" statement that can be delayed on sets until a "then-else" or
@@ -202,6 +230,7 @@ rec {
   isThenElse = attrs: (typeOf attrs) == "then-else";
   mkThenElse = attrs:
     assert attrs ? thenPart && attrs ? elsePart;
+    __trace "Obsolete usage of mkThenElse, replace it by mkMerge."
     mkProperty {
       property = {
         _type = "then-else";