about summary refs log tree commit diff
path: root/nixpkgs/pkgs/pkgs-lib
diff options
context:
space:
mode:
authorAlyssa Ross <hi@alyssa.is>2021-01-10 07:13:44 +0000
committerAlyssa Ross <hi@alyssa.is>2021-01-12 14:07:16 +0000
commite2698550456abba83c6dcd5d5e5a9990a0b96f8a (patch)
tree79a56f0df3fa55e470d84b4dff6059fbf487ec18 /nixpkgs/pkgs/pkgs-lib
parent1cdc42df888dc98c347e03bd942ed9825a55bcb3 (diff)
parent84d74ae9c9cbed73274b8e4e00be14688ffc93fe (diff)
downloadnixlib-e2698550456abba83c6dcd5d5e5a9990a0b96f8a.tar
nixlib-e2698550456abba83c6dcd5d5e5a9990a0b96f8a.tar.gz
nixlib-e2698550456abba83c6dcd5d5e5a9990a0b96f8a.tar.bz2
nixlib-e2698550456abba83c6dcd5d5e5a9990a0b96f8a.tar.lz
nixlib-e2698550456abba83c6dcd5d5e5a9990a0b96f8a.tar.xz
nixlib-e2698550456abba83c6dcd5d5e5a9990a0b96f8a.tar.zst
nixlib-e2698550456abba83c6dcd5d5e5a9990a0b96f8a.zip
Merge commit '84d74ae9c9cbed73274b8e4e00be14688ffc93fe'
Diffstat (limited to 'nixpkgs/pkgs/pkgs-lib')
-rw-r--r--nixpkgs/pkgs/pkgs-lib/default.nix11
-rw-r--r--nixpkgs/pkgs/pkgs-lib/formats.nix109
-rw-r--r--nixpkgs/pkgs/pkgs-lib/tests/default.nix7
-rw-r--r--nixpkgs/pkgs/pkgs-lib/tests/formats.nix157
4 files changed, 284 insertions, 0 deletions
diff --git a/nixpkgs/pkgs/pkgs-lib/default.nix b/nixpkgs/pkgs/pkgs-lib/default.nix
new file mode 100644
index 000000000000..113dcebf8c68
--- /dev/null
+++ b/nixpkgs/pkgs/pkgs-lib/default.nix
@@ -0,0 +1,11 @@
+# pkgs-lib is for functions and values that can't be in lib because
+# they depend on some packages. This notably is *not* for supporting package
+# building, instead pkgs/build-support is the place for that.
+{ lib, pkgs }: {
+  # setting format types and generators. These do not fit in lib/types.nix,
+  # because they depend on pkgs for rendering some formats
+  formats = import ./formats.nix {
+    inherit lib pkgs;
+  };
+}
+
diff --git a/nixpkgs/pkgs/pkgs-lib/formats.nix b/nixpkgs/pkgs/pkgs-lib/formats.nix
new file mode 100644
index 000000000000..14589f8ecdc3
--- /dev/null
+++ b/nixpkgs/pkgs/pkgs-lib/formats.nix
@@ -0,0 +1,109 @@
+{ lib, pkgs }:
+rec {
+
+  /*
+
+  Every following entry represents a format for program configuration files
+  used for `settings`-style options (see https://github.com/NixOS/rfcs/pull/42).
+  Each entry should look as follows:
+
+    <format> = <parameters>: {
+      #        ^^ Parameters for controlling the format
+
+      # The module system type most suitable for representing such a format
+      # The description needs to be overwritten for recursive types
+      type = ...;
+
+      # generate :: Name -> Value -> Path
+      # A function for generating a file with a value of such a type
+      generate = ...;
+
+    });
+  */
+
+
+  json = {}: {
+
+    type = with lib.types; let
+      valueType = nullOr (oneOf [
+        bool
+        int
+        float
+        str
+        (attrsOf valueType)
+        (listOf valueType)
+      ]) // {
+        description = "JSON value";
+      };
+    in valueType;
+
+    generate = name: value: pkgs.runCommandNoCC name {
+      nativeBuildInputs = [ pkgs.jq ];
+      value = builtins.toJSON value;
+      passAsFile = [ "value" ];
+    } ''
+      jq . "$valuePath"> $out
+    '';
+
+  };
+
+  # YAML has been a strict superset of JSON since 1.2
+  yaml = {}:
+    let jsonSet = json {};
+    in jsonSet // {
+      type = jsonSet.type // {
+        description = "YAML value";
+      };
+    };
+
+  ini = { listsAsDuplicateKeys ? false, ... }@args: {
+
+    type = with lib.types; let
+
+      singleIniAtom = nullOr (oneOf [
+        bool
+        int
+        float
+        str
+      ]) // {
+        description = "INI atom (null, bool, int, float or string)";
+      };
+
+      iniAtom =
+        if listsAsDuplicateKeys then
+          coercedTo singleIniAtom lib.singleton (listOf singleIniAtom) // {
+            description = singleIniAtom.description + " or a list of them for duplicate keys";
+          }
+        else
+          singleIniAtom;
+
+    in attrsOf (attrsOf iniAtom);
+
+    generate = name: value: pkgs.writeText name (lib.generators.toINI args value);
+
+  };
+
+  toml = {}: json {} // {
+    type = with lib.types; let
+      valueType = oneOf [
+        bool
+        int
+        float
+        str
+        (attrsOf valueType)
+        (listOf valueType)
+      ] // {
+        description = "TOML value";
+      };
+    in valueType;
+
+    generate = name: value: pkgs.runCommandNoCC name {
+      nativeBuildInputs = [ pkgs.remarshal ];
+      value = builtins.toJSON value;
+      passAsFile = [ "value" ];
+    } ''
+      json2toml "$valuePath" "$out"
+    '';
+
+  };
+}
diff --git a/nixpkgs/pkgs/pkgs-lib/tests/default.nix b/nixpkgs/pkgs/pkgs-lib/tests/default.nix
new file mode 100644
index 000000000000..f3549ea9b0f2
--- /dev/null
+++ b/nixpkgs/pkgs/pkgs-lib/tests/default.nix
@@ -0,0 +1,7 @@
+# Call nix-build on this file to run all tests in this directory
+{ pkgs ? import ../../.. {} }:
+let
+  formats = import ./formats.nix { inherit pkgs; };
+in pkgs.linkFarm "nixpkgs-pkgs-lib-tests" [
+  { name = "formats"; path = import ./formats.nix { inherit pkgs; }; }
+]
diff --git a/nixpkgs/pkgs/pkgs-lib/tests/formats.nix b/nixpkgs/pkgs/pkgs-lib/tests/formats.nix
new file mode 100644
index 000000000000..bf6be8595e1b
--- /dev/null
+++ b/nixpkgs/pkgs/pkgs-lib/tests/formats.nix
@@ -0,0 +1,157 @@
+{ pkgs }:
+let
+  inherit (pkgs) lib formats;
+in
+with lib;
+let
+
+  evalFormat = format: args: def:
+    let
+      formatSet = format args;
+      config = formatSet.type.merge [] (imap1 (n: def: {
+        value = def;
+        file = "def${toString n}";
+      }) [ def ]);
+    in formatSet.generate "test-format-file" config;
+
+  runBuildTest = name: { drv, expected }: pkgs.runCommandNoCC name {} ''
+    if diff ${drv} ${builtins.toFile "expected" expected}; then
+      touch $out
+    else
+      echo "Got: $(cat ${drv})"
+      echo "Should be: ${expected}"
+      exit 1
+    fi
+  '';
+
+  runBuildTests = tests: pkgs.linkFarm "nixpkgs-pkgs-lib-format-tests" (mapAttrsToList (name: value: { inherit name; path = runBuildTest name value; }) (filterAttrs (name: value: value != null) tests));
+
+in runBuildTests {
+
+  testJsonAtoms = {
+    drv = evalFormat formats.json {} {
+      null = null;
+      false = false;
+      true = true;
+      int = 10;
+      float = 3.141;
+      str = "foo";
+      attrs.foo = null;
+      list = [ null null ];
+    };
+    expected = ''
+      {
+        "attrs": {
+          "foo": null
+        },
+        "false": false,
+        "float": 3.141,
+        "int": 10,
+        "list": [
+          null,
+          null
+        ],
+        "null": null,
+        "str": "foo",
+        "true": true
+      }
+    '';
+  };
+
+  testYamlAtoms = {
+    drv = evalFormat formats.yaml {} {
+      null = null;
+      false = false;
+      true = true;
+      float = 3.141;
+      str = "foo";
+      attrs.foo = null;
+      list = [ null null ];
+    };
+    expected = ''
+      {
+        "attrs": {
+          "foo": null
+        },
+        "false": false,
+        "float": 3.141,
+        "list": [
+          null,
+          null
+        ],
+        "null": null,
+        "str": "foo",
+        "true": true
+      }
+    '';
+  };
+
+  testIniAtoms = {
+    drv = evalFormat formats.ini {} {
+      foo = {
+        bool = true;
+        int = 10;
+        float = 3.141;
+        str = "string";
+      };
+    };
+    expected = ''
+      [foo]
+      bool=true
+      float=3.141000
+      int=10
+      str=string
+    '';
+  };
+
+  testIniDuplicateKeys = {
+    drv = evalFormat formats.ini { listsAsDuplicateKeys = true; } {
+      foo = {
+        bar = [ null true "test" 1.2 10 ];
+        baz = false;
+        qux = "qux";
+      };
+    };
+    expected = ''
+      [foo]
+      bar=null
+      bar=true
+      bar=test
+      bar=1.200000
+      bar=10
+      baz=false
+      qux=qux
+    '';
+  };
+
+  testTomlAtoms = {
+    drv = evalFormat formats.toml {} {
+      false = false;
+      true = true;
+      int = 10;
+      float = 3.141;
+      str = "foo";
+      attrs.foo = "foo";
+      list = [ 1 2 ];
+      level1.level2.level3.level4 = "deep";
+    };
+    expected = ''
+      false = false
+      float = 3.141
+      int = 10
+      list = [1, 2]
+      str = "foo"
+      true = true
+
+      [attrs]
+      foo = "foo"
+
+      [level1]
+
+      [level1.level2]
+
+      [level1.level2.level3]
+      level4 = "deep"
+    '';
+  };
+}