Merge pull request #128503 from talyz/wrapper-prefix-dedup
makeWrapper: Don't duplicate values when prefixing/suffixing, add tests
This commit is contained in:
@@ -36,6 +36,58 @@ makeWrapper() {
|
||||
|
||||
assertExecutable "$original"
|
||||
|
||||
# Write wrapper code which adds `value` to the beginning or end of
|
||||
# the list variable named by `varName`, depending on the `mode`
|
||||
# specified.
|
||||
#
|
||||
# A value which is already part of the list will not be added
|
||||
# again. If this is the case and the `suffix` mode is used, the
|
||||
# list won't be touched at all. The `prefix` mode will however
|
||||
# move the last matching instance of the value to the beginning
|
||||
# of the list. Any remaining duplicates of the value will be left
|
||||
# as-is.
|
||||
addValue() {
|
||||
local mode="$1" # `prefix` or `suffix` to add to the beginning or end respectively
|
||||
local varName="$2" # name of list variable to add to
|
||||
local separator="$3" # character used to separate elements of list
|
||||
local value="$4" # one value, or multiple values separated by `separator`, to add to list
|
||||
if test -n "$value"; then
|
||||
local old_ifs=$IFS
|
||||
IFS=$separator
|
||||
|
||||
if [[ "$mode" == '--prefix'* ]]; then
|
||||
# Keep the order of the components as written when
|
||||
# prefixing; normally, they would be added in the
|
||||
# reverse order.
|
||||
local tmp=
|
||||
for v in $value; do
|
||||
tmp=$v${tmp:+$separator}$tmp
|
||||
done
|
||||
value="$tmp"
|
||||
fi
|
||||
for v in $value; do
|
||||
{
|
||||
echo "$varName=\${$varName:+${separator@Q}\$$varName${separator@Q}}" # add separators on both ends unless empty
|
||||
if [[ "$mode" == '--prefix'* ]]; then # -- in prefix mode --
|
||||
echo "$varName=\${$varName/${separator@Q}${v@Q}${separator@Q}/${separator@Q}}" # remove the first instance of the value (if any)
|
||||
echo "$varName=${v@Q}\$$varName" # prepend the value
|
||||
elif [[ "$mode" == '--suffix'* ]]; then # -- in suffix mode --
|
||||
echo "if [[ \$$varName != *${separator@Q}${v@Q}${separator@Q}* ]]; then" # if the value isn't already in the list
|
||||
echo " $varName=\$$varName${v@Q}" # append the value
|
||||
echo "fi"
|
||||
else
|
||||
echo "unknown mode $mode!" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
echo "$varName=\${$varName#${separator@Q}}" # remove leading separator
|
||||
echo "$varName=\${$varName%${separator@Q}}" # remove trailing separator
|
||||
echo "export $varName"
|
||||
} >> "$wrapper"
|
||||
done
|
||||
IFS=$old_ifs
|
||||
fi
|
||||
}
|
||||
|
||||
mkdir -p "$(dirname "$wrapper")"
|
||||
|
||||
echo "#! @shell@ -e" > "$wrapper"
|
||||
@@ -67,28 +119,14 @@ makeWrapper() {
|
||||
separator="${params[$((n + 2))]}"
|
||||
value="${params[$((n + 3))]}"
|
||||
n=$((n + 3))
|
||||
if test -n "$value"; then
|
||||
if test "$p" = "--suffix"; then
|
||||
echo "export $varName=\$$varName\${$varName:+${separator@Q}}${value@Q}" >> "$wrapper"
|
||||
else
|
||||
echo "export $varName=${value@Q}\${$varName:+${separator@Q}}\$$varName" >> "$wrapper"
|
||||
fi
|
||||
fi
|
||||
elif [[ "$p" == "--prefix-each" ]]; then
|
||||
addValue "$p" "$varName" "$separator" "$value"
|
||||
elif [[ ("$p" == "--suffix-each") || ("$p" == "--prefix-each") ]]; then
|
||||
varName="${params[$((n + 1))]}"
|
||||
separator="${params[$((n + 2))]}"
|
||||
values="${params[$((n + 3))]}"
|
||||
n=$((n + 3))
|
||||
for value in $values; do
|
||||
echo "export $varName=${value@Q}\${$varName:+${separator@Q}}\$$varName" >> "$wrapper"
|
||||
done
|
||||
elif [[ "$p" == "--suffix-each" ]]; then
|
||||
varName="${params[$((n + 1))]}"
|
||||
separator="${params[$((n + 2))]}"
|
||||
values="${params[$((n + 3))]}"
|
||||
n=$((n + 3))
|
||||
for value in $values; do
|
||||
echo "export $varName=\$$varName\${$varName:+$separator}${value@Q}" >> "$wrapper"
|
||||
addValue "$p" "$varName" "$separator" "$value"
|
||||
done
|
||||
elif [[ ("$p" == "--suffix-contents") || ("$p" == "--prefix-contents") ]]; then
|
||||
varName="${params[$((n + 1))]}"
|
||||
@@ -97,11 +135,7 @@ makeWrapper() {
|
||||
n=$((n + 3))
|
||||
for fileName in $fileNames; do
|
||||
contents="$(cat "$fileName")"
|
||||
if test "$p" = "--suffix-contents"; then
|
||||
echo "export $varName=\$$varName\${$varName:+$separator}${contents@Q}" >> "$wrapper"
|
||||
else
|
||||
echo "export $varName=${contents@Q}\${$varName:+$separator}\$$varName" >> "$wrapper"
|
||||
fi
|
||||
addValue "$p" "$varName" "$separator" "$contents"
|
||||
done
|
||||
elif [[ "$p" == "--add-flags" ]]; then
|
||||
flags="${params[$((n + 1))]}"
|
||||
|
||||
@@ -67,4 +67,6 @@ with pkgs;
|
||||
writers = callPackage ../build-support/writers/test.nix {};
|
||||
|
||||
dhall = callPackage ./dhall { };
|
||||
|
||||
makeWrapper = callPackage ./make-wrapper {};
|
||||
}
|
||||
|
||||
@@ -0,0 +1,136 @@
|
||||
{ lib
|
||||
, writeText
|
||||
, writeCBin
|
||||
, writeShellScript
|
||||
, makeWrapper
|
||||
, runCommand
|
||||
, which
|
||||
, ...
|
||||
}:
|
||||
|
||||
let
|
||||
# Testfiles
|
||||
foofile = writeText "foofile" "foo";
|
||||
barfile = writeText "barfile" "bar";
|
||||
|
||||
# Wrapped binaries
|
||||
wrappedArgv0 = writeCBin "wrapped-argv0" ''
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
void main(int argc, char** argv) {
|
||||
printf("argv0=%s", argv[0]);
|
||||
exit(0);
|
||||
}
|
||||
'';
|
||||
wrappedBinaryVar = writeShellScript "wrapped-var" ''
|
||||
echo "VAR=$VAR"
|
||||
'';
|
||||
wrappedBinaryArgs = writeShellScript "wrapped-args" ''
|
||||
echo "$@"
|
||||
'';
|
||||
|
||||
mkWrapperBinary = { name, args, wrapped ? wrappedBinaryVar }: runCommand name
|
||||
{
|
||||
nativeBuildInputs = [ makeWrapper ];
|
||||
} ''
|
||||
mkdir -p $out/bin
|
||||
makeWrapper "${wrapped}" "$out/bin/${name}" ${lib.escapeShellArgs args}
|
||||
'';
|
||||
|
||||
mkTest = cmd: toExpect: ''
|
||||
output="$(${cmd})"
|
||||
if [[ "$output" != '${toExpect}' ]]; then
|
||||
echo "test failed: the output of ${cmd} was '$output', expected '${toExpect}'"
|
||||
echo "the wrapper contents:"
|
||||
for i in ${cmd}; do
|
||||
if [[ $i =~ ^test- ]]; then
|
||||
cat $(which $i)
|
||||
fi
|
||||
done
|
||||
exit 1
|
||||
fi
|
||||
'';
|
||||
in
|
||||
runCommand "make-wrapper-test"
|
||||
{
|
||||
nativeBuildInputs = [
|
||||
which
|
||||
(mkWrapperBinary { name = "test-argv0"; args = [ "--argv0" "foo" ]; wrapped = "${wrappedArgv0}/bin/wrapped-argv0"; })
|
||||
(mkWrapperBinary { name = "test-set"; args = [ "--set" "VAR" "abc" ]; })
|
||||
(mkWrapperBinary { name = "test-set-default"; args = [ "--set-default" "VAR" "abc" ]; })
|
||||
(mkWrapperBinary { name = "test-unset"; args = [ "--unset" "VAR" ]; })
|
||||
(mkWrapperBinary { name = "test-run"; args = [ "--run" "echo bar" ]; })
|
||||
(mkWrapperBinary { name = "test-run-and-set"; args = [ "--run" "export VAR=foo" "--set" "VAR" "bar" ]; })
|
||||
(mkWrapperBinary { name = "test-args"; args = [ "--add-flags" "abc" ]; wrapped = wrappedBinaryArgs; })
|
||||
(mkWrapperBinary { name = "test-prefix"; args = [ "--prefix" "VAR" ":" "abc" ]; })
|
||||
(mkWrapperBinary { name = "test-suffix"; args = [ "--suffix" "VAR" ":" "abc" ]; })
|
||||
(mkWrapperBinary { name = "test-prefix-and-suffix"; args = [ "--prefix" "VAR" ":" "foo" "--suffix" "VAR" ":" "bar" ]; })
|
||||
(mkWrapperBinary { name = "test-prefix-multi"; args = [ "--prefix" "VAR" ":" "abc:foo:foo" ]; })
|
||||
(mkWrapperBinary { name = "test-suffix-each"; args = [ "--suffix-each" "VAR" ":" "foo bar:def" ]; })
|
||||
(mkWrapperBinary { name = "test-prefix-each"; args = [ "--prefix-each" "VAR" ":" "foo bar:def" ]; })
|
||||
(mkWrapperBinary { name = "test-suffix-contents"; args = [ "--suffix-contents" "VAR" ":" "${foofile} ${barfile}" ]; })
|
||||
(mkWrapperBinary { name = "test-prefix-contents"; args = [ "--prefix-contents" "VAR" ":" "${foofile} ${barfile}" ]; })
|
||||
];
|
||||
}
|
||||
(
|
||||
# --argv0 works
|
||||
mkTest "test-argv0" "argv0=foo"
|
||||
|
||||
# --set works
|
||||
+ mkTest "test-set" "VAR=abc"
|
||||
# --set overwrites the variable
|
||||
+ mkTest "VAR=foo test-set" "VAR=abc"
|
||||
# --set-default works
|
||||
+ mkTest "test-set-default" "VAR=abc"
|
||||
# --set-default doesn"t overwrite the variable
|
||||
+ mkTest "VAR=foo test-set-default" "VAR=foo"
|
||||
# --unset works
|
||||
+ mkTest "VAR=foo test-unset" "VAR="
|
||||
|
||||
# --add-flags works
|
||||
+ mkTest "test-args" "abc"
|
||||
# given flags are appended
|
||||
+ mkTest "test-args foo" "abc foo"
|
||||
|
||||
# --run works
|
||||
+ mkTest "test-run" "bar\nVAR="
|
||||
# --run & --set works
|
||||
+ mkTest "test-run-and-set" "VAR=bar"
|
||||
|
||||
# --prefix works
|
||||
+ mkTest "VAR=foo test-prefix" "VAR=abc:foo"
|
||||
# sets variable if not set yet
|
||||
+ mkTest "test-prefix" "VAR=abc"
|
||||
# prepends value only once
|
||||
+ mkTest "VAR=abc test-prefix" "VAR=abc"
|
||||
# Moves value to the front if it already existed
|
||||
+ mkTest "VAR=foo:abc test-prefix" "VAR=abc:foo"
|
||||
+ mkTest "VAR=abc:foo:bar test-prefix-multi" "VAR=abc:foo:bar"
|
||||
# Doesn't overwrite parts of the string
|
||||
+ mkTest "VAR=test:abcde:test test-prefix" "VAR=abc:test:abcde:test"
|
||||
# Only append the value once when given multiple times in a parameter
|
||||
# to makeWrapper
|
||||
+ mkTest "test-prefix" "VAR=abc"
|
||||
|
||||
|
||||
# --suffix works
|
||||
+ mkTest "VAR=foo test-suffix" "VAR=foo:abc"
|
||||
# sets variable if not set yet
|
||||
+ mkTest "test-suffix" "VAR=abc"
|
||||
# adds the same value only once
|
||||
+ mkTest "VAR=abc test-suffix" "VAR=abc"
|
||||
+ mkTest "VAR=abc:foo test-suffix" "VAR=abc:foo"
|
||||
# --prefix in combination with --suffix
|
||||
+ mkTest "VAR=abc test-prefix-and-suffix" "VAR=foo:abc:bar"
|
||||
|
||||
# --suffix-each works
|
||||
+ mkTest "VAR=abc test-suffix-each" "VAR=abc:foo:bar:def"
|
||||
# --prefix-each works
|
||||
+ mkTest "VAR=abc test-prefix-each" "VAR=bar:def:foo:abc"
|
||||
# --suffix-contents works
|
||||
+ mkTest "VAR=abc test-suffix-contents" "VAR=abc:foo:bar"
|
||||
# --prefix-contents works
|
||||
+ mkTest "VAR=abc test-prefix-contents" "VAR=bar:foo:abc"
|
||||
+ "touch $out"
|
||||
)
|
||||
@@ -715,8 +715,14 @@ with pkgs;
|
||||
|
||||
makeInitrd = callPackage ../build-support/kernel/make-initrd.nix; # Args intentionally left out
|
||||
|
||||
makeWrapper = makeSetupHook { deps = [ dieHook ]; substitutions = { shell = targetPackages.runtimeShell; }; }
|
||||
../build-support/setup-hooks/make-wrapper.sh;
|
||||
makeWrapper = makeSetupHook
|
||||
{ deps = [ dieHook ];
|
||||
substitutions = {
|
||||
shell = targetPackages.runtimeShell;
|
||||
passthru.tests = tests.makeWrapper;
|
||||
};
|
||||
}
|
||||
../build-support/setup-hooks/make-wrapper.sh;
|
||||
|
||||
makeBinaryWrapper = let
|
||||
f = { cc, sanitizers }: let
|
||||
|
||||
Reference in New Issue
Block a user