Merge pull request #10455 from tie/structured-attrs-get-env

Do not rely on $stdenv/setup to set output variables
This commit is contained in:
Théophane Hufschmitt 2024-04-11 06:48:36 +02:00 committed by GitHub
commit def00d7b52
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 38 additions and 29 deletions

View file

@ -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<Associative>(&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<String>(&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. */

View file

@ -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

View file

@ -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() {

View file

@ -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')"