From da31bd56732b2b954c867b0283df66539b3764c0 Mon Sep 17 00:00:00 2001 From: Shamrock Lee <44064051+ShamrockLee@users.noreply.github.com> Date: Wed, 3 Aug 2022 09:02:55 +0800 Subject: [PATCH] patchRcPathBash, patchRcPathCsh, patchRcPathFish, patchRcPathPosix: init Init patchRcPath hooks, which provides utilities to patch shell scripts to be sourced by users. Add test cases and documentation. --- doc/hooks/index.xml | 1 + doc/hooks/patch-rc-path-hooks.section.md | 50 ++ .../patch-rc-path-hooks/default.nix | 64 +++ .../patch-rc-path-hooks/patch-rc-path-bash.sh | 50 ++ .../patch-rc-path-hooks/patch-rc-path-csh.sh | 57 +++ .../patch-rc-path-hooks/patch-rc-path-fish.sh | 50 ++ .../patch-rc-path-posix.sh | 39 ++ .../patch-rc-path-hooks/test/default.nix | 442 ++++++++++++++++++ .../test/sample_source.bash | 2 + .../test/sample_source.csh.in | 1 + .../test/sample_source.fish | 9 + .../test/sample_source.sh.in | 2 + .../test/test-sourcing-bash | 21 + .../test/test-sourcing-csh | 13 + .../test/test-sourcing-fish | 13 + .../test/test-sourcing-posix | 21 + pkgs/top-level/all-packages.nix | 4 + 17 files changed, 839 insertions(+) create mode 100644 doc/hooks/patch-rc-path-hooks.section.md create mode 100644 pkgs/build-support/setup-hooks/patch-rc-path-hooks/default.nix create mode 100644 pkgs/build-support/setup-hooks/patch-rc-path-hooks/patch-rc-path-bash.sh create mode 100644 pkgs/build-support/setup-hooks/patch-rc-path-hooks/patch-rc-path-csh.sh create mode 100644 pkgs/build-support/setup-hooks/patch-rc-path-hooks/patch-rc-path-fish.sh create mode 100644 pkgs/build-support/setup-hooks/patch-rc-path-hooks/patch-rc-path-posix.sh create mode 100644 pkgs/build-support/setup-hooks/patch-rc-path-hooks/test/default.nix create mode 100644 pkgs/build-support/setup-hooks/patch-rc-path-hooks/test/sample_source.bash create mode 100644 pkgs/build-support/setup-hooks/patch-rc-path-hooks/test/sample_source.csh.in create mode 100644 pkgs/build-support/setup-hooks/patch-rc-path-hooks/test/sample_source.fish create mode 100644 pkgs/build-support/setup-hooks/patch-rc-path-hooks/test/sample_source.sh.in create mode 100644 pkgs/build-support/setup-hooks/patch-rc-path-hooks/test/test-sourcing-bash create mode 100644 pkgs/build-support/setup-hooks/patch-rc-path-hooks/test/test-sourcing-csh create mode 100644 pkgs/build-support/setup-hooks/patch-rc-path-hooks/test/test-sourcing-fish create mode 100644 pkgs/build-support/setup-hooks/patch-rc-path-hooks/test/test-sourcing-posix diff --git a/doc/hooks/index.xml b/doc/hooks/index.xml index ed703c03d8b0..0917fac6c0ac 100644 --- a/doc/hooks/index.xml +++ b/doc/hooks/index.xml @@ -22,6 +22,7 @@ + diff --git a/doc/hooks/patch-rc-path-hooks.section.md b/doc/hooks/patch-rc-path-hooks.section.md new file mode 100644 index 000000000000..5c870dc782c2 --- /dev/null +++ b/doc/hooks/patch-rc-path-hooks.section.md @@ -0,0 +1,50 @@ + +# `patchRcPath` hooks {#sec-patchRcPathHooks} + +These hooks provide shell-specific utilities (with the same name as the hook) to patch shell scripts meant to be sourced by software users. + +The typical usage is to patch initialisation or [rc](https://unix.stackexchange.com/questions/3467/what-does-rc-in-bashrc-stand-for) scripts inside `$out/bin` or `$out/etc`. +Such scripts, when being sourced, would insert the binary locations of certain commands into `PATH`, modify other environment variables or run a series of start-up commands. +When shipped from the upstream, they sometimes use commands that might not be available in the environment they are getting sourced in. + +The compatible shells for each hook are: + + - `patchRcPathBash`: [Bash](https://www.gnu.org/software/bash/), [ksh](http://www.kornshell.org/), [zsh](https://www.zsh.org/) and other shells supporting the Bash-like parameter expansions. + - `patchRcPathCsh`: Csh scripts, such as those targeting [tcsh](https://www.tcsh.org/). + - `patchRcPathFish`: [Fish](https://fishshell.com/) scripts. + - `patchRcPathPosix`: POSIX-conformant shells supporting the limited parameter expansions specified by the POSIX standard. Current implementation uses the parameter expansion `${foo-}` only. + +For each supported shell, it modifies the script with a `PATH` prefix that is later removed when the script ends. +It allows nested patching, which guarantees that a patched script may source another patched script. + +Syntax to apply the utility to a script: + +```sh +patchRcPath +``` + +Example usage: + +Given a package `foo` containing an init script `this-foo.fish` that depends on `coreutils`, `man` and `which`, +patch the init script for users to source without having the above dependencies in their `PATH`: + +```nix +{ lib, stdenv, patchRcPathFish}: +stdenv.mkDerivation { + + # ... + + nativeBuildInputs = [ + patchRcPathFish + ]; + + postFixup = '' + patchRcPathFish $out/bin/this-foo.fish ${lib.makeBinPath [ coreutils man which ]} + ''; +} +``` + +::: {.note} +`patchRcPathCsh` and `patchRcPathPosix` implementation depends on `sed` to do the string processing. +The others are in vanilla shell and have no third-party dependencies. +::: diff --git a/pkgs/build-support/setup-hooks/patch-rc-path-hooks/default.nix b/pkgs/build-support/setup-hooks/patch-rc-path-hooks/default.nix new file mode 100644 index 000000000000..73fbfa6e9b72 --- /dev/null +++ b/pkgs/build-support/setup-hooks/patch-rc-path-hooks/default.nix @@ -0,0 +1,64 @@ +{ lib +, callPackage +, makeSetupHook +, gnused +}: +let + tests = import ./test { inherit callPackage; }; +in +{ + patchRcPathBash = (makeSetupHook + { + name = "patch-rc-path-bash"; + meta = with lib; { + description = "Setup-hook to inject source-time PATH prefix to a Bash/Ksh/Zsh script"; + maintainers = with maintainers; [ ShamrockLee ]; + }; + } ./patch-rc-path-bash.sh).overrideAttrs (oldAttrs: { + passthru.tests = { + inherit (tests) test-bash; + }; + }); + patchRcPathCsh = (makeSetupHook + { + name = "patch-rc-path-csh"; + substitutions = { + sed = "${gnused}/bin/sed"; + }; + meta = with lib; { + description = "Setup-hook to inject source-time PATH prefix to a Csh script"; + maintainers = with maintainers; [ ShamrockLee ]; + }; + } ./patch-rc-path-csh.sh).overrideAttrs (oldAttrs: { + passthru.tests = { + inherit (tests) test-csh; + }; + }); + patchRcPathFish = (makeSetupHook + { + name = "patch-rc-path-fish"; + meta = with lib; { + description = "Setup-hook to inject source-time PATH prefix to a Fish script"; + maintainers = with maintainers; [ ShamrockLee ]; + }; + } ./patch-rc-path-fish.sh).overrideAttrs (oldAttrs: { + passthru.tests = { + inherit (tests) test-fish; + }; + }); + patchRcPathPosix = (makeSetupHook + { + name = "patch-rc-path-posix"; + substitutions = { + sed = "${gnused}/bin/sed"; + }; + meta = with lib; { + description = "Setup-hook to inject source-time PATH prefix to a POSIX shell script"; + maintainers = with maintainers; [ ShamrockLee ]; + }; + } ./patch-rc-path-posix.sh).overrideAttrs (oldAttrs: { + passthru.tests = { + inherit (tests) test-posix; + }; + }); +} diff --git a/pkgs/build-support/setup-hooks/patch-rc-path-hooks/patch-rc-path-bash.sh b/pkgs/build-support/setup-hooks/patch-rc-path-hooks/patch-rc-path-bash.sh new file mode 100644 index 000000000000..b98b983861b0 --- /dev/null +++ b/pkgs/build-support/setup-hooks/patch-rc-path-hooks/patch-rc-path-bash.sh @@ -0,0 +1,50 @@ +patchRcPathBash(){ + local FILE_TO_PATCH="$1" + local SOURCETIME_PATH="$2" + local FILE_TO_WORK_ON="$(mktemp "$(basename "$FILE_TO_PATCH").XXXXXX.tmp")" + cat <> "$FILE_TO_WORK_ON" +# Lines to add to PATH the source-time utilities for Nixpkgs packaging +if [[ -n "\${NIXPKGS_SOURCETIME_PATH-}" ]]; then + NIXPKGS_SOURCETIME_PATH_OLD="\$NIXPKGS_SOURCETIME_PATH;\${NIXPKGS_SOURCETIME_PATH_OLD-}" +fi +NIXPKGS_SOURCETIME_PATH="$SOURCETIME_PATH" +if [[ -n "\$PATH" ]]; then + PATH="\$NIXPKGS_SOURCETIME_PATH:\$PATH" +else + PATH="\$NIXPKGS_SOURCETIME_PATH" +fi +export PATH +# End of lines to add to PATH source-time utilities for Nixpkgs packaging +EOF + cat "$FILE_TO_PATCH" >> "$FILE_TO_WORK_ON" + cat <> "$FILE_TO_WORK_ON" +# Lines to clean up inside PATH the source-time utilities for Nixpkgs packaging +if [[ -n "\${PATH-}" ]]; then + # Remove the inserted section + PATH="\${PATH/\$NIXPKGS_SOURCETIME_PATH}" + # Remove the duplicated colons + PATH="\${PATH//::/:}" + # Remove the prefixing colon + if [[ -n "\$PATH" && "\${PATH:0:1}" == ":" ]]; then + PATH="\${PATH:1}" + fi + # Remove the trailing colon + if [[ -n "\$PATH" && "\${PATH:\${#PATH}-1}" == ":" ]]; then + PATH="\${PATH::}" + fi + export PATH +fi +if [[ -n "\${NIXPKGS_SOURCETIME_PATH_OLD-}" ]]; then + IFS="" read -r -d ";" NIXPKGS_SOURCETIME_PATH <<< "\$NIXPKGS_SOURCETIME_PATH_OLD" + NIXPKGS_SOURCETIME_PATH_OLD="\${NIXPKGS_SOURCETIME_PATH_OLD:\${#NIXPKGS_SOURCETIME_PATH}+1}" +else + unset NIXPKGS_SOURCETIME_PATH +fi +if [[ -z "\${NIXPKGS_SOURCETIME_PATH_OLD-}" ]]; then + unset NIXPKGS_SOURCETIME_PATH_OLD +fi +# End of lines to clean up inside PATH the source-time utilities for Nixpkgs packaging +EOF + cat "$FILE_TO_WORK_ON" > "$FILE_TO_PATCH" + rm "$FILE_TO_WORK_ON" +} diff --git a/pkgs/build-support/setup-hooks/patch-rc-path-hooks/patch-rc-path-csh.sh b/pkgs/build-support/setup-hooks/patch-rc-path-hooks/patch-rc-path-csh.sh new file mode 100644 index 000000000000..5e2367003ade --- /dev/null +++ b/pkgs/build-support/setup-hooks/patch-rc-path-hooks/patch-rc-path-csh.sh @@ -0,0 +1,57 @@ +patchRcPathCsh(){ + local FILE_TO_PATCH="$1" + local SOURCETIME_PATH="$2" + local FILE_TO_WORK_ON="$(mktemp "$(basename "$FILE_TO_PATCH").XXXXXX.tmp")" + cat <> "$FILE_TO_WORK_ON" +# Lines to add to PATH the source-time utilities for Nixpkgs packaging +if (\$?NIXPKGS_SOURCETIME_PATH) then + if ("\$NIXPKGS_SOURCETIME_PATH" != "") then + if (\$?NIXPKGS_SOURCETIME_PATH_OLD) then + if ("\$NIXPKGS_SOURCETIME_PATH_OLD" != "") + set NIXPKGS_SOURCETIME_PATH_OLD = (\$NIXPKGS_SOURCETIME_PATH \$NIXPKGS_SOURCETIME_PATH_OLD) + else + set NIXPKGS_SOURCETIME_PATH_OLD = \$NIXPKGS_SOURCETIME_PATH + endif + else + set NIXPKGS_SOURCETIME_PATH_OLD = \$NIXPKGS_SOURCETIME_PATH + endif + endif +endif +set NIXPKGS_SOURCETIME_PATH = "$SOURCETIME_PATH" +if (! \$?PATH) then + setenv PATH "" +endif +if ("\$PATH" != "") then + setenv PATH "\${NIXPKGS_SOURCETIME_PATH}:\$PATH" +else + setenv PATH "\$NIXPKGS_SOURCETIME_PATH" +endif +# End of lines to add to PATH source-time utilities for Nixpkgs packaging +EOF + cat "$FILE_TO_PATCH" >> "$FILE_TO_WORK_ON" + cat <> "$FILE_TO_WORK_ON" +# Lines to clean up inside PATH the source-time utilities for Nixpkgs packaging +if (\$?PATH) then + if ("\$PATH" != "") then + # Remove the inserted section, the duplicated colons, and the leading and trailing colon + setenv PATH \`echo "\$PATH" | @sed@ "s#\${NIXPKGS_SOURCETIME_PATH}##" | @sed@ "s#::#:#g" | @sed@ "s#^:##" | @sed@ 's#:\$##'\` + endif +endif +if (\$?NIXPKGS_SOURCETIME_PATH_OLD) then + if ("\$NIXPKGS_SOURCETIME_PATH_OLD" != "") then + set NIXPKGS_SOURCETIME_PATH = \$NIXPKGS_SOURCETIME_PATH_OLD[1] + set NIXPKGS_SOURCETIME_PATH_OLD = \$NIXPKGS_SOURCETIME_PATH_OLD[2-] + else + unset NIXPKGS_SOURCETIME_PATH + endif + if (NIXPKGS_SOURCETIME_PATH_OLD == "") then + unset NIXPKGS_SOURCETIME_PATH_OLD + endif +else + unset NIXPKGS_SOURCETIME_PATH +endif +# End of lines to clean up inside PATH the source-time utilities for Nixpkgs packaging +EOF + cat "$FILE_TO_WORK_ON" > "$FILE_TO_PATCH" + rm "$FILE_TO_WORK_ON" +} diff --git a/pkgs/build-support/setup-hooks/patch-rc-path-hooks/patch-rc-path-fish.sh b/pkgs/build-support/setup-hooks/patch-rc-path-hooks/patch-rc-path-fish.sh new file mode 100644 index 000000000000..3d3e08c57a11 --- /dev/null +++ b/pkgs/build-support/setup-hooks/patch-rc-path-hooks/patch-rc-path-fish.sh @@ -0,0 +1,50 @@ +patchRcPathFish(){ + local FILE_TO_PATCH="$1" + local SOURCETIME_PATH="$2" + local FILE_TO_WORK_ON="$(mktemp "$(basename "$FILE_TO_PATCH").XXXXXX.tmp")" + cat <> "$FILE_TO_WORK_ON" +# Lines to add to PATH the source-time utilities for Nixpkgs packaging +if set -q NIXPKGS_SOURCETIME_PATH && test (count \$NIXPKGS_SOURCETIME_PATH) -gt 0 + set --unpath NIXPKGS_SOURCETIME_PATH_OLD "\$NIXPKGS_SOURCETIME_PATH" \$NIXPKGS_SOURCETIME_PATH_OLD +end +set --path NIXPKGS_SOURCETIME_PATH $SOURCETIME_PATH +set -g --path PATH \$NIXPKGS_SOURCETIME_PATH \$PATH +# End of lines to add to PATH source-time utilities for Nixpkgs packaging +EOF + cat "$FILE_TO_PATCH" >> "$FILE_TO_WORK_ON" + cat <> "$FILE_TO_WORK_ON" +# Lines to clean up inside PATH the source-time utilities for Nixpkgs packaging +if set -q PATH && test "\$PATH" != "" && test (count \$PATH) -ge (count \$NIXPKGS_SOURCETIME_PATH) + # Remove the inserted section + for i in (seq 0 (math (count \$PATH) - (count \$NIXPKGS_SOURCETIME_PATH))) + for j in (seq 1 (count \$NIXPKGS_SOURCETIME_PATH)) + if test \$PATH[(math \$i + \$j)] != \$NIXPKGS_SOURCETIME_PATH[\$j] + set i -1 + break + end + end + if test \$i -eq -1 + continue + end + if test \$i -eq 0 + set -g --path PATH \$PATH[(math (count \$NIXPKGS_SOURCETIME_PATH) + 1)..] + else + set -g --path PATH \$PATH[..\$i] \$PATH[(math (count \$NIXPKGS_SOURCETIME_PATH) + 1 + \$i)..] + end + break + end +end +if set -q NIXPKGS_SOURCETIME_PATH_OLD && test (count \$NIXPKGS_SOURCETIME_PATH_OLD) -gt 0 + set --path NIXPKGS_SOURCETIME_PATH \$NIXPKGS_SOURCETIME_PATH_OLD[1] + set --unpath NIXPKGS_SOURCETIME_PATH_OLD \$NIXPKGS_SOURCETIME_PATH_OLD[2..] +else + set -e NIXPKGS_SOURCETIME_PATH +end +if set -q NIXPKGS_SOURCETIME_PATH_OLD && test (count \$NIXPKGS_SOURCETIME_PATH_OLD) -eq 0 + set -e NIXPKGS_SOURCETIME_PATH_OLD +end +# End of lines to clean up inside PATH the source-time utilities for Nixpkgs packaging +EOF + cat "$FILE_TO_WORK_ON" > "$FILE_TO_PATCH" + rm "$FILE_TO_WORK_ON" +} diff --git a/pkgs/build-support/setup-hooks/patch-rc-path-hooks/patch-rc-path-posix.sh b/pkgs/build-support/setup-hooks/patch-rc-path-hooks/patch-rc-path-posix.sh new file mode 100644 index 000000000000..a3740d4436d9 --- /dev/null +++ b/pkgs/build-support/setup-hooks/patch-rc-path-hooks/patch-rc-path-posix.sh @@ -0,0 +1,39 @@ +patchRcPathPosix(){ + local FILE_TO_PATCH="$1" + local SOURCETIME_PATH="$2" + local FILE_TO_WORK_ON="$(mktemp "$(basename "$FILE_TO_PATCH").XXXXXX.tmp")" + cat <> "$FILE_TO_WORK_ON" +# Lines to add to PATH the source-time utilities for Nixpkgs packaging +if [ -n "\${NIXPKGS_SOURCETIME_PATH-}" ]; then + NIXPKGS_SOURCETIME_PATH_OLD="\$NIXPKGS_SOURCETIME_PATH;\${NIXPKGS_SOURCETIME_PATH_OLD-}" +fi +NIXPKGS_SOURCETIME_PATH="$SOURCETIME_PATH" +if [ -n "\$PATH" ]; then + PATH="\$NIXPKGS_SOURCETIME_PATH:\$PATH"; +else + PATH="\$NIXPKGS_SOURCETIME_PATH" +fi +export PATH +# End of lines to add to PATH source-time utilities for Nixpkgs packaging +EOF + cat "$FILE_TO_PATCH" >> "$FILE_TO_WORK_ON" + cat <> "$FILE_TO_WORK_ON" +# Lines to clean up inside PATH the source-time utilities for Nixpkgs packaging +if [ -n "\${PATH-}" ]; then + PATH="\$(echo "\$PATH" | @sed@ "s#\$NIXPKGS_SOURCETIME_PATH##" | @sed@ "s#::#:#g" | @sed@ "s#^:##" | @sed@ "s#:\\\$##")" + export PATH +fi +if [ -n "\${NIXPKGS_SOURCETIME_PATH_OLD-}" ]; then + NIXPKGS_SOURCETIME_PATH="\$(echo "\$NIXPKGS_SOURCETIME_PATH_OLD" | @sed@ "s#\\([^;]\\);.*#\\1#")" + NIXPKGS_SOURCETIME_PATH_OLD="\$(echo "\$NIXPKGS_SOURCETIME_PATH_OLD" | @sed@ "s#[^;];\\(.*\\)#\\1#")" +else + unset NIXPKGS_SOURCETIME_PATH +fi +if [ -z "\${NIXPKGS_SOURCETIME_PATH_OLD-}" ]; then + unset NIXPKGS_SOURCETIME_PATH_OLD +fi +# End of lines to clean up inside PATH the source-time utilities for Nixpkgs packaging +EOF + cat "$FILE_TO_WORK_ON" > "$FILE_TO_PATCH" + rm "$FILE_TO_WORK_ON" +} diff --git a/pkgs/build-support/setup-hooks/patch-rc-path-hooks/test/default.nix b/pkgs/build-support/setup-hooks/patch-rc-path-hooks/test/default.nix new file mode 100644 index 000000000000..82bc160387ee --- /dev/null +++ b/pkgs/build-support/setup-hooks/patch-rc-path-hooks/test/default.nix @@ -0,0 +1,442 @@ +{ callPackage }: + +{ + test-bash = callPackage + ( + { lib + , runCommandLocal + , bash + , hello + , ksh + , patchRcPathBash + , shellcheck + , zsh + }: + runCommandLocal "patch-rc-path-bash-test" + { + nativeBuildInputs = [ + bash + ksh + patchRcPathBash + shellcheck + zsh + ]; + meta = { + description = "Package test of patchActivateBash"; + inherit (patchRcPathBash.meta) maintainers; + }; + } + '' + set -eu -o pipefail + + + # Check the setup hook script + + echo "Running shellcheck against ${./test-sourcing-bash}" + shellcheck -s bash --exclude SC1090 ${./test-sourcing-bash} + shellcheck -s ksh --exclude SC1090 ${./test-sourcing-bash} + + + # Test patching a blank file + + echo > blank.bash + + echo "Generating blank_patched.bash from blank.bash" + cp blank.bash blank_patched.bash + patchRcPathBash blank_patched.bash "$PWD/delta:$PWD/foxtrot" + + echo "Running shellcheck against blank_patched.bash" + shellcheck -s bash blank_patched.bash + shellcheck -s ksh blank_patched.bash + + echo "Testing in Bash if blank.bash and blank_patched.bash modifies PATH the same way" + bash ${./test-sourcing-bash} ./blank.bash ./blank_patched.bash + + echo "Testing in Ksh if blank.bash and blank_patched.bash modifies PATH the same way" + ksh ${./test-sourcing-bash} "$PWD/blank.bash" "$PWD/blank_patched.bash" + + echo "Testing in Zsh if blank.bash and blank_patched.bash modifies PATH the same way" + zsh ${./test-sourcing-bash} ./blank.bash ./blank_patched.bash + + + # Test patching silent_hello + + echo "hello > /dev/null" > silent_hello.bash + + echo "Generating silent_hello_patched.bash from silent_hello.bash" + cp silent_hello.bash silent_hello_patched.bash + patchRcPathBash silent_hello_patched.bash "${hello}/bin" + + echo "Running shellcheck against silent_hello_patched.bash" + shellcheck -s bash silent_hello_patched.bash + + echo "Testing in Bash if silent_hello_patched.bash get sourced without error" + bash -eu -o pipefail -c ". ./silent_hello_patched.bash" + + echo "Testing in Ksh if silent_hello_patched.bash get sourced without error" + ksh -eu -o pipefail -c ". ./silent_hello_patched.bash" + + echo "Testing in Zsh if silent_hello_patched.bash get sourced without error" + zsh -eu -o pipefail -c ". ./silent_hello_patched.bash" + + + # Check the sample source + + echo "Running shellcheck against sample_source.bash" + shellcheck -s bash ${./sample_source.bash} + shellcheck -s ksh ${./sample_source.bash} + + + # Test patching the sample source + + cp ${./sample_source.bash} sample_source_patched.bash + chmod u+w sample_source_patched.bash + + echo "Generating sample_source_patched.bash from ./sample_source.bash" + patchRcPathBash sample_source_patched.bash "$PWD/delta:$PWD/foxtrot" + + echo "Running shellcheck against sample_source_patched.bash" + shellcheck -s bash sample_source_patched.bash + + echo "Testing in Bash if sample_source.bash and sample_source_patched.bash modifies PATH the same way" + bash ${./test-sourcing-bash} ${./sample_source.bash} ./sample_source_patched.bash + + echo "Testing in Ksh if sample_source.bash and sample_source_patched.bash modifies PATH the same way" + ksh ${./test-sourcing-bash} ${./sample_source.bash} "$PWD/sample_source_patched.bash" + + echo "Testing in Zsh if sample_source.bash and sample_source_patched.bash modifies PATH the same way" + zsh ${./test-sourcing-bash} ${./sample_source.bash} ./sample_source_patched.bash + + + # Test double-patching the sample source + + echo "Patching again sample_source_patched.bash" + patchRcPathBash sample_source_patched.bash "$PWD/foxtrot:$PWD/golf" + + echo "Running shellcheck against sample_source_patched.bash" + shellcheck -s bash sample_source_patched.bash + shellcheck -s ksh sample_source_patched.bash + + echo "Testing in Bash if sample_source.bash and sample_source_patched.bash modifies PATH the same way" + bash ${./test-sourcing-bash} ${./sample_source.bash} ./sample_source_patched.bash + + echo "Testing in Ksh if sample_source.bash and sample_source_patched.bash modifies PATH the same way" + ksh ${./test-sourcing-bash} ${./sample_source.bash} "$PWD/sample_source_patched.bash" + + echo "Testing in Zsh if sample_source.bash and sample_source_patched.bash modifies PATH the same way" + zsh ${./test-sourcing-bash} ${./sample_source.bash} ./sample_source_patched.bash + + + # Create a dummy output + touch "$out" + '' + ) + { }; + + + + test-csh = callPackage + ( + { lib + , runCommandLocal + , gnused + , hello + , patchRcPathCsh + , tcsh + }: + runCommandLocal "patch-rc-path-csh-test" + { + nativeBuildInputs = [ + patchRcPathCsh + tcsh + ]; + meta = { + description = "Package test of patchActivateCsh"; + inherit (patchRcPathCsh.meta) maintainers; + }; + } + '' + set -eu -o pipefail + + + # Test patching a blank file + + echo > blank.csh + + echo "Generating blank_patched.csh from blank.csh" + cp blank.csh blank_patched.csh + patchRcPathCsh blank_patched.csh "$PWD/delta:$PWD/foxtrot" + + echo "Testing in Csh if blank.csh and blank_patched.csh modifies PATH the same way" + tcsh -e ${./test-sourcing-csh} blank.csh blank_patched.csh + + + # Test patching silent_hello file + + echo "hello > /dev/null" > silent_hello.csh + + echo "Generating silent_hello_patched.csh from silent_hello.csh" + cp silent_hello.csh silent_hello_patched.csh + patchRcPathCsh silent_hello_patched.csh "${hello}/bin" + + echo "Testing in Csh if silent_hello_patched.csh get sourced without errer" + tcsh -e -c "source silent_hello_patched.csh" + + + # Generate the sample source + + substitute ${./sample_source.csh.in} sample_source.csh --replace @sed@ ${gnused}/bin/sed + chmod u+rw sample_source.csh + + + # Test patching the sample source + + echo "Generating sample_source_patched.csh from sample_source.csh" + cp sample_source.csh sample_source_patched.csh + chmod u+w sample_source_patched.csh + patchRcPathCsh sample_source_patched.csh "$PWD/delta:$PWD/foxtrot" + + echo "Testing in Csh if sample_source.csh and sample_source_patched.csh modifies PATH the same way" + tcsh -e ${./test-sourcing-csh} sample_source.csh sample_source_patched.csh + + + # Test double-patching the sample source + + echo "Patching again sample_source_patched.csh from sample_source.csh" + patchRcPathCsh sample_source_patched.csh "$PWD/foxtrot:$PWD/golf" + + echo "Testing in Csh if sample_source.csh and sample_source_patched.csh modifies PATH the same way" + tcsh -e ${./test-sourcing-csh} sample_source.csh sample_source_patched.csh + + + # Create a dummy output + touch "$out" + '' + ) + { }; + + + + test-fish = callPackage + ( + { lib + , runCommandLocal + , fish + , hello + , patchRcPathFish + }: + runCommandLocal "patch-rc-path-fish-test" + { + nativeBuildInputs = [ + fish + patchRcPathFish + ]; + meta = { + description = "Package test of patchActivateFish"; + inherit (patchRcPathFish.meta) maintainers; + }; + } + '' + set -eu -o pipefail + + + # Test patching a blank file + + echo > blank.fish + + echo "Generating blank_patched.fish from blank.fish" + cp blank.fish blank_patched.fish + patchRcPathFish blank_patched.fish "$PWD/delta:$PWD/foxtrot" + + echo "Testing in Fish if blank.fish and blank_patched.fish modifies PATH the same way" + HOME_TEMP="$(mktemp -d temporary_home_XXXXXX)" + HOME="$HOME_TEMP" fish ${./test-sourcing-fish} blank.fish blank_patched.fish + rm -r "$HOME_TEMP" + + + # Test patching silent_hello file + + echo "hello > /dev/null" > silent_hello.fish + + echo "Generating silent_hello_patched.fish from silent_hello.fish" + cp silent_hello.fish silent_hello_patched.fish + patchRcPathFish silent_hello_patched.fish "${hello}/bin" + + echo "Testing in Fish if silent_hello_patched.fish get sourced without error" + HOME_TEMP="$(mktemp -d temporary_home_XXXXXX)" + HOME="$HOME_TEMP" fish -c "source silent_hello_patched.fish" + rm -r "$HOME_TEMP" + + + # Test patching the sample source + + cp ${./sample_source.fish} sample_source_patched.fish + chmod u+w sample_source_patched.fish + + echo "Generating sample_source_patched.fish from ${./sample_source.fish}" + patchRcPathFish sample_source_patched.fish "$PWD/delta:$PWD/foxtrot" + echo "Testing in Fish if sample_source.fish and sample_source_patched.fish modifies PATH the same way" + HOME_TEMP="$(mktemp -d temporary_home_XXXXXX)" + HOME="$HOME_TEMP" fish ${./test-sourcing-fish} ${./sample_source.fish} sample_source_patched.fish + rm -r "$HOME_TEMP" + + + # Test double-patching the sample source + + echo "Patching again sample_source_patched.fish from ${./sample_source.fish}" + patchRcPathFish sample_source_patched.fish "$PWD/foxtrot:$PWD/golf" + + echo "Testing in Fish if sample_source.fish and sample_source_patched.fish modifies PATH the same way" + HOME_TEMP="$(mktemp -d temporary_home_XXXXXX)" + HOME="$HOME_TEMP" fish ${./test-sourcing-fish} ${./sample_source.fish} sample_source_patched.fish + rm -r "$HOME_TEMP" + + + # Create a dummy output + touch "$out" + '' + ) + { }; + + + + test-posix = callPackage + ( + { lib + , runCommandLocal + , bash + , dash + , gnused + , hello + , ksh + , patchRcPathPosix + , shellcheck + }: + runCommandLocal "patch-rc-path-posix-test" + { + nativeBuildInputs = [ + bash + dash + ksh + patchRcPathPosix + shellcheck + ]; + meta = { + description = "Package test of patchActivatePosix"; + inherit (patchRcPathPosix.meta) maintainers; + }; + } + '' + set -eu -o pipefail + + + # Check the setup hook script + + echo "Running shellcheck against ${./test-sourcing-posix}" + shellcheck -s sh --exclude SC1090 ${./test-sourcing-posix} + shellcheck -s dash --exclude SC1090 ${./test-sourcing-posix} + + + # Test patching a blank file + + echo > blank.sh + + echo "Generating blank_patched.sh from blank.sh" + cp blank.sh blank_patched.sh + patchRcPathPosix blank_patched.sh "$PWD/delta:$PWD/foxtrot" + + echo "Running shellcheck against blank_patched.sh" + shellcheck -s sh blank_patched.sh + shellcheck -s dash blank_patched.sh + + echo "Testing in Bash if blank.sh and blank_patched.sh modifies PATH the same way" + bash --posix ${./test-sourcing-posix} ./blank.sh ./blank_patched.sh + + echo "Testing in Dash if blank.sh and blank_patched.sh modifies PATH the same way" + dash ${./test-sourcing-posix} ./blank.sh ./blank_patched.sh + + echo "Testing in Ksh if ./blank.sh and ./blank_patched.sh modifies PATH the same way" + ksh ${./test-sourcing-posix} "$PWD/blank.sh" "$PWD/blank_patched.sh" + + + # Test patching silent_hello file + + echo "hello > /dev/null" > silent_hello.sh + + echo "Generating silent_hello_patched.sh from silent_hello.sh" + cp silent_hello.sh silent_hello_patched.sh + patchRcPathPosix silent_hello_patched.sh "${hello}/bin" + + echo "Running shellcheck against silent_hello_patched.sh" + shellcheck -s sh silent_hello_patched.sh + shellcheck -s dash silent_hello_patched.sh + + echo "Testing in Bash if silent_hello_patched.sh get sourced without error" + bash --posix -eu -c ". ./silent_hello_patched.sh" + + echo "Testing in Dash if silent_hello_patched.sh get sourced without error" + dash -eu -c ". ./silent_hello_patched.sh" + + echo "Testing in Ksh if silent_hello_patched.sh get sourced without error" + ksh -eu -c ". $PWD/silent_hello_patched.sh" + + + # Generate the sample source "$PWD/delta:$PWD/foxtrot" "$PWD/delta:$PWD/foxtrot" + + substitute ${./sample_source.sh.in} sample_source.sh --replace @sed@ ${gnused}/bin/sed + chmod u+rw sample_source.sh + + + # Check the sample source + + echo "Running shellcheck against sample_source.sh" + shellcheck -s sh sample_source.sh + shellcheck -s dash sample_source.sh + + + # Test patching the sample source + + echo "Generating sample_source_patched.sh from sample_source.sh" + cp sample_source.sh sample_source_patched.sh + chmod u+w sample_source_patched.sh + patchRcPathPosix sample_source_patched.sh "$PWD/delta:$PWD/foxtrot" + + echo "Running shellcheck against sample_source_patched.sh" + shellcheck -s sh sample_source_patched.sh + shellcheck -s dash sample_source_patched.sh + + echo "Testing in Bash if sample_source.bash and sample_source_patched.bash modifies PATH the same way" + bash --posix ${./test-sourcing-posix} "./sample_source.sh" "./sample_source_patched.sh" + + echo "Testing in Dash if sample_source.sh and sample_source_patched.sh modifies PATH the same way" + dash ${./test-sourcing-posix} "./sample_source.sh" "./sample_source_patched.sh" + + echo "Testing in Ksh if sample_source.sh and sample_source_patched.sh modifies PATH the same way" + ksh ${./test-sourcing-posix} "$PWD/sample_source.sh" "$PWD/sample_source_patched.sh" + + + # Test double-patching the sample source + + echo "Patching again sample_source_patched.sh" + patchRcPathPosix sample_source_patched.sh "$PWD/foxtrot:$PWD/golf" + + echo "Running shellcheck against sample_source_patched.sh" + shellcheck -s sh sample_source_patched.sh + shellcheck -s dash sample_source_patched.sh + + echo "Testing in Bash if sample_source.bash and sample_source_patched.bash modifies PATH the same way" + bash --posix ${./test-sourcing-posix} "./sample_source.sh" "./sample_source_patched.sh" + + echo "Testing in Dash if sample_source.sh and sample_source_patched.sh modifies PATH the same way" + dash ${./test-sourcing-posix} "./sample_source.sh" "./sample_source_patched.sh" + + echo "Testing in Ksh if sample_source.sh and sample_source_patched.sh modifies PATH the same way" + ksh ${./test-sourcing-posix} "$PWD/sample_source.sh" "$PWD/sample_source_patched.sh" + + + # Create a dummy output + touch "$out" + '' + ) + { }; +} diff --git a/pkgs/build-support/setup-hooks/patch-rc-path-hooks/test/sample_source.bash b/pkgs/build-support/setup-hooks/patch-rc-path-hooks/test/sample_source.bash new file mode 100644 index 000000000000..6cb043e4e70c --- /dev/null +++ b/pkgs/build-support/setup-hooks/patch-rc-path-hooks/test/sample_source.bash @@ -0,0 +1,2 @@ +PATH="$PWD/charlie:${PATH/:$PWD\/bravo}" +export PATH diff --git a/pkgs/build-support/setup-hooks/patch-rc-path-hooks/test/sample_source.csh.in b/pkgs/build-support/setup-hooks/patch-rc-path-hooks/test/sample_source.csh.in new file mode 100644 index 000000000000..9606458c037e --- /dev/null +++ b/pkgs/build-support/setup-hooks/patch-rc-path-hooks/test/sample_source.csh.in @@ -0,0 +1 @@ +setenv PATH $PWD/charlie:`echo "$PATH" | @sed@ "s#:$PWD/bravo##"` diff --git a/pkgs/build-support/setup-hooks/patch-rc-path-hooks/test/sample_source.fish b/pkgs/build-support/setup-hooks/patch-rc-path-hooks/test/sample_source.fish new file mode 100644 index 000000000000..f638fe5e24d1 --- /dev/null +++ b/pkgs/build-support/setup-hooks/patch-rc-path-hooks/test/sample_source.fish @@ -0,0 +1,9 @@ +begin + for p in $PATH + if test $p != "$PWD/bravo" + set TEMPORARY_PATH $TEMPORARY_PATH $p + end + end + set -g PATH $TEMPORARY_PATH +end +set PATH "$PWD/charlie" $PATH diff --git a/pkgs/build-support/setup-hooks/patch-rc-path-hooks/test/sample_source.sh.in b/pkgs/build-support/setup-hooks/patch-rc-path-hooks/test/sample_source.sh.in new file mode 100644 index 000000000000..42e64a1ffc08 --- /dev/null +++ b/pkgs/build-support/setup-hooks/patch-rc-path-hooks/test/sample_source.sh.in @@ -0,0 +1,2 @@ +PATH="$PWD/charlie:$(echo "$PATH" | @sed@ "s#:$PWD/bravo##")" +export PATH diff --git a/pkgs/build-support/setup-hooks/patch-rc-path-hooks/test/test-sourcing-bash b/pkgs/build-support/setup-hooks/patch-rc-path-hooks/test/test-sourcing-bash new file mode 100644 index 000000000000..1b6cc54d8f93 --- /dev/null +++ b/pkgs/build-support/setup-hooks/patch-rc-path-hooks/test/test-sourcing-bash @@ -0,0 +1,21 @@ +#!/usr/bin/env bash + +set -eu -o pipefail + +UNPATCHED_SOURCE_FILE="$1" +PATCHED_SOURCE_FILE="$2" +ORIG_PATH="$PWD/alfa:$PWD/bravo" +RESULT_PATH_FROM_UNPATCHED="$( + PATH="$ORIG_PATH"; export PATH + . "$UNPATCHED_SOURCE_FILE" + echo "$PATH" +)" +RESULT_PATH_FROM_PATCHED="$( + PATH="$ORIG_PATH"; export PATH + . "$PATCHED_SOURCE_FILE" + echo "$PATH" +)" +if [[ "$RESULT_PATH_FROM_UNPATCHED" != "$RESULT_PATH_FROM_PATCHED" ]]; then + echo "Result path mismatched: $UNPATCHED_SOURCE_FILE ($RESULT_PATH_FROM_UNPATCHED) and $PATCHED_SOURCE_FILE ($RESULT_PATH_FROM_PATCHED)" >&2 + exit 1 +fi diff --git a/pkgs/build-support/setup-hooks/patch-rc-path-hooks/test/test-sourcing-csh b/pkgs/build-support/setup-hooks/patch-rc-path-hooks/test/test-sourcing-csh new file mode 100644 index 000000000000..7ddb2ddc1bdc --- /dev/null +++ b/pkgs/build-support/setup-hooks/patch-rc-path-hooks/test/test-sourcing-csh @@ -0,0 +1,13 @@ +#/usr/bin/env tcsh + +set UNPATCHED_SOURCE_FILE = "$1" +set PATCHED_SOURCE_FILE = "$2" +set ORIG_PATH = "${PWD}/alfa:${PWD}/bravo" + +set RESULT_PATH_FROM_UNPATCHED = `setenv PATH "$ORIG_PATH"; source $UNPATCHED_SOURCE_FILE; echo $PATH` +set RESULT_PATH_FROM_PATCHED = `setenv PATH "$ORIG_PATH"; source $PATCHED_SOURCE_FILE; echo $PATH` + +if ($RESULT_PATH_FROM_UNPATCHED != $RESULT_PATH_FROM_PATCHED) then + echo "Result path mismatched: $UNPATCHED_SOURCE_FILE ($RESULT_PATH_FROM_UNPATCHED) and $PATCHED_SOURCE_FILE ($RESULT_PATH_FROM_PATCHED)" > /dev/stderr + exit 1 +endif diff --git a/pkgs/build-support/setup-hooks/patch-rc-path-hooks/test/test-sourcing-fish b/pkgs/build-support/setup-hooks/patch-rc-path-hooks/test/test-sourcing-fish new file mode 100644 index 000000000000..fcce014331e5 --- /dev/null +++ b/pkgs/build-support/setup-hooks/patch-rc-path-hooks/test/test-sourcing-fish @@ -0,0 +1,13 @@ +#/usr/bin/env fish + +set UNPATCHED_SOURCE_FILE $argv[1] +set PATCHED_SOURCE_FILE $argv[2] +set ORIG_PATH "$PWD/alfa:$PWD/bravo" + +set RESULT_PATH_FROM_UNPATCHED (fish -c "set -g PATH \"$ORIG_PATH\"; source $UNPATCHED_SOURCE_FILE; echo \"\$PATH\"") +set RESULT_PATH_FROM_PATCHED (fish -c "set -g PATH \"$ORIG_PATH\"; source $PATCHED_SOURCE_FILE; echo \"\$PATH\"") + +if test "$RESULT_PATH_FROM_UNPATCHED" != "$RESULT_PATH_FROM_PATCHED" + echo "Result path mismatched: $UNPATCHED_SOURCE_FILE ($RESULT_PATH_FROM_UNPATCHED) and $PATCHED_SOURCE_FILE ($RESULT_PATH_FROM_PATCHED)" >&2 + exit 1 +end diff --git a/pkgs/build-support/setup-hooks/patch-rc-path-hooks/test/test-sourcing-posix b/pkgs/build-support/setup-hooks/patch-rc-path-hooks/test/test-sourcing-posix new file mode 100644 index 000000000000..6039b4dcf097 --- /dev/null +++ b/pkgs/build-support/setup-hooks/patch-rc-path-hooks/test/test-sourcing-posix @@ -0,0 +1,21 @@ +#!/bin/sh + +set -eu + +UNPATCHED_SOURCE_FILE="$1" +PATCHED_SOURCE_FILE="$2" +ORIG_PATH="$PWD/alfa:$PWD/bravo" +RESULT_PATH_FROM_UNPATCHED="$( + PATH="$ORIG_PATH"; export PATH + . "$UNPATCHED_SOURCE_FILE" + echo "$PATH" +)" +RESULT_PATH_FROM_PATCHED="$( + PATH="$ORIG_PATH"; export PATH + . "$PATCHED_SOURCE_FILE" + echo "$PATH" +)" +if [ "$RESULT_PATH_FROM_UNPATCHED" != "$RESULT_PATH_FROM_PATCHED" ]; then + echo "Result path mismatched: $UNPATCHED_SOURCE_FILE ($RESULT_PATH_FROM_UNPATCHED) and $PATCHED_SOURCE_FILE ($RESULT_PATH_FROM_PATCHED)" > /dev/stderr + exit 1 +fi diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix index cdf564bd7644..22bace945227 100644 --- a/pkgs/top-level/all-packages.nix +++ b/pkgs/top-level/all-packages.nix @@ -983,6 +983,10 @@ with pkgs; octant-desktop = callPackage ../applications/networking/cluster/octant/desktop.nix { }; starboard-octant-plugin = callPackage ../applications/networking/cluster/octant/plugins/starboard-octant-plugin.nix { }; + inherit ( + callPackages ../build-support/setup-hooks/patch-rc-path-hooks { } + ) patchRcPathBash patchRcPathCsh patchRcPathFish patchRcPathPosix; + pathsFromGraph = ../build-support/kernel/paths-from-graph.pl; pruneLibtoolFiles = makeSetupHook { name = "prune-libtool-files"; }