Commit 47ad60d4 authored by Profpatsch's avatar Profpatsch

containers/helpers: rewrite withScript to withOptions

All scripts generated now have true argparsers (and don’t throw undebuggable
error messages or default to empty string when passed the wrong data).
The usage descriptions should also help to keep complexity in check.
parent f2225c90
{ stdenv, helpers, writeScript, writeText, nix-prefetch-scripts }:
{ stdenv, helpers, writeText, nix-prefetch-scripts }:
let
args = writeText "args.nix" ''
{ nixPrefetchGit = "${nix-prefetch-scripts}/bin/nix-prefetch-git"; }
'';
in writeScript "fetchgit-updater" ''
#!${stdenv.shell}
in helpers.script.withOptions {
name = "fetchgit-updater";
description = "Update the json description of a git source.";
options = {
file = {
description = "The json file to update.";
checks = [ helpers.script.optionChecks.fileExists ];
};
};
script = ''
${helpers.json2string} \
${args} \
${./json-to-prefetch-invocation.nix} \
"$1"
''
"$file"
'';
}
{ lib, pkgs, stdenv, libPath ? <nixpkgs/lib> }:
{ lib, pkgs, stdenv, helpers, libPath ? <nixpkgs/lib> }:
# TODO: Do we need all of lib?
# TODO: Is there a better way to pass stuff to nix?!
# TODO: better argument handling
let
transGeneric = nixCommand: ''
transGeneric = name: synopsis: nixCommand: with helpers.script;
withOptions {
inherit name synopsis;
description = ''
Similar to jq, but arguably more powerful.
The nix script `trans` is a function that takes
`args` as first argument (a nix attrset)
and a `json` file as a nix value as second argument.
`trans` has the <nixpkgs/lib> attrset in scope.
Through `args` it is possible to pass e.g.
nix store paths or files or more complex data.
'';
options = {
args = {
description = "Nix arguments to pass to the transformer.";
checks = [ optionChecks.fileExists ];
};
trans = {
description = "Nix JSON transformer function.";
checks = [ optionChecks.fileExists ];
};
json = {
description = "JSON input data";
checks = [ optionChecks.fileExists ];
};
};
script = ''
#!${stdenv.shell}
ARGS="$(realpath "$1")"
ARGS="$(realpath "$args")"
DIR=$(mktemp -d)
cat >$DIR/script-input.nix <<EOF
with import ${libPath};
$(cat "$2")
$(cat "$trans")
EOF
JSON="$(realpath "$3")"
JSON="$(realpath "$json")"
cat >$DIR/script.nix <<EOF
let
......@@ -31,27 +57,32 @@ let
source ${pkgs.setupLocalNixStore}
${nixCommand}
'';
};
json2json = pkgs.writeScript "nix-json-to-json"
(transGeneric ''
json2json = transGeneric
"nix-json-to-json"
"Transform a json file using a nix expression."
''
${pkgs.nix}/bin/nix eval \
--json \
--show-trace \
-f $DIR/script.nix \
""
'');
'';
# TODO: Not sure if the produced output path is always
# reachable from the result? Maybe enable passing a valid
# path from outside?
json2string = pkgs.writeScript "nix-json-to-out"
(transGeneric ''
json2string = transGeneric
"nix-json-to-out"
"Convert a json file to a string using a nix expression."
''
${pkgs.nix}/bin/nix eval \
--raw \
--show-trace \
-f $DIR/script.nix \
""
'');
'';
mkjson = json: pkgs.writeText "test.json" (builtins.toJSON json);
......@@ -60,7 +91,10 @@ let
eq = nixFile: jsonFile: resultFile: ''
echo "{}" > ./args.nix
${pkgs.diffutils}/bin/diff \
<(${json2json} ./args.nix ${nixFile} ${jsonFile}) \
<(${json2json} \
--args ./args.nix \
--trans ${nixFile} \
--json ${jsonFile}) \
${resultFile}
'';
in {
......@@ -85,7 +119,10 @@ let
buildEchoScriptFromJsonString = ''
echo "{}" > ./args.nix
echo "{}: str: str" > ./echo.nix
${json2string} ./args.nix ./echo.nix ${mkjson "hello!\nworld!"} \
${json2string} \
--args=./args.nix \
--trans=./echo.nix \
--json=${mkjson "hello!\nworld!"} \
> out
grep "hello!" <out
grep "world!" <out
......@@ -104,7 +141,10 @@ let
'';
in ''
touch empty.json
${json2string} ${args} ${echoshell} empty.json \
${json2string} \
--args ${args} \
--trans ${echoshell} \
--json empty.json \
| ${stdenv.shell} -s \
| grep echoshell
'';
......
{ stdenv, lib, writeText, writeScript }:
{ stdenv, lib, writeText, writeScript, runCommand, utillinux }:
{
name,
description,
synopsis,
description ? "",
# { description, checks }
options,
script
......@@ -13,8 +14,9 @@ let
usageAttr = n: v: "--${n} (${checks v.checks}): ${v.description}";
in
writeText "${name}-usage.txt" ''
${name}: ${description}
${name}: ${synopsis}
${description}
${name}
${builtins.concatStringsSep "\n "
(lib.mapAttrsToList usageAttr options)}
......@@ -49,8 +51,12 @@ let
getopt =
let
opts = nameMapOptsSep "," (o: "${o}:");
getoptBin = runCommand "getopt-bin" {} ''
install -D ${lib.getBin utillinux}/bin/getopt \
$out/bin/getopt
'';
in ''
PARSED__=$(getopt --name="${name}" \
PARSED__=$(${getoptBin}/bin/getopt --name="${name}" \
--options= \
--longoptions=${opts} \
-- "$@")
......@@ -123,8 +129,8 @@ let
'';
argParser = writeText "${name}-argparser.sh" ''
# This is an automatically generated argparser.
optParser = writeText "${name}-optparser.sh" ''
# This is an automatically generated optparser.
# It sets the following bash variables:
# ${nameMapOptsSep ", " lib.id}
# Inspired by:
......@@ -150,7 +156,7 @@ let
#!${stdenv.shell}
# call the argparser, which sets the following variables:
# ${nameMapOptsSep ", " lib.id}
source ${argParser}
source ${optParser}
${script}
'';
......
{ pkgs }:
let
writeScriptArgparse = pkgs.callPackage ./build-script.nix {};
writeScriptOptparse = pkgs.callPackage ./build-script.nix {};
checks = {
fileExists = {
......@@ -13,9 +13,9 @@ let
# TODO: nice tests
tests = {
foo = writeScriptArgparse {
foo = writeScriptOptparse {
name = "myname";
description = "dis is description";
synopsis = "dis is synopsis";
options = {
args = {
description = "argument description";
......@@ -34,7 +34,8 @@ let
};
in {
argumentChecks = checks;
withArguments = writeScriptArgparse;
# tests = tests;
optionChecks = checks;
# TODO: Opt/Arg? Argh!
withOptions = writeScriptOptparse;
tests = tests;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment