Bring back POSIX sh (dash) support

gh-525

Assisted by Qwen3-Coder-30B-A3B-Instruct via OpenCode.
This commit is contained in:
Christopher O. Caldwell 2026-04-20 17:38:22 -06:00
parent 6a832cacbb
commit 57ac377dd8
No known key found for this signature in database
GPG key ID: D23FBE970881C782
2 changed files with 28 additions and 18 deletions

View file

@ -214,7 +214,7 @@ EOS
return \$ret return \$ret
fi fi
if [ "\${PWD}" = "\${_PYENV_VH_PWD-}" ] \\ if [ "\${PWD}" = "\${_PYENV_VH_PWD-}" ] \\
&& [ "\$(stat ${_stat_fmt} "\${_PYENV_VH_PATHS[@]}" 2>/dev/null)" = "\${_PYENV_VH_MTIMES-}" ]; then && [ "\$(stat ${_stat_fmt} \${_PYENV_VH_PATHS} 2>/dev/null)" = "\${_PYENV_VH_MTIMES-}" ]; then
return \$ret return \$ret
fi fi
fi fi
@ -227,25 +227,25 @@ EOS
_PYENV_VH_VERSION="\${PYENV_VERSION-}" _PYENV_VH_VERSION="\${PYENV_VERSION-}"
_PYENV_VH_VENV="\${VIRTUAL_ENV-}" _PYENV_VH_VENV="\${VIRTUAL_ENV-}"
local _pvh_d="\${PWD}" _pvh_found_local=0 local _pvh_d="\${PWD}" _pvh_found_local=0
_PYENV_VH_PATHS=() _PYENV_VH_PATHS=""
while :; do while :; do
if [ -f "\${_pvh_d}/.python-version" ] || [ -L "\${_pvh_d}/.python-version" ]; then if [ -f "\${_pvh_d}/.python-version" ] || [ -L "\${_pvh_d}/.python-version" ]; then
_PYENV_VH_PATHS+=("\${_pvh_d}/.python-version") _PYENV_VH_PATHS="\${_PYENV_VH_PATHS} \${_pvh_d}/.python-version"
if [ -f "\${_pvh_d}/.python-version" ]; then if [ -f "\${_pvh_d}/.python-version" ]; then
_pvh_found_local=1 _pvh_found_local=1
break break
fi fi
else else
_PYENV_VH_PATHS+=("\${_pvh_d}") _PYENV_VH_PATHS="\${_PYENV_VH_PATHS} \${_pvh_d}"
fi fi
[ "\${_pvh_d}" = "/" ] && break [ "\${_pvh_d}" = "/" ] && break
_pvh_d="\${_pvh_d%/*}" _pvh_d="\${_pvh_d%/*}"
[ -z "\${_pvh_d}" ] && _pvh_d="/" [ -z "\${_pvh_d}" ] && _pvh_d="/"
done done
if [ "\${_pvh_found_local}" = "0" ]; then if [ "\${_pvh_found_local}" = "0" ]; then
_PYENV_VH_PATHS+=("\${PYENV_ROOT}/version") _PYENV_VH_PATHS="\${_PYENV_VH_PATHS} \${PYENV_ROOT}/version"
fi fi
_PYENV_VH_MTIMES="\$(stat ${_stat_fmt} "\${_PYENV_VH_PATHS[@]}" 2>/dev/null)" _PYENV_VH_MTIMES="\$(stat ${_stat_fmt} \${_PYENV_VH_PATHS} 2>/dev/null)"
return \$ret return \$ret
}; };
EOS EOS

View file

@ -39,6 +39,16 @@ load test_helper
assert_output_contains 'eval "$(pyenv virtualenv-init -)"' assert_output_contains 'eval "$(pyenv virtualenv-init -)"'
} }
@test "generated hook code is valid POSIX sh" {
# Get output directly to avoid bats env affecting shell detection
# The bash output should be POSIX sh-compatible (no bash arrays, etc.)
output=$(bash bin/pyenv-virtualenv-init - bash 2>/dev/null)
# Validate syntax with dash (POSIX sh)
result=$(echo "$output" | dash -n - 2>&1)
status=$?
[ $status -eq 0 ] || echo "dash failed: $result" >&2
}
@test "fish instructions" { @test "fish instructions" {
run pyenv-virtualenv-init fish run pyenv-virtualenv-init fish
assert [ "$status" -eq 1 ] assert [ "$status" -eq 1 ]
@ -61,7 +71,7 @@ _pyenv_virtualenv_hook() {
return \$ret return \$ret
fi fi
if [ "\${PWD}" = "\${_PYENV_VH_PWD-}" ] \\ if [ "\${PWD}" = "\${_PYENV_VH_PWD-}" ] \\
&& [ "\$(stat ${_stat_fmt} "\${_PYENV_VH_PATHS[@]}" 2>/dev/null)" = "\${_PYENV_VH_MTIMES-}" ]; then && [ "\$(stat ${_stat_fmt} \${_PYENV_VH_PATHS} 2>/dev/null)" = "\${_PYENV_VH_MTIMES-}" ]; then
return \$ret return \$ret
fi fi
fi fi
@ -74,25 +84,25 @@ _pyenv_virtualenv_hook() {
_PYENV_VH_VERSION="\${PYENV_VERSION-}" _PYENV_VH_VERSION="\${PYENV_VERSION-}"
_PYENV_VH_VENV="\${VIRTUAL_ENV-}" _PYENV_VH_VENV="\${VIRTUAL_ENV-}"
local _pvh_d="\${PWD}" _pvh_found_local=0 local _pvh_d="\${PWD}" _pvh_found_local=0
_PYENV_VH_PATHS=() _PYENV_VH_PATHS=""
while :; do while :; do
if [ -f "\${_pvh_d}/.python-version" ] || [ -L "\${_pvh_d}/.python-version" ]; then if [ -f "\${_pvh_d}/.python-version" ] || [ -L "\${_pvh_d}/.python-version" ]; then
_PYENV_VH_PATHS+=("\${_pvh_d}/.python-version") _PYENV_VH_PATHS="\${_PYENV_VH_PATHS} \${_pvh_d}/.python-version"
if [ -f "\${_pvh_d}/.python-version" ]; then if [ -f "\${_pvh_d}/.python-version" ]; then
_pvh_found_local=1 _pvh_found_local=1
break break
fi fi
else else
_PYENV_VH_PATHS+=("\${_pvh_d}") _PYENV_VH_PATHS="\${_PYENV_VH_PATHS} \${_pvh_d}"
fi fi
[ "\${_pvh_d}" = "/" ] && break [ "\${_pvh_d}" = "/" ] && break
_pvh_d="\${_pvh_d%/*}" _pvh_d="\${_pvh_d%/*}"
[ -z "\${_pvh_d}" ] && _pvh_d="/" [ -z "\${_pvh_d}" ] && _pvh_d="/"
done done
if [ "\${_pvh_found_local}" = "0" ]; then if [ "\${_pvh_found_local}" = "0" ]; then
_PYENV_VH_PATHS+=("\${PYENV_ROOT}/version") _PYENV_VH_PATHS="\${_PYENV_VH_PATHS} \${PYENV_ROOT}/version"
fi fi
_PYENV_VH_MTIMES="\$(stat ${_stat_fmt} "\${_PYENV_VH_PATHS[@]}" 2>/dev/null)" _PYENV_VH_MTIMES="\$(stat ${_stat_fmt} \${_PYENV_VH_PATHS} 2>/dev/null)"
return \$ret return \$ret
}; };
if ! [[ "\${PROMPT_COMMAND-}" =~ _pyenv_virtualenv_hook ]]; then if ! [[ "\${PROMPT_COMMAND-}" =~ _pyenv_virtualenv_hook ]]; then
@ -172,7 +182,7 @@ _pyenv_virtualenv_hook() {
return \$ret return \$ret
fi fi
if [ "\${PWD}" = "\${_PYENV_VH_PWD-}" ] \\ if [ "\${PWD}" = "\${_PYENV_VH_PWD-}" ] \\
&& [ "\$(stat ${_stat_fmt} "\${_PYENV_VH_PATHS[@]}" 2>/dev/null)" = "\${_PYENV_VH_MTIMES-}" ]; then && [ "\$(stat ${_stat_fmt} \${_PYENV_VH_PATHS} 2>/dev/null)" = "\${_PYENV_VH_MTIMES-}" ]; then
return \$ret return \$ret
fi fi
fi fi
@ -185,25 +195,25 @@ _pyenv_virtualenv_hook() {
_PYENV_VH_VERSION="\${PYENV_VERSION-}" _PYENV_VH_VERSION="\${PYENV_VERSION-}"
_PYENV_VH_VENV="\${VIRTUAL_ENV-}" _PYENV_VH_VENV="\${VIRTUAL_ENV-}"
local _pvh_d="\${PWD}" _pvh_found_local=0 local _pvh_d="\${PWD}" _pvh_found_local=0
_PYENV_VH_PATHS=() _PYENV_VH_PATHS=""
while :; do while :; do
if [ -f "\${_pvh_d}/.python-version" ] || [ -L "\${_pvh_d}/.python-version" ]; then if [ -f "\${_pvh_d}/.python-version" ] || [ -L "\${_pvh_d}/.python-version" ]; then
_PYENV_VH_PATHS+=("\${_pvh_d}/.python-version") _PYENV_VH_PATHS="\${_PYENV_VH_PATHS} \${_pvh_d}/.python-version"
if [ -f "\${_pvh_d}/.python-version" ]; then if [ -f "\${_pvh_d}/.python-version" ]; then
_pvh_found_local=1 _pvh_found_local=1
break break
fi fi
else else
_PYENV_VH_PATHS+=("\${_pvh_d}") _PYENV_VH_PATHS="\${_PYENV_VH_PATHS} \${_pvh_d}"
fi fi
[ "\${_pvh_d}" = "/" ] && break [ "\${_pvh_d}" = "/" ] && break
_pvh_d="\${_pvh_d%/*}" _pvh_d="\${_pvh_d%/*}"
[ -z "\${_pvh_d}" ] && _pvh_d="/" [ -z "\${_pvh_d}" ] && _pvh_d="/"
done done
if [ "\${_pvh_found_local}" = "0" ]; then if [ "\${_pvh_found_local}" = "0" ]; then
_PYENV_VH_PATHS+=("\${PYENV_ROOT}/version") _PYENV_VH_PATHS="\${_PYENV_VH_PATHS} \${PYENV_ROOT}/version"
fi fi
_PYENV_VH_MTIMES="\$(stat ${_stat_fmt} "\${_PYENV_VH_PATHS[@]}" 2>/dev/null)" _PYENV_VH_MTIMES="\$(stat ${_stat_fmt} \${_PYENV_VH_PATHS} 2>/dev/null)"
return \$ret return \$ret
}; };
typeset -g -a precmd_functions typeset -g -a precmd_functions