uboot: (firmwareOdroidC2/C4) don't invoke patch tool, use patches = [] instead
https://github.com/NixOS/nixpkgs/blob/master/pkgs/stdenv/generic/setup.sh#L948 this can do it nicely. Signed-off-by: Anton Arapov <anton@deadbeef.mx>
This commit is contained in:
commit
56de2bcd43
30691 changed files with 3076956 additions and 0 deletions
11
pkgs/pkgs-lib/default.nix
Normal file
11
pkgs/pkgs-lib/default.nix
Normal file
|
|
@ -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;
|
||||
};
|
||||
}
|
||||
|
||||
371
pkgs/pkgs-lib/formats.nix
Normal file
371
pkgs/pkgs-lib/formats.nix
Normal file
|
|
@ -0,0 +1,371 @@
|
|||
{ 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 = ...;
|
||||
|
||||
# Utility functions for convenience, or special interactions with the
|
||||
# format (optional)
|
||||
lib = {
|
||||
exampleFunction = ...
|
||||
# Types specific to the format (optional)
|
||||
types = { ... };
|
||||
...
|
||||
};
|
||||
|
||||
# generate :: Name -> Value -> Path
|
||||
# A function for generating a file with a value of such a type
|
||||
generate = ...;
|
||||
|
||||
});
|
||||
*/
|
||||
|
||||
|
||||
inherit (import ./formats/java-properties/default.nix { inherit lib pkgs; })
|
||||
javaProperties;
|
||||
|
||||
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);
|
||||
|
||||
};
|
||||
|
||||
gitIni = { listsAsDuplicateKeys ? false, ... }@args: {
|
||||
|
||||
type = with lib.types; let
|
||||
|
||||
iniAtom = (ini args).type/*attrsOf*/.functor.wrapped/*attrsOf*/.functor.wrapped;
|
||||
|
||||
in attrsOf (attrsOf (either iniAtom (attrsOf iniAtom)));
|
||||
|
||||
generate = name: value: pkgs.writeText name (lib.generators.toGitINI value);
|
||||
};
|
||||
|
||||
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"
|
||||
'';
|
||||
|
||||
};
|
||||
|
||||
/* For configurations of Elixir project, like config.exs or runtime.exs
|
||||
|
||||
Most Elixir project are configured using the [Config] Elixir DSL
|
||||
|
||||
Since Elixir has more types than Nix, we need a way to map Nix types to
|
||||
more than 1 Elixir type. To that end, this format provides its own library,
|
||||
and its own set of types.
|
||||
|
||||
To be more detailed, a Nix attribute set could correspond in Elixir to a
|
||||
[Keyword list] (the more common type), or it could correspond to a [Map].
|
||||
|
||||
A Nix string could correspond in Elixir to a [String] (also called
|
||||
"binary"), an [Atom], or a list of chars (usually discouraged).
|
||||
|
||||
A Nix array could correspond in Elixir to a [List] or a [Tuple].
|
||||
|
||||
Some more types exists, like records, regexes, but since they are less used,
|
||||
we can leave the `mkRaw` function as an escape hatch.
|
||||
|
||||
For more information on how to use this format in modules, please refer to
|
||||
the Elixir section of the Nixos documentation.
|
||||
|
||||
TODO: special Elixir values doesn't show up nicely in the documentation
|
||||
|
||||
[Config]: <https://hexdocs.pm/elixir/Config.html>
|
||||
[Keyword list]: <https://hexdocs.pm/elixir/Keyword.html>
|
||||
[Map]: <https://hexdocs.pm/elixir/Map.html>
|
||||
[String]: <https://hexdocs.pm/elixir/String.html>
|
||||
[Atom]: <https://hexdocs.pm/elixir/Atom.html>
|
||||
[List]: <https://hexdocs.pm/elixir/List.html>
|
||||
[Tuple]: <https://hexdocs.pm/elixir/Tuple.html>
|
||||
*/
|
||||
elixirConf = { elixir ? pkgs.elixir }:
|
||||
with lib; let
|
||||
toElixir = value: with builtins;
|
||||
if value == null then "nil" else
|
||||
if value == true then "true" else
|
||||
if value == false then "false" else
|
||||
if isInt value || isFloat value then toString value else
|
||||
if isString value then string value else
|
||||
if isAttrs value then attrs value else
|
||||
if isList value then list value else
|
||||
abort "formats.elixirConf: should never happen (value = ${value})";
|
||||
|
||||
escapeElixir = escape [ "\\" "#" "\"" ];
|
||||
string = value: "\"${escapeElixir value}\"";
|
||||
|
||||
attrs = set:
|
||||
if set ? _elixirType then specialType set
|
||||
else
|
||||
let
|
||||
toKeyword = name: value: "${name}: ${toElixir value}";
|
||||
keywordList = concatStringsSep ", " (mapAttrsToList toKeyword set);
|
||||
in
|
||||
"[" + keywordList + "]";
|
||||
|
||||
listContent = values: concatStringsSep ", " (map toElixir values);
|
||||
|
||||
list = values: "[" + (listContent values) + "]";
|
||||
|
||||
specialType = { value, _elixirType }:
|
||||
if _elixirType == "raw" then value else
|
||||
if _elixirType == "atom" then value else
|
||||
if _elixirType == "map" then elixirMap value else
|
||||
if _elixirType == "tuple" then tuple value else
|
||||
abort "formats.elixirConf: should never happen (_elixirType = ${_elixirType})";
|
||||
|
||||
elixirMap = set:
|
||||
let
|
||||
toEntry = name: value: "${toElixir name} => ${toElixir value}";
|
||||
entries = concatStringsSep ", " (mapAttrsToList toEntry set);
|
||||
in
|
||||
"%{${entries}}";
|
||||
|
||||
tuple = values: "{${listContent values}}";
|
||||
|
||||
toConf = values:
|
||||
let
|
||||
keyConfig = rootKey: key: value:
|
||||
"config ${rootKey}, ${key}, ${toElixir value}";
|
||||
keyConfigs = rootKey: values: mapAttrsToList (keyConfig rootKey) values;
|
||||
rootConfigs = flatten (mapAttrsToList keyConfigs values);
|
||||
in
|
||||
''
|
||||
import Config
|
||||
|
||||
${concatStringsSep "\n" rootConfigs}
|
||||
'';
|
||||
in
|
||||
{
|
||||
type = with lib.types; let
|
||||
valueType = nullOr
|
||||
(oneOf [
|
||||
bool
|
||||
int
|
||||
float
|
||||
str
|
||||
(attrsOf valueType)
|
||||
(listOf valueType)
|
||||
]) // {
|
||||
description = "Elixir value";
|
||||
};
|
||||
in
|
||||
attrsOf (attrsOf (valueType));
|
||||
|
||||
lib =
|
||||
let
|
||||
mkRaw = value: {
|
||||
inherit value;
|
||||
_elixirType = "raw";
|
||||
};
|
||||
|
||||
in
|
||||
{
|
||||
inherit mkRaw;
|
||||
|
||||
/* Fetch an environment variable at runtime, with optional fallback
|
||||
*/
|
||||
mkGetEnv = { envVariable, fallback ? null }:
|
||||
mkRaw "System.get_env(${toElixir envVariable}, ${toElixir fallback})";
|
||||
|
||||
/* Make an Elixir atom.
|
||||
|
||||
Note: lowercase atoms still need to be prefixed by ':'
|
||||
*/
|
||||
mkAtom = value: {
|
||||
inherit value;
|
||||
_elixirType = "atom";
|
||||
};
|
||||
|
||||
/* Make an Elixir tuple out of a list.
|
||||
*/
|
||||
mkTuple = value: {
|
||||
inherit value;
|
||||
_elixirType = "tuple";
|
||||
};
|
||||
|
||||
/* Make an Elixir map out of an attribute set.
|
||||
*/
|
||||
mkMap = value: {
|
||||
inherit value;
|
||||
_elixirType = "map";
|
||||
};
|
||||
|
||||
/* Contains Elixir types. Every type it exports can also be replaced
|
||||
by raw Elixir code (i.e. every type is `either type rawElixir`).
|
||||
|
||||
It also reexports standard types, wrapping them so that they can
|
||||
also be raw Elixir.
|
||||
*/
|
||||
types = with lib.types; let
|
||||
isElixirType = type: x: (x._elixirType or "") == type;
|
||||
|
||||
rawElixir = mkOptionType {
|
||||
name = "rawElixir";
|
||||
description = "raw elixir";
|
||||
check = isElixirType "raw";
|
||||
};
|
||||
|
||||
elixirOr = other: either other rawElixir;
|
||||
in
|
||||
{
|
||||
inherit rawElixir elixirOr;
|
||||
|
||||
atom = elixirOr (mkOptionType {
|
||||
name = "elixirAtom";
|
||||
description = "elixir atom";
|
||||
check = isElixirType "atom";
|
||||
});
|
||||
|
||||
tuple = elixirOr (mkOptionType {
|
||||
name = "elixirTuple";
|
||||
description = "elixir tuple";
|
||||
check = isElixirType "tuple";
|
||||
});
|
||||
|
||||
map = elixirOr (mkOptionType {
|
||||
name = "elixirMap";
|
||||
description = "elixir map";
|
||||
check = isElixirType "map";
|
||||
});
|
||||
# Wrap standard types, since anything in the Elixir configuration
|
||||
# can be raw Elixir
|
||||
} // lib.mapAttrs (_name: type: elixirOr type) lib.types;
|
||||
};
|
||||
|
||||
generate = name: value: pkgs.runCommand name
|
||||
{
|
||||
value = toConf value;
|
||||
passAsFile = [ "value" ];
|
||||
nativeBuildInputs = [ elixir ];
|
||||
} ''
|
||||
cp "$valuePath" "$out"
|
||||
mix format "$out"
|
||||
'';
|
||||
};
|
||||
|
||||
}
|
||||
132
pkgs/pkgs-lib/formats/java-properties/default.nix
Normal file
132
pkgs/pkgs-lib/formats/java-properties/default.nix
Normal file
|
|
@ -0,0 +1,132 @@
|
|||
{ lib, pkgs }:
|
||||
let
|
||||
inherit (lib) types;
|
||||
inherit (types) attrsOf oneOf coercedTo str bool int float package;
|
||||
in
|
||||
{
|
||||
javaProperties = { comment ? "Generated with Nix", boolToString ? lib.boolToString }: {
|
||||
|
||||
# Design note:
|
||||
# A nested representation of inevitably leads to bad UX:
|
||||
# 1. keys like "a.b" must be disallowed, or
|
||||
# the addition of options in a freeformType module
|
||||
# become breaking changes
|
||||
# 2. adding a value for "a" after "a"."b" was already
|
||||
# defined leads to a somewhat hard to understand
|
||||
# Nix error, because that's not something you can
|
||||
# do with attrset syntax. Workaround: "a"."", but
|
||||
# that's too little too late. Another workaround:
|
||||
# mkMerge [ { a = ...; } { a.b = ...; } ].
|
||||
#
|
||||
# Choosing a non-nested representation does mean that
|
||||
# we sacrifice the ability to override at the (conceptual)
|
||||
# hierarchical levels, _if_ an application exhibits those.
|
||||
#
|
||||
# Some apps just use periods instead of spaces in an odd
|
||||
# mix of attempted categorization and natural language,
|
||||
# with no meaningful hierarchy.
|
||||
#
|
||||
# We _can_ choose to support hierarchical config files
|
||||
# via nested attrsets, but the module author should
|
||||
# make sure that problem (2) does not occur.
|
||||
type = let
|
||||
elemType =
|
||||
oneOf ([
|
||||
# `package` isn't generalized to `path` because path values
|
||||
# are ambiguous. Are they host path strings (toString /foo/bar)
|
||||
# or should they be added to the store? ("${/foo/bar}")
|
||||
# The user must decide.
|
||||
(coercedTo package toString str)
|
||||
|
||||
(coercedTo bool boolToString str)
|
||||
(coercedTo int toString str)
|
||||
(coercedTo float toString str)
|
||||
])
|
||||
// { description = "string, package, bool, int or float"; };
|
||||
in attrsOf elemType;
|
||||
|
||||
generate = name: value:
|
||||
pkgs.runCommandLocal name
|
||||
{
|
||||
# Requirements
|
||||
# ============
|
||||
#
|
||||
# 1. Strings in Nix carry over to the same
|
||||
# strings in Java => need proper escapes
|
||||
# 2. Generate files quickly
|
||||
# - A JVM would have to match the app's
|
||||
# JVM to avoid build closure bloat
|
||||
# - Even then, JVM startup would slow
|
||||
# down config generation.
|
||||
#
|
||||
#
|
||||
# Implementation
|
||||
# ==============
|
||||
#
|
||||
# Escaping has two steps
|
||||
#
|
||||
# 1. jq
|
||||
# Escape known separators, in order not
|
||||
# to break up the keys and values.
|
||||
# This handles typical whitespace correctly,
|
||||
# but may produce garbage for other control
|
||||
# characters.
|
||||
#
|
||||
# 2. iconv
|
||||
# Escape >ascii code points to java escapes,
|
||||
# as .properties files are supposed to be
|
||||
# encoded in ISO 8859-1. It's an old format.
|
||||
# UTF-8 behavior may exist in some apps and
|
||||
# libraries, but we can't rely on this in
|
||||
# general.
|
||||
|
||||
passAsFile = [ "value" ];
|
||||
value = builtins.toJSON value;
|
||||
nativeBuildInputs = [
|
||||
pkgs.jq
|
||||
pkgs.libiconvReal
|
||||
];
|
||||
|
||||
jqCode =
|
||||
let
|
||||
main = ''
|
||||
to_entries
|
||||
| .[]
|
||||
| "\(
|
||||
.key
|
||||
| ${commonEscapes}
|
||||
| gsub(" "; "\\ ")
|
||||
| gsub("="; "\\=")
|
||||
) = \(
|
||||
.value
|
||||
| ${commonEscapes}
|
||||
| gsub("^ "; "\\ ")
|
||||
| gsub("\\n "; "\n\\ ")
|
||||
)"
|
||||
'';
|
||||
# Most escapes are equal for both keys and values.
|
||||
commonEscapes = ''
|
||||
gsub("\\\\"; "\\\\")
|
||||
| gsub("\\n"; "\\n\\\n")
|
||||
| gsub("#"; "\\#")
|
||||
| gsub("!"; "\\!")
|
||||
| gsub("\\t"; "\\t")
|
||||
| gsub("\r"; "\\r")
|
||||
'';
|
||||
in
|
||||
main;
|
||||
|
||||
inputEncoding = "UTF-8";
|
||||
|
||||
inherit comment;
|
||||
|
||||
} ''
|
||||
(
|
||||
echo "$comment" | while read -r ln; do echo "# $ln"; done
|
||||
echo
|
||||
jq -r --arg hash '#' "$jqCode" "$valuePath" \
|
||||
| iconv --from-code "$inputEncoding" --to-code JAVA \
|
||||
) > "$out"
|
||||
'';
|
||||
};
|
||||
}
|
||||
27
pkgs/pkgs-lib/formats/java-properties/test/Main.java
Normal file
27
pkgs/pkgs-lib/formats/java-properties/test/Main.java
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
import java.io.FileInputStream;
|
||||
import java.io.InputStream;
|
||||
import java.util.Properties;
|
||||
import java.util.SortedSet;
|
||||
import java.util.TreeSet;
|
||||
|
||||
class Main {
|
||||
public static void main (String args[]) {
|
||||
try {
|
||||
InputStream input = new FileInputStream(args[0]);
|
||||
Properties prop = new Properties();
|
||||
prop.load(input);
|
||||
SortedSet<String> keySet = new TreeSet(prop.keySet());
|
||||
for (String key : keySet) {
|
||||
System.out.println("KEY");
|
||||
System.out.println(key);
|
||||
System.out.println("VALUE");
|
||||
System.out.println(prop.get(key));
|
||||
System.out.println("");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
System.err.println(e.toString());
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
92
pkgs/pkgs-lib/formats/java-properties/test/default.nix
Normal file
92
pkgs/pkgs-lib/formats/java-properties/test/default.nix
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
{ fetchurl
|
||||
, formats
|
||||
, glibcLocales
|
||||
, jdk
|
||||
, lib
|
||||
, stdenv
|
||||
}:
|
||||
|
||||
# This test primarily tests correct escaping.
|
||||
# See also testJavaProperties in
|
||||
# pkgs/pkgs-lib/tests/formats.nix, which tests
|
||||
# type coercions and is a bit easier to read.
|
||||
|
||||
let
|
||||
inherit (lib) concatStrings attrValues mapAttrs;
|
||||
|
||||
javaProperties = formats.javaProperties { };
|
||||
|
||||
input = {
|
||||
foo = "bar";
|
||||
"empty value" = "";
|
||||
"typical.dot.syntax" = "com.sun.awt";
|
||||
"" = "empty key's value";
|
||||
"1" = "2 3";
|
||||
"#" = "not a comment # still not";
|
||||
"!" = "not a comment!";
|
||||
"!a" = "still not! a comment";
|
||||
"!b" = "still not ! a comment";
|
||||
"dos paths" = "C:\\Program Files\\Nix For Windows\\nix.exe";
|
||||
"a \t\nb" = " c";
|
||||
"angry \t\nkey" = ''
|
||||
multi
|
||||
${"\tline\r"}
|
||||
space-
|
||||
indented
|
||||
trailing-space${" "}
|
||||
trailing-space${" "}
|
||||
value
|
||||
'';
|
||||
"this=not" = "bad";
|
||||
"nor = this" = "bad";
|
||||
"all stuff" = "foo = bar";
|
||||
"unicode big brain" = "e = mc□";
|
||||
"ütf-8" = "dûh";
|
||||
# NB: Some editors (vscode) show this _whole_ line in right-to-left order
|
||||
"الجبر" = "أكثر من مجرد أرقام";
|
||||
};
|
||||
|
||||
in
|
||||
stdenv.mkDerivation {
|
||||
name = "pkgs.formats.javaProperties-test-${jdk.name}";
|
||||
nativeBuildInputs = [
|
||||
jdk
|
||||
glibcLocales
|
||||
];
|
||||
|
||||
# technically should go through the type.merge first, but that's tested
|
||||
# in tests/formats.nix.
|
||||
properties = javaProperties.generate "example.properties" input;
|
||||
|
||||
# Expected output as printed by Main.java
|
||||
passAsFile = [ "expected" ];
|
||||
expected = concatStrings (attrValues (
|
||||
mapAttrs
|
||||
(key: value:
|
||||
''
|
||||
KEY
|
||||
${key}
|
||||
VALUE
|
||||
${value}
|
||||
|
||||
''
|
||||
)
|
||||
input
|
||||
));
|
||||
|
||||
src = lib.sourceByRegex ./. [
|
||||
".*\.java"
|
||||
];
|
||||
# On Linux, this can be C.UTF-8, but darwin + zulu requires en_US.UTF-8
|
||||
LANG = "en_US.UTF-8";
|
||||
buildPhase = ''
|
||||
javac Main.java
|
||||
'';
|
||||
doCheck = true;
|
||||
checkPhase = ''
|
||||
cat -v $properties
|
||||
java Main $properties >actual
|
||||
diff -U3 $expectedPath actual
|
||||
'';
|
||||
installPhase = "touch $out";
|
||||
}
|
||||
45
pkgs/pkgs-lib/tests/default.nix
Normal file
45
pkgs/pkgs-lib/tests/default.nix
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
# Call nix-build on this file to run all tests in this directory
|
||||
|
||||
# This produces a link farm derivation with the original attrs
|
||||
# merged on top of it.
|
||||
# You can run parts of the "hierarchy" with for example:
|
||||
# nix-build -A java-properties
|
||||
# See `structured` below.
|
||||
|
||||
{ pkgs ? import ../../.. { } }:
|
||||
let
|
||||
inherit (pkgs.lib) mapAttrs mapAttrsToList isDerivation mergeAttrs foldl' attrValues recurseIntoAttrs;
|
||||
|
||||
structured = {
|
||||
formats = import ./formats.nix { inherit pkgs; };
|
||||
java-properties = recurseIntoAttrs {
|
||||
jdk8 = pkgs.callPackage ../formats/java-properties/test { jdk = pkgs.jdk8; };
|
||||
jdk11 = pkgs.callPackage ../formats/java-properties/test { jdk = pkgs.jdk11_headless; };
|
||||
jdk17 = pkgs.callPackage ../formats/java-properties/test { jdk = pkgs.jdk17_headless; };
|
||||
};
|
||||
};
|
||||
|
||||
flatten = prefix: as:
|
||||
foldl'
|
||||
mergeAttrs
|
||||
{ }
|
||||
(attrValues
|
||||
(mapAttrs
|
||||
(k: v:
|
||||
if isDerivation v
|
||||
then { "${prefix}${k}" = v; }
|
||||
else if v?recurseForDerivations
|
||||
then flatten "${prefix}${k}-" (removeAttrs v [ "recurseForDerivations" ])
|
||||
else builtins.trace v throw "expected derivation or recurseIntoAttrs")
|
||||
as
|
||||
)
|
||||
);
|
||||
in
|
||||
|
||||
# It has to be a link farm for inclusion in the hydra unstable jobset.
|
||||
pkgs.linkFarm "pkgs-lib-formats-tests"
|
||||
(mapAttrsToList
|
||||
(k: v: { name = k; path = v; })
|
||||
(flatten "" structured)
|
||||
)
|
||||
// structured
|
||||
209
pkgs/pkgs-lib/tests/formats.nix
Normal file
209
pkgs/pkgs-lib/tests/formats.nix
Normal file
|
|
@ -0,0 +1,209 @@
|
|||
{ 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: {
|
||||
# We check the input values, so that
|
||||
# - we don't write nonsensical tests that will impede progress
|
||||
# - the test author has a slightly more realistic view of the
|
||||
# final format during development.
|
||||
value = lib.throwIfNot (formatSet.type.check def) (builtins.trace def "definition does not pass the type's check function") def;
|
||||
file = "def${toString n}";
|
||||
}) [ def ]);
|
||||
in formatSet.generate "test-format-file" config;
|
||||
|
||||
runBuildTest = name: { drv, expected }: pkgs.runCommand name {
|
||||
passAsFile = ["expected"];
|
||||
inherit expected drv;
|
||||
} ''
|
||||
if diff -u "$expectedPath" "$drv"; then
|
||||
touch "$out"
|
||||
else
|
||||
echo
|
||||
echo "Got different values than expected; diff above."
|
||||
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 ];
|
||||
path = ./formats.nix;
|
||||
};
|
||||
expected = ''
|
||||
{
|
||||
"attrs": {
|
||||
"foo": null
|
||||
},
|
||||
"false": false,
|
||||
"float": 3.141,
|
||||
"int": 10,
|
||||
"list": [
|
||||
null,
|
||||
null
|
||||
],
|
||||
"null": null,
|
||||
"path": "${./formats.nix}",
|
||||
"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 ];
|
||||
path = ./formats.nix;
|
||||
};
|
||||
expected = ''
|
||||
attrs:
|
||||
foo: null
|
||||
'false': false
|
||||
float: 3.141
|
||||
list:
|
||||
- null
|
||||
- null
|
||||
'null': null
|
||||
path: ${./formats.nix}
|
||||
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
|
||||
'';
|
||||
};
|
||||
|
||||
testIniListToValue = {
|
||||
drv = evalFormat formats.ini { listToValue = concatMapStringsSep ", " (generators.mkValueStringDefault {}); } {
|
||||
foo = {
|
||||
bar = [ null true "test" 1.2 10 ];
|
||||
baz = false;
|
||||
qux = "qux";
|
||||
};
|
||||
};
|
||||
expected = ''
|
||||
[foo]
|
||||
bar=null, true, test, 1.200000, 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.level2.level3]
|
||||
level4 = "deep"
|
||||
'';
|
||||
};
|
||||
|
||||
# This test is responsible for
|
||||
# 1. testing type coercions
|
||||
# 2. providing a more readable example test
|
||||
# Whereas java-properties/default.nix tests the low level escaping, etc.
|
||||
testJavaProperties = {
|
||||
drv = evalFormat formats.javaProperties {} {
|
||||
floaty = 3.1415;
|
||||
tautologies = true;
|
||||
contradictions = false;
|
||||
foo = "bar";
|
||||
# # Disallowed at eval time, because it's ambiguous:
|
||||
# # add to store or convert to string?
|
||||
# root = /root;
|
||||
"1" = 2;
|
||||
package = pkgs.hello;
|
||||
"ütf 8" = "dûh";
|
||||
# NB: Some editors (vscode) show this _whole_ line in right-to-left order
|
||||
"الجبر" = "أكثر من مجرد أرقام";
|
||||
};
|
||||
expected = ''
|
||||
# Generated with Nix
|
||||
|
||||
1 = 2
|
||||
contradictions = false
|
||||
floaty = 3.141500
|
||||
foo = bar
|
||||
package = ${pkgs.hello}
|
||||
tautologies = true
|
||||
\u00fctf\ 8 = d\u00fbh
|
||||
\u0627\u0644\u062c\u0628\u0631 = \u0623\u0643\u062b\u0631 \u0645\u0646 \u0645\u062c\u0631\u062f \u0623\u0631\u0642\u0627\u0645
|
||||
'';
|
||||
};
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue