From 3504c811a55ecd58e0712cf24829c67c192f5e80 Mon Sep 17 00:00:00 2001 From: Maximilian Bosch Date: Tue, 18 May 2021 15:07:30 +0200 Subject: [PATCH] Add testcase for `nix develop` with `__structuredAttrs` --- src/nix/develop.cc | 3 +++ src/nix/get-env.sh | 9 ++++++--- tests/shell.nix | 8 ++++++++ tests/structured-attrs-shell.nix | 2 ++ tests/structured-attrs.sh | 5 +++++ 5 files changed, 24 insertions(+), 3 deletions(-) diff --git a/src/nix/develop.cc b/src/nix/develop.cc index 3443fab73..ee782c4ec 100644 --- a/src/nix/develop.cc +++ b/src/nix/develop.cc @@ -256,6 +256,9 @@ struct Common : InstallableCommand, MixProfile // FIXME: properly unquote 'outputs'. StringMap rewrites; for (auto & outputName : tokenizeString>(replaceStrings(outputs->second.quoted, "'", ""))) { + // Hacky way to obtain the key of an associate array. This is needed for strctured attrs where + // `outputs` is an associative array. If the regex isn't matched, the non-structured-attrs behavior will + // be used. std::regex ptrn(R"re(\[([A-z0-9]+)\]=.*)re"); std::smatch match; if (std::regex_match(outputName, match, ptrn)) { diff --git a/src/nix/get-env.sh b/src/nix/get-env.sh index b6b8310a9..431440516 100644 --- a/src/nix/get-env.sh +++ b/src/nix/get-env.sh @@ -8,6 +8,9 @@ if [[ -n $stdenv ]]; then source $stdenv/setup fi +# 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 .attrs.sh ]; then __olist="${!outputs[@]}" else @@ -16,10 +19,10 @@ fi for __output in $__olist; do if [[ -z $__done ]]; then - export > ${!__output} - set >> ${!__output} + export > "${!__output}" + set >> "${!__output}" __done=1 else - echo -n >> ${!__output} + echo -n >> "${!__output}" fi done diff --git a/tests/shell.nix b/tests/shell.nix index 24ebcc04c..53a32059b 100644 --- a/tests/shell.nix +++ b/tests/shell.nix @@ -8,6 +8,14 @@ let pkgs = rec { for pkg in $buildInputs; do export PATH=$PATH:$pkg/bin done + + # mimic behavior of stdenv for `$out` etc. for structured attrs. + if [ -n "''${ATTRS_SH_FILE}" ]; then + for o in "''${!outputs[@]}"; do + eval "''${o}=''${outputs[$o]}" + export "''${o}" + done + fi ''; stdenv = mkDerivation { diff --git a/tests/structured-attrs-shell.nix b/tests/structured-attrs-shell.nix index 0c01c2568..57c1e6bd2 100644 --- a/tests/structured-attrs-shell.nix +++ b/tests/structured-attrs-shell.nix @@ -6,10 +6,12 @@ let mkdir $out; echo bla > $out/bla ''; }; + inherit (import ./shell.nix { inNixShell = true; }) stdenv; in mkDerivation { name = "structured2"; __structuredAttrs = true; + inherit stdenv; outputs = [ "out" "dev" ]; my.list = [ "a" "b" "c" ]; exportReferencesGraph.refs = [ dep ]; diff --git a/tests/structured-attrs.sh b/tests/structured-attrs.sh index 241835539..f851b3cbb 100644 --- a/tests/structured-attrs.sh +++ b/tests/structured-attrs.sh @@ -12,3 +12,8 @@ nix-build structured-attrs.nix -A all -o $TEST_ROOT/result export NIX_BUILD_SHELL=$SHELL env NIX_PATH=nixpkgs=shell.nix nix-shell structured-attrs-shell.nix \ --run 'test -e .attrs.json; test "3" = "$(jq ".my.list|length" < $ATTRS_JSON_FILE)"' + +# `nix develop` is a slightly special way of dealing with environment vars, it parses +# these from a shell-file exported from a derivation. This is to test especially `outputs` +# (which is an associative array in thsi case) being fine. +nix develop -f structured-attrs-shell.nix -c bash -c 'test -n "$out"'