nixpkgs/pkgs/pkgs-lib/formats.nix
lucasew 83514ae7a9 lib.formats.yaml: use well known YAML format
The way `(lib.formats.yaml {}).generate` generates YAML is compliant
because on YAML 1.2 spec JSON is a subset of YAML but it bugs people's
minds and can lead to problems with software that is not compatible with
YAML 1.2.

This commit also changes the test of the generation function. Data
validation/typing remains the same.

See #133802.

Signed-off-by: lucasew <lucas59356@gmail.com>
2021-08-25 14:02:59 +02:00

150 lines
3.5 KiB
Nix

{ 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
path
(attrsOf valueType)
(listOf valueType)
]) // {
description = "JSON value";
};
in valueType;
generate = name: value: pkgs.runCommand name {
nativeBuildInputs = [ pkgs.jq ];
value = builtins.toJSON value;
passAsFile = [ "value" ];
} ''
jq . "$valuePath"> $out
'';
};
yaml = {}: {
generate = name: value: pkgs.runCommand name {
nativeBuildInputs = [ pkgs.remarshal ];
value = builtins.toJSON value;
passAsFile = [ "value" ];
} ''
json2yaml "$valuePath" "$out"
'';
type = with lib.types; let
valueType = nullOr (oneOf [
bool
int
float
str
path
(attrsOf valueType)
(listOf valueType)
]) // {
description = "YAML value";
};
in valueType;
};
ini = {
# Represents lists as duplicate keys
listsAsDuplicateKeys ? false,
# Alternative to listsAsDuplicateKeys, converts list to non-list
# listToValue :: [IniAtom] -> IniAtom
listToValue ? null,
...
}@args:
assert !listsAsDuplicateKeys || listToValue == null;
{
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 if listToValue != null then
coercedTo singleIniAtom lib.singleton (nonEmptyListOf singleIniAtom) // {
description = singleIniAtom.description + " or a non-empty list of them";
}
else
singleIniAtom;
in attrsOf (attrsOf iniAtom);
generate = name: value:
let
transformedValue =
if listToValue != null
then
lib.mapAttrs (section: lib.mapAttrs (key: val:
if lib.isList val then listToValue val else val
)) value
else value;
in pkgs.writeText name (lib.generators.toINI (removeAttrs args ["listToValue"]) transformedValue);
};
toml = {}: json {} // {
type = with lib.types; let
valueType = oneOf [
bool
int
float
str
path
(attrsOf valueType)
(listOf valueType)
] // {
description = "TOML value";
};
in valueType;
generate = name: value: pkgs.runCommand name {
nativeBuildInputs = [ pkgs.remarshal ];
value = builtins.toJSON value;
passAsFile = [ "value" ];
} ''
json2toml "$valuePath" "$out"
'';
};
}