about summary refs log tree commit diff
path: root/pkgs/pkgs-lib
diff options
context:
space:
mode:
authorAaron Andersen <aaron@fosslib.net>2022-07-01 00:11:34 +0200
committerGitHub <noreply@github.com>2022-07-01 00:11:34 +0200
commit1cab3622065a8c0a05707e66949ace02c1aee41a (patch)
treef963b1730fc255911be4abacce2d769235004e2a /pkgs/pkgs-lib
parent6d91af447511045056eb2936f66c943b34774e0f (diff)
parent0d2842a4353f55eb2fc79ec7ad6490c1f5a2b88e (diff)
Merge pull request #178365 from fgaz/lib.formats.keyValue
lib.formats.keyValue: init
Diffstat (limited to 'pkgs/pkgs-lib')
-rw-r--r--pkgs/pkgs-lib/formats.nix49
-rw-r--r--pkgs/pkgs-lib/tests/formats.nix45
2 files changed, 94 insertions, 0 deletions
diff --git a/pkgs/pkgs-lib/formats.nix b/pkgs/pkgs-lib/formats.nix
index cdcbd3663422a..13aada3681f7c 100644
--- a/pkgs/pkgs-lib/formats.nix
+++ b/pkgs/pkgs-lib/formats.nix
@@ -135,6 +135,55 @@ rec {
 
   };
 
+  keyValue = {
+    # Represents lists as duplicate keys
+    listsAsDuplicateKeys ? false,
+    # Alternative to listsAsDuplicateKeys, converts list to non-list
+    # listToValue :: [Atom] -> Atom
+    listToValue ? null,
+    ...
+    }@args:
+    assert !listsAsDuplicateKeys || listToValue == null;
+    {
+
+    type = with lib.types; let
+
+      singleAtom = nullOr (oneOf [
+        bool
+        int
+        float
+        str
+      ]) // {
+        description = "atom (null, bool, int, float or string)";
+      };
+
+      atom =
+        if listsAsDuplicateKeys then
+          coercedTo singleAtom lib.singleton (listOf singleAtom) // {
+            description = singleAtom.description + " or a list of them for duplicate keys";
+          }
+        else if listToValue != null then
+          coercedTo singleAtom lib.singleton (nonEmptyListOf singleAtom) // {
+            description = singleAtom.description + " or a non-empty list of them";
+          }
+        else
+          singleAtom;
+
+    in attrsOf atom;
+
+    generate = name: value:
+      let
+        transformedValue =
+          if listToValue != null
+          then
+            lib.mapAttrs (key: val:
+              if lib.isList val then listToValue val else val
+            ) value
+          else value;
+      in pkgs.writeText name (lib.generators.toKeyValue (removeAttrs args ["listToValue"]) transformedValue);
+
+  };
+
   gitIni = { listsAsDuplicateKeys ? false, ... }@args: {
 
     type = with lib.types; let
diff --git a/pkgs/pkgs-lib/tests/formats.nix b/pkgs/pkgs-lib/tests/formats.nix
index dba7f981cbd9a..80df247f7b6af 100644
--- a/pkgs/pkgs-lib/tests/formats.nix
+++ b/pkgs/pkgs-lib/tests/formats.nix
@@ -147,6 +147,51 @@ in runBuildTests {
     '';
   };
 
+  testKeyValueAtoms = {
+    drv = evalFormat formats.keyValue {} {
+      bool = true;
+      int = 10;
+      float = 3.141;
+      str = "string";
+    };
+    expected = ''
+      bool=true
+      float=3.141000
+      int=10
+      str=string
+    '';
+  };
+
+  testKeyValueDuplicateKeys = {
+    drv = evalFormat formats.keyValue { listsAsDuplicateKeys = true; } {
+      bar = [ null true "test" 1.2 10 ];
+      baz = false;
+      qux = "qux";
+    };
+    expected = ''
+      bar=null
+      bar=true
+      bar=test
+      bar=1.200000
+      bar=10
+      baz=false
+      qux=qux
+    '';
+  };
+
+  testKeyValueListToValue = {
+    drv = evalFormat formats.keyValue { listToValue = concatMapStringsSep ", " (generators.mkValueStringDefault {}); } {
+      bar = [ null true "test" 1.2 10 ];
+      baz = false;
+      qux = "qux";
+    };
+    expected = ''
+      bar=null, true, test, 1.200000, 10
+      baz=false
+      qux=qux
+    '';
+  };
+
   testTomlAtoms = {
     drv = evalFormat formats.toml {} {
       false = false;