From 54c51d8f87e4ac94d1dd3fb95042769deb55e705 Mon Sep 17 00:00:00 2001 From: Alex Hedges Date: Sun, 25 Feb 2024 15:02:41 -0500 Subject: [PATCH] Handle case where `pyenv-commands --sh` returns nothing When running `eval "$(pyenv init -)"` to initialize `pyenv`, the command generates a shell script to be executed. When not using the `fish` shell, this script contains a `case` statement where the first case matches against the output of `pyenv-commands --sh` and the second case handles everything else. However, if no commands are returned, then the matching expression will be only `)`, which is invalid Bash. I have solved this (on the advice of @ native-api) by using the string `/` if there are no commands to include. `/` is the only character in Linux/POSIX besides `\0` that a filename cannot contain, so it is safe to use as a pattern that will never match. To catch any regressions, I have added a test to catch unexpected changes in the generated `case` statement. I copied the `create_executable` function from `latest.bats` because I needed to shim `pyenv-commands`. I do not know if `pyenv-commands --sh` can ever return nothing under normal conditions, but it happened to me due to completely unrelated problems in underlying Unix utilities called by `pyenv`. Although this bug will rarely occur, I feel that this increased robustness will be useful. --- libexec/pyenv-init | 2 +- test/init.bats | 30 ++++++++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/libexec/pyenv-init b/libexec/pyenv-init index a875bb31..492360e6 100755 --- a/libexec/pyenv-init +++ b/libexec/pyenv-init @@ -297,7 +297,7 @@ EOS fi case "\$command" in - ${commands[*]}) + ${commands[*]:-/}) eval "\$(pyenv "sh-\$command" "\$@")" ;; *) diff --git a/test/init.bats b/test/init.bats index 21109c94..53d131cc 100755 --- a/test/init.bats +++ b/test/init.bats @@ -2,6 +2,18 @@ load test_helper +setup() { + export PATH="${PYENV_TEST_DIR}/bin:$PATH" +} + +create_executable() { + local name="$1" + local bin="${PYENV_TEST_DIR}/bin" + mkdir -p "$bin" + sed -Ee '1s/^ +//' > "${bin}/$name" + chmod +x "${bin}/$name" +} + @test "creates shims and versions directories" { assert [ ! -d "${PYENV_ROOT}/shims" ] assert [ ! -d "${PYENV_ROOT}/versions" ] @@ -167,6 +179,24 @@ echo "\$PATH" assert_line ' case "$command" in' } +@test "outputs sh-compatible case syntax" { + create_executable pyenv-commands <