about summary refs log tree commit diff
path: root/lib/generators.nix
diff options
context:
space:
mode:
authorLinus Heckemann <git@sphalerite.org>2021-09-29 11:03:31 +0200
committerGitHub <noreply@github.com>2021-09-29 11:03:31 +0200
commita3df3d05e5db17b26ff886f53a58761a547561cc (patch)
tree3048af8fedf275f86fe60185936381823faffdd8 /lib/generators.nix
parent40f34902e623ad3c130bbdb2a65c53610e933307 (diff)
parent681758d41588c27aaa6f3c3a72184dcc4d0aeba8 (diff)
Merge pull request #131205 from Ma27/showdefs-overflow
lib/modules: improve errors for `options`/`config`-mixups
Diffstat (limited to 'lib/generators.nix')
-rw-r--r--lib/generators.nix27
1 files changed, 26 insertions, 1 deletions
diff --git a/lib/generators.nix b/lib/generators.nix
index 0cec4d2dd6206..79ae9055ce3d9 100644
--- a/lib/generators.nix
+++ b/lib/generators.nix
@@ -197,6 +197,30 @@ rec {
     */
   toYAML = {}@args: toJSON args;
 
+  withRecursion =
+    args@{
+      /* If this option is not null, the given value will stop evaluating at a certain depth */
+      depthLimit
+      /* If this option is true, an error will be thrown, if a certain given depth is exceeded */
+    , throwOnDepthLimit ? true
+    }:
+      assert builtins.isInt depthLimit;
+      let
+        transform = depth:
+          if depthLimit != null && depth > depthLimit then
+            if throwOnDepthLimit
+              then throw "Exceeded maximum eval-depth limit of ${toString depthLimit} while trying to evaluate with `generators.withRecursion'!"
+              else const "<unevaluated>"
+          else id;
+        mapAny = with builtins; depth: v:
+          let
+            evalNext = x: mapAny (depth + 1) (transform (depth + 1) x);
+          in
+            if isAttrs v then mapAttrs (const evalNext) v
+            else if isList v then map evalNext v
+            else transform (depth + 1) v;
+      in
+        mapAny 0;
 
   /* Pretty print a value, akin to `builtins.trace`.
     * Should probably be a builtin as well.
@@ -208,7 +232,8 @@ rec {
     allowPrettyValues ? false,
     /* If this option is true, the output is indented with newlines for attribute sets and lists */
     multiline ? true
-  }@args: let
+  }@args:
+    let
     go = indent: v: with builtins;
     let     isPath   = v: typeOf v == "path";
             introSpace = if multiline then "\n${indent}  " else " ";