From 1a402e0c53609df25539ae852ca7db6696e6f174 Mon Sep 17 00:00:00 2001 From: Martin Fischer Date: Tue, 31 Dec 2024 13:52:18 +0100 Subject: [PATCH 1/2] test: test eval of newlines with raw output --- tests/functional/eval.nix | 2 +- tests/functional/eval.sh | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/functional/eval.nix b/tests/functional/eval.nix index befbd17a9..cabf28c29 100644 --- a/tests/functional/eval.nix +++ b/tests/functional/eval.nix @@ -1,5 +1,5 @@ { int = 123; - str = "foo"; + str = "foo\nbar"; attr.foo = "bar"; } diff --git a/tests/functional/eval.sh b/tests/functional/eval.sh index 7af49d7fd..18f8589df 100755 --- a/tests/functional/eval.sh +++ b/tests/functional/eval.sh @@ -16,8 +16,8 @@ EOF nix eval --expr 'assert 1 + 2 == 3; true' [[ $(nix eval int -f "./eval.nix") == 123 ]] -[[ $(nix eval str -f "./eval.nix") == '"foo"' ]] -[[ $(nix eval str --raw -f "./eval.nix") == 'foo' ]] +[[ $(nix eval str -f "./eval.nix") == '"foo\nbar"' ]] +[[ $(nix eval str --raw -f "./eval.nix") == $'foo\nbar' ]] [[ "$(nix eval attr -f "./eval.nix")" == '{ foo = "bar"; }' ]] [[ $(nix eval attr --json -f "./eval.nix") == '{"foo":"bar"}' ]] [[ $(nix eval int -f - < "./eval.nix") == 123 ]] @@ -28,7 +28,7 @@ nix eval --expr 'assert 1 + 2 == 3; true' nix-instantiate --eval -E 'assert 1 + 2 == 3; true' [[ $(nix-instantiate -A int --eval "./eval.nix") == 123 ]] -[[ $(nix-instantiate -A str --eval "./eval.nix") == '"foo"' ]] +[[ $(nix-instantiate -A str --eval "./eval.nix") == '"foo\nbar"' ]] [[ "$(nix-instantiate -A attr --eval "./eval.nix")" == '{ foo = "bar"; }' ]] [[ $(nix-instantiate -A attr --eval --json "./eval.nix") == '{"foo":"bar"}' ]] [[ $(nix-instantiate -A int --eval - < "./eval.nix") == 123 ]] From 7a8a28629c61c75af010ff0a5a88c16c4ce536c7 Mon Sep 17 00:00:00 2001 From: Martin Fischer Date: Tue, 31 Dec 2024 14:04:50 +0100 Subject: [PATCH 2/2] feat(nix-instantiate): add --raw flag The experimental `nix eval` command already supports a `--raw` flag. This commit implements the same flag for the stable nix-instantiate command. Until now instructions and scripts that didn't want to rely on experimental features had to use workarounds such as: nix-instantiate --eval | tr -d \" (which also undesirably also removes double quotation marks within the string), or nix-instantiate --eval | jq -j (which undesirably depends on another package). Co-authored-by: Silvan Mosberger --- doc/manual/rl-next/nix-instantiate-raw.md | 8 ++++++++ doc/manual/source/command-ref/nix-copy-closure.md | 2 +- doc/manual/source/command-ref/nix-instantiate.md | 7 ++++++- src/nix-instantiate/nix-instantiate.cc | 10 ++++++++-- tests/functional/eval.sh | 1 + 5 files changed, 24 insertions(+), 4 deletions(-) create mode 100644 doc/manual/rl-next/nix-instantiate-raw.md diff --git a/doc/manual/rl-next/nix-instantiate-raw.md b/doc/manual/rl-next/nix-instantiate-raw.md new file mode 100644 index 000000000..fb4a72b88 --- /dev/null +++ b/doc/manual/rl-next/nix-instantiate-raw.md @@ -0,0 +1,8 @@ +--- +synopsis: "`nix-instantiate --eval` now supports `--raw`" +prs: [12119] +--- + +The `nix-instantiate --eval` command now supports a `--raw` flag, when used +the evaluation result must be a string, which is printed verbatim without +quotation marks or escaping. diff --git a/doc/manual/source/command-ref/nix-copy-closure.md b/doc/manual/source/command-ref/nix-copy-closure.md index 8cfd6ebad..b7e31d93b 100644 --- a/doc/manual/source/command-ref/nix-copy-closure.md +++ b/doc/manual/source/command-ref/nix-copy-closure.md @@ -84,7 +84,7 @@ When using public key authentication, you can avoid typing the passphrase with ` > Copy GNU Hello from a remote machine using a known store path, and run it: > > ```shell-session -> $ storePath="$(nix-instantiate --eval '' -I nixpkgs=channel:nixpkgs-unstable -A hello.outPath | tr -d '"')" +> $ storePath="$(nix-instantiate --eval --raw '' -I nixpkgs=channel:nixpkgs-unstable -A hello.outPath)" > $ nix-copy-closure --from alice@itchy.example.org "$storePath" > $ "$storePath"/bin/hello > Hello, world! diff --git a/doc/manual/source/command-ref/nix-instantiate.md b/doc/manual/source/command-ref/nix-instantiate.md index 6f6fcdc1f..487ef8f10 100644 --- a/doc/manual/source/command-ref/nix-instantiate.md +++ b/doc/manual/source/command-ref/nix-instantiate.md @@ -5,7 +5,7 @@ # Synopsis `nix-instantiate` - [`--parse` | `--eval` [`--strict`] [`--json`] [`--xml`] ] + [`--parse` | `--eval` [`--strict`] [`--raw` | `--json` | `--xml`] ] [`--read-write-mode`] [`--arg` *name* *value*] [{`--attr`| `-A`} *attrPath*] @@ -102,6 +102,11 @@ standard input. > This option can cause non-termination, because lazy data > structures can be infinitely large. +- `--raw` + + When used with `--eval`, the evaluation result must be a string, + which is printed verbatim, without quoting, escaping or trailing newline. + - `--json` When used with `--eval`, print the resulting value as an JSON diff --git a/src/nix-instantiate/nix-instantiate.cc b/src/nix-instantiate/nix-instantiate.cc index c48549511..09d354832 100644 --- a/src/nix-instantiate/nix-instantiate.cc +++ b/src/nix-instantiate/nix-instantiate.cc @@ -24,7 +24,7 @@ static Path gcRoot; static int rootNr = 0; -enum OutputKind { okPlain, okXML, okJSON }; +enum OutputKind { okPlain, okRaw, okXML, okJSON }; void processExpr(EvalState & state, const Strings & attrPaths, bool parseOnly, bool strict, Bindings & autoArgs, @@ -50,7 +50,11 @@ void processExpr(EvalState & state, const Strings & attrPaths, vRes = v; else state.autoCallFunction(autoArgs, v, vRes); - if (output == okXML) + if (output == okRaw) + std::cout << *state.coerceToString(noPos, vRes, context, "while generating the nix-instantiate output"); + // We intentionally don't output a newline here. The default PS1 for Bash in NixOS starts with a newline + // and other interactive shells like Zsh are smart enough to print a missing newline before the prompt. + else if (output == okXML) printValueAsXML(state, strict, location, vRes, std::cout, context, noPos); else if (output == okJSON) { printValueAsJSON(state, strict, vRes, v.determinePos(noPos), std::cout, context); @@ -132,6 +136,8 @@ static int main_nix_instantiate(int argc, char * * argv) gcRoot = getArg(*arg, arg, end); else if (*arg == "--indirect") ; + else if (*arg == "--raw") + outputKind = okRaw; else if (*arg == "--xml") outputKind = okXML; else if (*arg == "--json") diff --git a/tests/functional/eval.sh b/tests/functional/eval.sh index 18f8589df..ed9c214f5 100755 --- a/tests/functional/eval.sh +++ b/tests/functional/eval.sh @@ -29,6 +29,7 @@ nix eval --expr 'assert 1 + 2 == 3; true' nix-instantiate --eval -E 'assert 1 + 2 == 3; true' [[ $(nix-instantiate -A int --eval "./eval.nix") == 123 ]] [[ $(nix-instantiate -A str --eval "./eval.nix") == '"foo\nbar"' ]] +[[ $(nix-instantiate -A str --raw --eval "./eval.nix") == $'foo\nbar' ]] [[ "$(nix-instantiate -A attr --eval "./eval.nix")" == '{ foo = "bar"; }' ]] [[ $(nix-instantiate -A attr --eval --json "./eval.nix") == '{"foo":"bar"}' ]] [[ $(nix-instantiate -A int --eval - < "./eval.nix") == 123 ]]