From 664532c533457fb7bda113ea432fb53710fd7d92 Mon Sep 17 00:00:00 2001 From: Ivan Trubach Date: Wed, 10 Apr 2024 13:34:17 +0300 Subject: [PATCH] Do not rely on $stdenv/setup to set output variables Instead of relying on setup script to set output variables when structured attributes are enabled, iterate over the values of an outputs associative array. See also https://github.com/NixOS/nixpkgs/blob/374fa3532ee7d7496165d3b5a6652a3dcad1ebc2/pkgs/stdenv/generic/setup.sh#L23-L26 --- src/nix/develop.cc | 24 +++++++++++++++----- src/nix/get-env.sh | 33 ++++++++++++++++------------ tests/functional/shell.nix | 8 ------- tests/functional/structured-attrs.sh | 2 +- 4 files changed, 38 insertions(+), 29 deletions(-) diff --git a/src/nix/develop.cc b/src/nix/develop.cc index bb96f7786..b654dc52f 100644 --- a/src/nix/develop.cc +++ b/src/nix/develop.cc @@ -177,6 +177,14 @@ struct BuildEnvironment throw Error("bash variable is not a string"); } + static Associative getAssociative(const Value & value) + { + if (auto assoc = std::get_if(&value)) + return *assoc; + else + throw Error("bash variable is not an associative array"); + } + static Array getStrings(const Value & value) { if (auto str = std::get_if(&value)) @@ -362,13 +370,17 @@ struct Common : InstallableCommand, MixProfile auto outputs = buildEnvironment.vars.find("outputs"); assert(outputs != buildEnvironment.vars.end()); - // FIXME: properly unquote 'outputs'. StringMap rewrites; - for (auto & outputName : BuildEnvironment::getStrings(outputs->second)) { - auto from = buildEnvironment.vars.find(outputName); - assert(from != buildEnvironment.vars.end()); - // FIXME: unquote - rewrites.insert({BuildEnvironment::getString(from->second), outputsDir + "/" + outputName}); + if (buildEnvironment.providesStructuredAttrs()) { + for (auto & [outputName, from] : BuildEnvironment::getAssociative(outputs->second)) { + rewrites.insert({from, outputsDir + "/" + outputName}); + } + } else { + for (auto & outputName : BuildEnvironment::getStrings(outputs->second)) { + auto from = buildEnvironment.vars.find(outputName); + assert(from != buildEnvironment.vars.end()); + rewrites.insert({BuildEnvironment::getString(from->second), outputsDir + "/" + outputName}); + } } /* Substitute redirects. */ diff --git a/src/nix/get-env.sh b/src/nix/get-env.sh index 832cc2f11..071edf9b9 100644 --- a/src/nix/get-env.sh +++ b/src/nix/get-env.sh @@ -128,20 +128,25 @@ __escapeString() { printf '"%s"' "$__s" } -# In case of `__structuredAttrs = true;` the list of outputs is an associative -# array with a format like `outname => /nix/store/hash-drvname-outname`, so `__olist` -# must contain the array's keys (hence `${!...[@]}`) in this case. -if [ -e "$NIX_ATTRS_SH_FILE" ]; then - __olist="${!outputs[@]}" -else - __olist=$outputs -fi - -for __output in $__olist; do - if [[ -z $__done ]]; then - __dumpEnv > ${!__output} +__dumpEnvToOutput() { + local __output="$1" + if [[ -z ${__done-} ]]; then + __dumpEnv > "$__output" __done=1 else - echo -n >> "${!__output}" + echo -n >> "$__output" fi -done +} + +# In case of `__structuredAttrs = true;` the list of outputs is an associative +# array with a format like `outname => /nix/store/hash-drvname-outname`. +# Otherwise it is a space-separated list of output variable names. +if [ -e "$NIX_ATTRS_SH_FILE" ]; then + for __output in "${outputs[@]}"; do + __dumpEnvToOutput "$__output" + done +else + for __outname in $outputs; do + __dumpEnvToOutput "${!__outname}" + done +fi diff --git a/tests/functional/shell.nix b/tests/functional/shell.nix index 92d94fbc2..6a7dd7ad1 100644 --- a/tests/functional/shell.nix +++ b/tests/functional/shell.nix @@ -21,14 +21,6 @@ let pkgs = rec { export PATH=$PATH:$pkg/bin done - # mimic behavior of stdenv for `$out` etc. for structured attrs. - if [ -n "''${NIX_ATTRS_SH_FILE}" ]; then - for o in "''${!outputs[@]}"; do - eval "''${o}=''${outputs[$o]}" - export "''${o}" - done - fi - declare -a arr1=(1 2 "3 4" 5) declare -a arr2=(x $'\n' $'x\ny') fun() { diff --git a/tests/functional/structured-attrs.sh b/tests/functional/structured-attrs.sh index f11992dcd..6711efbb4 100644 --- a/tests/functional/structured-attrs.sh +++ b/tests/functional/structured-attrs.sh @@ -32,4 +32,4 @@ jsonOut="$(nix print-dev-env -f structured-attrs-shell.nix --json)" test "$(<<<"$jsonOut" jq '.structuredAttrs|keys|.[]' -r)" = "$(printf ".attrs.json\n.attrs.sh")" -test "$(<<<"$jsonOut" jq '.variables.out.value' -r)" = "$(<<<"$jsonOut" jq '.structuredAttrs.".attrs.json"' -r | jq -r '.outputs.out')" +test "$(<<<"$jsonOut" jq '.variables.outputs.value.out' -r)" = "$(<<<"$jsonOut" jq '.structuredAttrs.".attrs.json"' -r | jq -r '.outputs.out')"