about summary refs log tree commit diff
path: root/lib
diff options
context:
space:
mode:
authorProfpatsch <mail@profpatsch.de>2022-03-14 10:14:18 +0100
committerProfpatsch <mail@profpatsch.de>2022-03-14 10:21:15 +0100
commitab03ddc8f441a11644a4ce3d29eb290fa02b11e3 (patch)
tree70b3a3752412e3caf6ca215f199e384f21b0d477 /lib
parent31961f641557fb4b9c96250e68f520a768d5e303 (diff)
downloadnixlib-ab03ddc8f441a11644a4ce3d29eb290fa02b11e3.tar
nixlib-ab03ddc8f441a11644a4ce3d29eb290fa02b11e3.tar.gz
nixlib-ab03ddc8f441a11644a4ce3d29eb290fa02b11e3.tar.bz2
nixlib-ab03ddc8f441a11644a4ce3d29eb290fa02b11e3.tar.lz
nixlib-ab03ddc8f441a11644a4ce3d29eb290fa02b11e3.tar.xz
nixlib-ab03ddc8f441a11644a4ce3d29eb290fa02b11e3.tar.zst
nixlib-ab03ddc8f441a11644a4ce3d29eb290fa02b11e3.zip
lib.generators: add toINIWithGlobalSection
As discussed in
https://github.com/NixOS/nixpkgs/pull/118925#issuecomment-821112723,
this is the best way of adding global sections to `toINI` without
employing heuristics (i.e. checking whether something is an attrset).
Diffstat (limited to 'lib')
-rw-r--r--lib/generators.nix45
-rw-r--r--lib/tests/misc.nix60
2 files changed, 105 insertions, 0 deletions
diff --git a/lib/generators.nix b/lib/generators.nix
index 79ae9055ce3d..c421573a727b 100644
--- a/lib/generators.nix
+++ b/lib/generators.nix
@@ -130,6 +130,51 @@ rec {
       # map input to ini sections
       mapAttrsToStringsSep "\n" mkSection attrsOfAttrs;
 
+  /* Generate an INI-style config file from an attrset
+   * specifying the global section (no header), and an
+   * attrset of sections to an attrset of key-value pairs.
+   *
+   * generators.toINIWithGlobalSection {} {
+   *   globalSection = {
+   *     someGlobalKey = "hi";
+   *   };
+   *   sections = {
+   *     foo = { hi = "${pkgs.hello}"; ciao = "bar"; };
+   *     baz = { "also, integers" = 42; };
+   * }
+   *
+   *> someGlobalKey=hi
+   *>
+   *> [baz]
+   *> also, integers=42
+   *>
+   *> [foo]
+   *> ciao=bar
+   *> hi=/nix/store/y93qql1p5ggfnaqjjqhxcw0vqw95rlz0-hello-2.10
+   *
+   * The mk* configuration attributes can generically change
+   * the way sections and key-value strings are generated.
+   *
+   * For more examples see the test cases in ./tests.nix.
+   *
+   * If you don’t need a global section, you can also use
+   * `generators.toINI` directly, which only takes
+   * the part in `sections`.
+   */
+  toINIWithGlobalSection = {
+    # apply transformations (e.g. escapes) to section names
+    mkSectionName ? (name: libStr.escape [ "[" "]" ] name),
+    # format a setting line from key and value
+    mkKeyValue    ? mkKeyValueDefault {} "=",
+    # allow lists as values for duplicate keys
+    listsAsDuplicateKeys ? false
+  }: { globalSection, sections }:
+    ( if globalSection == {}
+      then ""
+      else (toKeyValue { inherit mkKeyValue listsAsDuplicateKeys; } globalSection)
+           + "\n")
+    + (toINI { inherit mkSectionName mkKeyValue listsAsDuplicateKeys; } sections);
+
   /* Generate a git-config file from an attrset.
    *
    * It has two major differences from the regular INI format:
diff --git a/lib/tests/misc.nix b/lib/tests/misc.nix
index 5fa95828df69..6687b9bebaee 100644
--- a/lib/tests/misc.nix
+++ b/lib/tests/misc.nix
@@ -471,6 +471,66 @@ runTests {
     '';
   };
 
+  testToINIWithGlobalSectionEmpty = {
+    expr = generators.toINIWithGlobalSection {} {
+      globalSection = {
+      };
+      sections = {
+      };
+    };
+    expected = ''
+    '';
+  };
+
+  testToINIWithGlobalSectionGlobalEmptyIsTheSameAsToINI =
+    let
+      sections = {
+        "section 1" = {
+          attribute1 = 5;
+          x = "Me-se JarJar Binx";
+        };
+        "foo" = {
+          "he\\h=he" = "this is okay";
+        };
+      };
+    in {
+      expr =
+        generators.toINIWithGlobalSection {} {
+            globalSection = {};
+            sections = sections;
+        };
+      expected = generators.toINI {} sections;
+  };
+
+  testToINIWithGlobalSectionFull = {
+    expr = generators.toINIWithGlobalSection {} {
+      globalSection = {
+        foo = "bar";
+        test = false;
+      };
+      sections = {
+        "section 1" = {
+          attribute1 = 5;
+          x = "Me-se JarJar Binx";
+        };
+        "foo" = {
+          "he\\h=he" = "this is okay";
+        };
+      };
+    };
+    expected = ''
+      foo=bar
+      test=false
+
+      [foo]
+      he\h\=he=this is okay
+
+      [section 1]
+      attribute1=5
+      x=Me-se JarJar Binx
+    '';
+  };
+
   /* right now only invocation check */
   testToJSONSimple =
     let val = {