Merge pull request #318614 from wolfgangwalther/structured-attrs-setup-hooks

treewide: support structuredAttrs in setup hooks
This commit is contained in:
Someone
2024-08-13 19:29:36 +00:00
committed by GitHub
7 changed files with 233 additions and 143 deletions
+6 -1
View File
@@ -2,6 +2,11 @@ preConfigurePhases="${preConfigurePhases:-} autoreconfPhase"
autoreconfPhase() {
runHook preAutoreconf
autoreconf ${autoreconfFlags:---install --force --verbose}
local flagsArray=()
: "${autoreconfFlags:=--install --force --verbose}"
concatTo flagsArray autoreconfFlags
autoreconf "${flagsArray[@]}"
runHook postAutoreconf
}
+31 -28
View File
@@ -38,7 +38,7 @@ cmakeConfigurePhase() {
fi
if [ -z "${dontAddPrefix-}" ]; then
cmakeFlags="-DCMAKE_INSTALL_PREFIX=$prefix $cmakeFlags"
prependToVar cmakeFlags "-DCMAKE_INSTALL_PREFIX=$prefix"
fi
# We should set the proper `CMAKE_SYSTEM_NAME`.
@@ -47,21 +47,21 @@ cmakeConfigurePhase() {
# Unfortunately cmake seems to expect absolute paths for ar, ranlib, and
# strip. Otherwise they are taken to be relative to the source root of the
# package being built.
cmakeFlags="-DCMAKE_CXX_COMPILER=$CXX $cmakeFlags"
cmakeFlags="-DCMAKE_C_COMPILER=$CC $cmakeFlags"
cmakeFlags="-DCMAKE_AR=$(command -v $AR) $cmakeFlags"
cmakeFlags="-DCMAKE_RANLIB=$(command -v $RANLIB) $cmakeFlags"
cmakeFlags="-DCMAKE_STRIP=$(command -v $STRIP) $cmakeFlags"
prependToVar cmakeFlags "-DCMAKE_CXX_COMPILER=$CXX"
prependToVar cmakeFlags "-DCMAKE_C_COMPILER=$CC"
prependToVar cmakeFlags "-DCMAKE_AR=$(command -v $AR)"
prependToVar cmakeFlags "-DCMAKE_RANLIB=$(command -v $RANLIB)"
prependToVar cmakeFlags "-DCMAKE_STRIP=$(command -v $STRIP)"
# on macOS we want to prefer Unix-style headers to Frameworks
# because we usually do not package the framework
cmakeFlags="-DCMAKE_FIND_FRAMEWORK=LAST $cmakeFlags"
prependToVar cmakeFlags "-DCMAKE_FIND_FRAMEWORK=LAST"
# we never want to use the global macOS SDK
cmakeFlags="-DCMAKE_OSX_SYSROOT= $cmakeFlags"
prependToVar cmakeFlags "-DCMAKE_OSX_SYSROOT="
# correctly detect our clang compiler
cmakeFlags="-DCMAKE_POLICY_DEFAULT_CMP0025=NEW $cmakeFlags"
prependToVar cmakeFlags "-DCMAKE_POLICY_DEFAULT_CMP0025=NEW"
# This installs shared libraries with a fully-specified install
# name. By default, cmake installs shared libraries with just the
@@ -70,7 +70,7 @@ cmakeConfigurePhase() {
# libraries are in a system path or in the same directory as the
# executable. This flag makes the shared library accessible from its
# nix/store directory.
cmakeFlags="-DCMAKE_INSTALL_NAME_DIR=${!outputLib}/lib $cmakeFlags"
prependToVar cmakeFlags "-DCMAKE_INSTALL_NAME_DIR=${!outputLib}/lib"
# The docdir flag needs to include PROJECT_NAME as per GNU guidelines,
# try to extract it from CMakeLists.txt.
@@ -93,39 +93,42 @@ cmakeConfigurePhase() {
# This ensures correct paths with multiple output derivations
# It requires the project to use variables from GNUInstallDirs module
# https://cmake.org/cmake/help/latest/module/GNUInstallDirs.html
cmakeFlags="-DCMAKE_INSTALL_BINDIR=${!outputBin}/bin $cmakeFlags"
cmakeFlags="-DCMAKE_INSTALL_SBINDIR=${!outputBin}/sbin $cmakeFlags"
cmakeFlags="-DCMAKE_INSTALL_INCLUDEDIR=${!outputInclude}/include $cmakeFlags"
cmakeFlags="-DCMAKE_INSTALL_OLDINCLUDEDIR=${!outputInclude}/include $cmakeFlags"
cmakeFlags="-DCMAKE_INSTALL_MANDIR=${!outputMan}/share/man $cmakeFlags"
cmakeFlags="-DCMAKE_INSTALL_INFODIR=${!outputInfo}/share/info $cmakeFlags"
cmakeFlags="-DCMAKE_INSTALL_DOCDIR=${!outputDoc}/share/doc/${shareDocName} $cmakeFlags"
cmakeFlags="-DCMAKE_INSTALL_LIBDIR=${!outputLib}/lib $cmakeFlags"
cmakeFlags="-DCMAKE_INSTALL_LIBEXECDIR=${!outputLib}/libexec $cmakeFlags"
cmakeFlags="-DCMAKE_INSTALL_LOCALEDIR=${!outputLib}/share/locale $cmakeFlags"
prependToVar cmakeFlags "-DCMAKE_INSTALL_BINDIR=${!outputBin}/bin"
prependToVar cmakeFlags "-DCMAKE_INSTALL_SBINDIR=${!outputBin}/sbin"
prependToVar cmakeFlags "-DCMAKE_INSTALL_INCLUDEDIR=${!outputInclude}/include"
prependToVar cmakeFlags "-DCMAKE_INSTALL_OLDINCLUDEDIR=${!outputInclude}/include"
prependToVar cmakeFlags "-DCMAKE_INSTALL_MANDIR=${!outputMan}/share/man"
prependToVar cmakeFlags "-DCMAKE_INSTALL_INFODIR=${!outputInfo}/share/info"
prependToVar cmakeFlags "-DCMAKE_INSTALL_DOCDIR=${!outputDoc}/share/doc/${shareDocName}"
prependToVar cmakeFlags "-DCMAKE_INSTALL_LIBDIR=${!outputLib}/lib"
prependToVar cmakeFlags "-DCMAKE_INSTALL_LIBEXECDIR=${!outputLib}/libexec"
prependToVar cmakeFlags "-DCMAKE_INSTALL_LOCALEDIR=${!outputLib}/share/locale"
# Dont build tests when doCheck = false
if [ -z "${doCheck-}" ]; then
cmakeFlags="-DBUILD_TESTING=OFF $cmakeFlags"
prependToVar cmakeFlags "-DBUILD_TESTING=OFF"
fi
# Always build Release, to ensure optimisation flags
cmakeFlags="-DCMAKE_BUILD_TYPE=${cmakeBuildType:-Release} $cmakeFlags"
prependToVar cmakeFlags "-DCMAKE_BUILD_TYPE=${cmakeBuildType:-Release}"
# Disable user package registry to avoid potential side effects
# and unecessary attempts to access non-existent home folder
# https://cmake.org/cmake/help/latest/manual/cmake-packages.7.html#disabling-the-package-registry
cmakeFlags="-DCMAKE_EXPORT_NO_PACKAGE_REGISTRY=ON $cmakeFlags"
cmakeFlags="-DCMAKE_FIND_USE_PACKAGE_REGISTRY=OFF $cmakeFlags"
cmakeFlags="-DCMAKE_FIND_USE_SYSTEM_PACKAGE_REGISTRY=OFF $cmakeFlags"
prependToVar cmakeFlags "-DCMAKE_EXPORT_NO_PACKAGE_REGISTRY=ON"
prependToVar cmakeFlags "-DCMAKE_FIND_USE_PACKAGE_REGISTRY=OFF"
prependToVar cmakeFlags "-DCMAKE_FIND_USE_SYSTEM_PACKAGE_REGISTRY=OFF"
if [ "${buildPhase-}" = ninjaBuildPhase ]; then
cmakeFlags="-GNinja $cmakeFlags"
prependToVar cmakeFlags "-GNinja"
fi
echo "cmake flags: $cmakeFlags ${cmakeFlagsArray[@]}"
local flagsArray=()
concatTo flagsArray cmakeFlags cmakeFlagsArray
cmake "$cmakeDir" $cmakeFlags "${cmakeFlagsArray[@]}"
echoCmd 'cmake flags' "${flagsArray[@]}"
cmake "$cmakeDir" "${flagsArray[@]}"
if ! [[ -v enableParallelBuilding ]]; then
enableParallelBuilding=1
+1 -1
View File
@@ -488,7 +488,7 @@ let
''${enableParallelBuilding:+-j''${NIX_BUILD_CORES}}
SHELL=$SHELL
)
_accumFlagsArray makeFlags makeFlagsArray buildFlags buildFlagsArray
concatTo flagsArray makeFlags makeFlagsArray buildFlags buildFlagsArray
echoCmd 'build flags' "''${flagsArray[@]}"
make build "''${flagsArray[@]}"
unset flagsArray
+5 -8
View File
@@ -21,11 +21,10 @@ mesonConfigurePhase() {
"--localedir=${!outputLib}/share/locale"
"-Dauto_features=${mesonAutoFeatures:-enabled}"
"-Dwrap_mode=${mesonWrapMode:-nodownload}"
${crossMesonFlags}
"--buildtype=${mesonBuildType:-plain}"
)
_accumFlagsArray mesonFlags mesonFlagsArray
concatTo flagsArray mesonFlags mesonFlagsArray
echoCmd 'mesonConfigurePhase flags' "${flagsArray[@]}"
@@ -50,7 +49,8 @@ mesonConfigurePhase() {
mesonCheckPhase() {
runHook preCheck
local flagsArray=($mesonCheckFlags "${mesonCheckFlagsArray[@]}")
local flagsArray=()
concatTo flagsArray mesonCheckFlags mesonCheckFlagsArray
echoCmd 'mesonCheckPhase flags' "${flagsArray[@]}"
meson test --no-rebuild --print-errorlogs "${flagsArray[@]}"
@@ -64,12 +64,9 @@ mesonInstallPhase() {
local flagsArray=()
if [[ -n "$mesonInstallTags" ]]; then
flagsArray+=("--tags" "${mesonInstallTags// /,}")
flagsArray+=("--tags" "$(concatStringsSep "," mesonInstallTags)")
fi
flagsArray+=(
$mesonInstallFlags
"${mesonInstallFlagsArray[@]}"
)
concatTo flagsArray mesonInstallFlags mesonInstallFlagsArray
echoCmd 'mesonInstallPhase flags' "${flagsArray[@]}"
meson install --no-rebuild "${flagsArray[@]}"
+13 -12
View File
@@ -1,3 +1,5 @@
# shellcheck shell=bash
ninjaBuildPhase() {
runHook preBuild
@@ -9,9 +11,9 @@ ninjaBuildPhase() {
fi
local flagsArray=(
-j$buildCores
$ninjaFlags "${ninjaFlagsArray[@]}"
"-j$buildCores"
)
concatTo flagsArray ninjaFlags ninjaFlagsArray
echoCmd 'build flags' "${flagsArray[@]}"
TERM=dumb ninja "${flagsArray[@]}"
@@ -24,7 +26,7 @@ ninjaCheckPhase() {
if [ -z "${checkTarget:-}" ]; then
if ninja -t query test >/dev/null 2>&1; then
checkTarget=test
checkTarget="test"
fi
fi
@@ -38,10 +40,9 @@ ninjaCheckPhase() {
fi
local flagsArray=(
-j$buildCores
$ninjaFlags "${ninjaFlagsArray[@]}"
$checkTarget
"-j$buildCores"
)
concatTo flagsArray ninjaFlags ninjaFlagsArray checkTarget
echoCmd 'check flags' "${flagsArray[@]}"
TERM=dumb ninja "${flagsArray[@]}"
@@ -62,10 +63,10 @@ ninjaInstallPhase() {
# shellcheck disable=SC2086
local flagsArray=(
-j$buildCores
$ninjaFlags "${ninjaFlagsArray[@]}"
${installTargets:-install}
"-j$buildCores"
)
: "${installTargets:=install}"
concatTo flagsArray ninjaFlags ninjaFlagsArray installTargets
echoCmd 'install flags' "${flagsArray[@]}"
TERM=dumb ninja "${flagsArray[@]}"
@@ -73,14 +74,14 @@ ninjaInstallPhase() {
runHook postInstall
}
if [ -z "${dontUseNinjaBuild-}" -a -z "${buildPhase-}" ]; then
if [ -z "${dontUseNinjaBuild-}" ] && [ -z "${buildPhase-}" ]; then
buildPhase=ninjaBuildPhase
fi
if [ -z "${dontUseNinjaCheck-}" -a -z "${checkPhase-}" ]; then
if [ -z "${dontUseNinjaCheck-}" ] && [ -z "${checkPhase-}" ]; then
checkPhase=ninjaCheckPhase
fi
if [ -z "${dontUseNinjaInstall-}" -a -z "${installPhase-}" ]; then
if [ -z "${dontUseNinjaInstall-}" ] && [ -z "${installPhase-}" ]; then
installPhase=ninjaInstallPhase
fi
+81 -89
View File
@@ -330,16 +330,16 @@ prependToVar() {
fi
# check if variable already exist and if it does then do extra checks
if declare -p "$1" 2> /dev/null | grep -q '^'; then
type="$(declare -p "$1")"
if [[ "$type" =~ "declare -A" ]]; then
echo "prependToVar(): ERROR: trying to use prependToVar on an associative array." >&2
return 1
elif [[ "$type" =~ "declare -a" ]]; then
useArray=true
else
useArray=false
fi
if type=$(declare -p "$1" 2> /dev/null); then
case "${type#* }" in
-A*)
echo "prependToVar(): ERROR: trying to use prependToVar on an associative array." >&2
return 1 ;;
-a*)
useArray=true ;;
*)
useArray=false ;;
esac
fi
shift
@@ -363,16 +363,16 @@ appendToVar() {
fi
# check if variable already exist and if it does then do extra checks
if declare -p "$1" 2> /dev/null | grep -q '^'; then
type="$(declare -p "$1")"
if [[ "$type" =~ "declare -A" ]]; then
echo "appendToVar(): ERROR: trying to use appendToVar on an associative array, use variable+=([\"X\"]=\"Y\") instead." >&2
return 1
elif [[ "$type" =~ "declare -a" ]]; then
useArray=true
else
useArray=false
fi
if type=$(declare -p "$1" 2> /dev/null); then
case "${type#* }" in
-A*)
echo "appendToVar(): ERROR: trying to use appendToVar on an associative array, use variable+=([\"X\"]=\"Y\") instead." >&2
return 1 ;;
-a*)
useArray=true ;;
*)
useArray=false ;;
esac
fi
shift
@@ -384,36 +384,57 @@ appendToVar() {
fi
}
# Accumulate into `flagsArray` the flags from the named variables.
# Accumulate flags from the named variables $2+ into the indexed array $1.
#
# If __structuredAttrs, the variables are all treated as arrays
# and simply concatenated onto `flagsArray`.
#
# If not __structuredAttrs, then:
# * Each variable is treated as a string, and split on whitespace;
# * except variables whose names end in "Array", which are treated
# as arrays.
_accumFlagsArray() {
local name
if [ -n "$__structuredAttrs" ]; then
for name in "$@"; do
# Arrays are simply concatenated, strings are split on whitespace.
concatTo() {
local -n targetref="$1"; shift
local name type
for name in "$@"; do
if type=$(declare -p "$name" 2> /dev/null); then
local -n nameref="$name"
flagsArray+=( ${nameref+"${nameref[@]}"} )
done
else
for name in "$@"; do
local -n nameref="$name"
case "$name" in
*Array)
# shellcheck disable=SC2206
flagsArray+=( ${nameref+"${nameref[@]}"} ) ;;
case "${type#* }" in
-A*)
echo "concatTo(): ERROR: trying to use concatTo on an associative array." >&2
return 1 ;;
-a*)
targetref+=( "${nameref[@]}" ) ;;
*)
# shellcheck disable=SC2206
flagsArray+=( ${nameref-} ) ;;
targetref+=( ${nameref-} ) ;;
esac
done
fi
fi
done
}
# Concatenate a list of strings ($2) with a separator ($1) between each element.
# The list can be an indexed array of strings or a single string. A single string
# is split on spaces and then concatenated with the separator.
#
# $ flags="lorem ipsum dolor sit amet"
# $ concatStringsSep ";" flags
# lorem;ipsum;dolor;sit;amet
#
# $ flags=("lorem ipsum" "dolor" "sit amet")
# $ concatStringsSep ";" flags
# lorem ipsum;dolor;sit amet
concatStringsSep() {
local sep="$1"
local name="$2"
local type oldifs
if type=$(declare -p "$name" 2> /dev/null); then
local -n nameref="$name"
case "${type#* }" in
-A*)
echo "concatStringsSep(): ERROR: trying to use concatStringsSep on an associative array." >&2
return 1 ;;
-a*)
local IFS="$sep"
echo -n "${nameref[*]}" ;;
*)
echo -n "${nameref// /"${sep}"}" ;;
esac
fi
}
# Add $1/lib* into rpaths.
@@ -1220,12 +1241,7 @@ unpackPhase() {
fi
local -a srcsArray
if [ -n "$__structuredAttrs" ]; then
srcsArray=( "${srcs[@]}" )
else
# shellcheck disable=SC2206
srcsArray=( $srcs )
fi
concatTo srcsArray srcs
# To determine the source directory created by unpacking the
# source archives, we record the contents of the current
@@ -1290,13 +1306,7 @@ patchPhase() {
runHook prePatch
local -a patchesArray
if [ -n "$__structuredAttrs" ]; then
# shellcheck disable=SC2206
patchesArray=( ${patches:+"${patches[@]}"} )
else
# shellcheck disable=SC2206
patchesArray=( ${patches:-} )
fi
concatTo patchesArray patches
for i in "${patchesArray[@]}"; do
echo "applying patch $i"
@@ -1317,12 +1327,8 @@ patchPhase() {
esac
local -a flagsArray
if [ -n "$__structuredAttrs" ]; then
flagsArray=( "${patchFlags[@]:--p1}" )
else
# shellcheck disable=SC2086,SC2206
flagsArray=( ${patchFlags:--p1} )
fi
: "${patchFlags:=-p1}"
concatTo flagsArray patchFlags
# "2>&1" is a hack to make patch fail if the decompressor fails (nonexistent patch, etc.)
# shellcheck disable=SC2086
$uncompress < "$i" 2>&1 | patch "${flagsArray[@]}"
@@ -1408,7 +1414,7 @@ configurePhase() {
if [ -n "$configureScript" ]; then
local -a flagsArray
_accumFlagsArray configureFlags configureFlagsArray
concatTo flagsArray configureFlags configureFlagsArray
echoCmd 'configure flags' "${flagsArray[@]}"
# shellcheck disable=SC2086
@@ -1435,7 +1441,7 @@ buildPhase() {
${enableParallelBuilding:+-j${NIX_BUILD_CORES}}
SHELL="$SHELL"
)
_accumFlagsArray makeFlags makeFlagsArray buildFlags buildFlagsArray
concatTo flagsArray makeFlags makeFlagsArray buildFlags buildFlagsArray
echoCmd 'build flags' "${flagsArray[@]}"
make ${makefile:+-f $makefile} "${flagsArray[@]}"
@@ -1474,16 +1480,8 @@ checkPhase() {
SHELL="$SHELL"
)
_accumFlagsArray makeFlags makeFlagsArray
if [ -n "$__structuredAttrs" ]; then
flagsArray+=( "${checkFlags[@]:-VERBOSE=y}" )
else
# shellcheck disable=SC2206
flagsArray+=( ${checkFlags:-VERBOSE=y} )
fi
_accumFlagsArray checkFlagsArray
# shellcheck disable=SC2206
flagsArray+=( ${checkTarget} )
: "${checkFlags:=VERBOSE=y}"
concatTo flagsArray makeFlags makeFlagsArray checkFlags checkFlagsArray checkTarget
echoCmd 'check flags' "${flagsArray[@]}"
make ${makefile:+-f $makefile} "${flagsArray[@]}"
@@ -1516,13 +1514,9 @@ installPhase() {
${enableParallelInstalling:+-j${NIX_BUILD_CORES}}
SHELL="$SHELL"
)
_accumFlagsArray makeFlags makeFlagsArray installFlags installFlagsArray
if [ -n "$__structuredAttrs" ]; then
flagsArray+=( "${installTargets[@]:-install}" )
else
# shellcheck disable=SC2206
flagsArray+=( ${installTargets:-install} )
fi
: "${installTargets:=install}"
concatTo flagsArray makeFlags makeFlagsArray installFlags installFlagsArray installTargets
echoCmd 'install flags' "${flagsArray[@]}"
make ${makefile:+-f $makefile} "${flagsArray[@]}"
@@ -1605,10 +1599,9 @@ installCheckPhase() {
SHELL="$SHELL"
)
_accumFlagsArray makeFlags makeFlagsArray \
installCheckFlags installCheckFlagsArray
# shellcheck disable=SC2206
flagsArray+=( ${installCheckTarget:-installcheck} )
: "${installCheckTarget:=installcheck}"
concatTo flagsArray makeFlags makeFlagsArray \
installCheckFlags installCheckFlagsArray installCheckTarget
echoCmd 'installcheck flags' "${flagsArray[@]}"
make ${makefile:+-f $makefile} "${flagsArray[@]}"
@@ -1623,9 +1616,8 @@ distPhase() {
runHook preDist
local flagsArray=()
_accumFlagsArray distFlags distFlagsArray
# shellcheck disable=SC2206
flagsArray+=( ${distTarget:-dist} )
: "${distTarget:=dist}"
concatTo flagsArray distFlags distFlagsArray distTarget
echo 'dist flags: %q' "${flagsArray[@]}"
make ${makefile:+-f $makefile} "${flagsArray[@]}"
+96 -4
View File
@@ -74,19 +74,19 @@ let
declare -p string
declare -A associativeArray=(["X"]="Y")
[[ $(appendToVar associativeArray "fail" 2>&1) =~ "trying to use" ]] || (echo "prependToVar did not catch prepending associativeArray" && false)
[[ $(prependToVar associativeArray "fail" 2>&1) =~ "trying to use" ]] || (echo "prependToVar did not catch prepending associativeArray" && false)
[[ $(appendToVar associativeArray "fail" 2>&1) =~ "trying to use" ]] || (echo "appendToVar did not throw appending to associativeArray" && false)
[[ $(prependToVar associativeArray "fail" 2>&1) =~ "trying to use" ]] || (echo "prependToVar did not throw prepending associativeArray" && false)
[[ $string == "world testing-string hello" ]] || (echo "'\$string' was not 'world testing-string hello'" && false)
# test appending to a unset variable
appendToVar nonExistant created hello
typeset -p nonExistant
declare -p nonExistant
if [[ -n $__structuredAttrs ]]; then
[[ "''${nonExistant[@]}" == "created hello" ]]
else
# there's a extra " " in front here and a extra " " in the end of prependToVar
# shouldn't matter because these functions will mostly be used for $*Flags and the Flag variable will in most cases already exit
# shouldn't matter because these functions will mostly be used for $*Flags and the Flag variable will in most cases already exist
[[ "$nonExistant" == " created hello" ]]
fi
@@ -96,6 +96,65 @@ let
'';
} // extraAttrs);
testConcatTo = { name, stdenv', extraAttrs ? { } }:
stdenv'.mkDerivation
({
inherit name;
string = "a b";
list = ["c" "d"];
passAsFile = [ "buildCommand" ] ++ lib.optionals (extraAttrs ? extraTest) [ "extraTest" ];
buildCommand = ''
declare -A associativeArray=(["X"]="Y")
[[ $(concatTo nowhere associativeArray 2>&1) =~ "trying to use" ]] || (echo "concatTo did not throw concatenating associativeArray" && false)
declare -a flagsArray
concatTo flagsArray string list
declare -p flagsArray
[[ "''${flagsArray[0]}" == "a" ]] || (echo "'\$flagsArray[0]' was not 'a'" && false)
[[ "''${flagsArray[1]}" == "b" ]] || (echo "'\$flagsArray[1]' was not 'b'" && false)
[[ "''${flagsArray[2]}" == "c" ]] || (echo "'\$flagsArray[2]' was not 'c'" && false)
[[ "''${flagsArray[3]}" == "d" ]] || (echo "'\$flagsArray[3]' was not 'd'" && false)
# test concatenating to unset variable
concatTo nonExistant string list
declare -p nonExistant
[[ "''${nonExistant[0]}" == "a" ]] || (echo "'\$nonExistant[0]' was not 'a'" && false)
[[ "''${nonExistant[1]}" == "b" ]] || (echo "'\$nonExistant[1]' was not 'b'" && false)
[[ "''${nonExistant[2]}" == "c" ]] || (echo "'\$nonExistant[2]' was not 'c'" && false)
[[ "''${nonExistant[3]}" == "d" ]] || (echo "'\$nonExistant[3]' was not 'd'" && false)
eval "$extraTest"
touch $out
'';
} // extraAttrs);
testConcatStringsSep = { name, stdenv' }:
stdenv'.mkDerivation
{
inherit name;
# NOTE: Testing with "&" as separator is intentional, because unquoted
# "&" has a special meaning in the "${var//pattern/replacement}" syntax.
# Cf. https://github.com/NixOS/nixpkgs/pull/318614#discussion_r1706191919
passAsFile = [ "buildCommand" ];
buildCommand = ''
declare -A associativeArray=(["X"]="Y")
[[ $(concatStringsSep ";" associativeArray 2>&1) =~ "trying to use" ]] || (echo "concatStringsSep did not throw concatenating associativeArray" && false)
string="lorem ipsum dolor sit amet"
stringWithSep="$(concatStringsSep "&" string)"
[[ "$stringWithSep" == "lorem&ipsum&dolor&sit&amet" ]] || (echo "'\$stringWithSep' was not 'lorem&ipsum&dolor&sit&amet'" && false)
array=("lorem ipsum" "dolor" "sit amet")
arrayWithSep="$(concatStringsSep "&" array)"
[[ "$arrayWithSep" == "lorem ipsum&dolor&sit amet" ]] || (echo "'\$arrayWithSep' was not 'lorem ipsum&dolor&sit amet'" && false)
touch $out
'';
};
in
{
@@ -196,6 +255,16 @@ in
stdenv' = bootStdenv;
};
test-concat-to = testConcatTo {
name = "test-concat-to";
stdenv' = bootStdenv;
};
test-concat-strings-sep = testConcatStringsSep {
name = "test-concat-strings-sep";
stdenv' = bootStdenv;
};
test-structured-env-attrset = testEnvAttrset {
name = "test-structured-env-attrset";
stdenv' = bootStdenv;
@@ -255,6 +324,29 @@ in
};
};
test-concat-to = testConcatTo {
name = "test-concat-to-structuredAttrsByDefault";
stdenv' = bootStdenvStructuredAttrsByDefault;
extraAttrs = {
# test that whitespace is kept in the bash array for structuredAttrs
listWithSpaces = [ "c c" "d d" ];
extraTest = ''
declare -a flagsWithSpaces
concatTo flagsWithSpaces string listWithSpaces
declare -p flagsWithSpaces
[[ "''${flagsWithSpaces[0]}" == "a" ]] || (echo "'\$flagsWithSpaces[0]' was not 'a'" && false)
[[ "''${flagsWithSpaces[1]}" == "b" ]] || (echo "'\$flagsWithSpaces[1]' was not 'b'" && false)
[[ "''${flagsWithSpaces[2]}" == "c c" ]] || (echo "'\$flagsWithSpaces[2]' was not 'c c'" && false)
[[ "''${flagsWithSpaces[3]}" == "d d" ]] || (echo "'\$flagsWithSpaces[3]' was not 'd d'" && false)
'';
};
};
test-concat-strings-sep = testConcatStringsSep {
name = "test-concat-strings-sep-structuredAttrsByDefault";
stdenv' = bootStdenvStructuredAttrsByDefault;
};
test-golden-example-structuredAttrs =
let
goldenSh = earlyPkgs.writeText "goldenSh" ''