Skip to content

Commit

Permalink
writers: introduce data writers
Browse files Browse the repository at this point in the history
Make it easy to write structured data back to disk.
  • Loading branch information
zimbatm committed Jul 22, 2023
1 parent d0c7ffc commit 504e42b
Show file tree
Hide file tree
Showing 3 changed files with 126 additions and 4 deletions.
80 changes: 80 additions & 0 deletions pkgs/build-support/writers/data.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
{ lib, runCommandNoCC, dasel }:
let
daselBin = lib.getExe dasel;

inherit (lib)
last
optionalString
types
;
in
rec {
# Creates a transformer function that writes input data to disk, transformed
# by both the `input` and `output` arguments.
#
# Type: makeDataWriter :: input -> output -> nameOrPath -> data -> (any -> string) -> string -> string -> any -> derivation
#
# input :: T -> string: function that takes the nix data and returns a string
# output :: string: script that takes the $inputFile and write the result into $out
# nameOrPath :: string: if the name contains a / the files gets written to a sub-folder of $out. The derivation name is the basename of this argument.
# data :: T: the data that will be converted.
#
# Example:
# writeJSON = makeDataWriter { input = builtins.toJSON; output = "cp $inputPath $out"; };
# myConfig = writeJSON "config.json" { hello = "world"; }
#
makeDataWriter = { input ? lib.id, output ? "cp $inputPath $out" }: nameOrPath: data:
assert lib.or (types.path.check nameOrPath) (builtins.match "([0-9A-Za-z._])[0-9A-Za-z._-]*" nameOrPath != null);
let
name = last (builtins.split "/" nameOrPath);
in
runCommandNoCC name
{
input = input data;
passAsFile = [ "input" ];
} ''
${output}
${optionalString (types.path.check nameOrPath) ''
mv $out tmp
mkdir -p $out/$(dirname "${nameOrPath}")
mv tmp $out/${nameOrPath}
''}
'';

# Writes the content to text.
#
# Example:
# writeText "filename.txt" "file content"
writeText = makeDataWriter {
input = toString;
output = "cp $inputPath $out";
};

# Writes the content to a JSON file.
#
# Example:
# writeJSON "data.json" { hello = "world"; }
writeJSON = makeDataWriter {
input = builtins.toJSON;
output = "${daselBin} -f $inputPath -r json -w json > $out";
};

# Writes the content to a TOML file.
#
# Example:
# writeTOML "data.toml" { hello = "world"; }
writeTOML = makeDataWriter {
input = builtins.toJSON;
output = "${daselBin} -f $inputPath -r json -w toml > $out";
};

# Writes the content to a YAML file.
#
# Example:
# writeYAML "data.yaml" { hello = "world"; }
writeYAML = makeDataWriter {
input = builtins.toJSON;
output = "${daselBin} -f $inputPath -r json -w yaml > $out";
};
}
12 changes: 10 additions & 2 deletions pkgs/build-support/writers/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,16 @@
let
aliases = if config.allowAliases then (import ./aliases.nix lib) else prev: {};

scriptWriters = import ./scripts.nix { inherit pkgs lib; };
# Writers for JSON-like data structures
dataWriters = import ./data.nix {
inherit lib; inherit (pkgs) runCommandNoCC dasel;
};

writers = scriptWriters;
# Writers for scripts
scriptWriters = import ./scripts.nix {
inherit lib pkgs;
};

writers = scriptWriters // dataWriters;
in
writers // (aliases writers)
38 changes: 36 additions & 2 deletions pkgs/build-support/writers/test.nix
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ with writers;
let
expectSuccess = test:
runCommand "run-${test.name}" {} ''
if test "$(${test})" != "success"; then
if [[ "$(${test})" != success ]]; then
echo 'test ${test.name} failed'
exit 1
fi
Expand All @@ -24,11 +24,24 @@ let

expectSuccessBin = test:
runCommand "run-${test.name}" {} ''
if test "$(${lib.getExe test})" != "success"; then
if [[ "$(${lib.getExe test})" != success ]]; then
echo 'test ${test.name} failed'
exit 1
fi
touch $out
'';

expectDataEqual = { file, expected }:
let
expectedFile = writeText "${file.name}-expected" expected;
in
runCommand "run-${file.name}" {} ''
if ! diff -u ${file} ${expectedFile}; then
echo 'test ${file.name} failed'
exit 1
fi
touch $out
'';
in
Expand Down Expand Up @@ -235,4 +248,25 @@ lib.recurseIntoAttrs {
_ -> print "fail"
''));
};

data = {
json = expectDataEqual {
file = writeJSON "data.json" { hello = "world"; };
expected = ''
{
"hello": "world"
}
'';
};

toml = expectDataEqual {
file = writeTOML "data.toml" { hello = "world"; };
expected = "hello = 'world'\n";
};

yaml = expectDataEqual {
file = writeYAML "data.yaml" { hello = "world"; };
expected = "hello: world\n";
};
};
}

0 comments on commit 504e42b

Please sign in to comment.