diff --git a/COMMANDS.md b/COMMANDS.md index 5d52e13f..203250d4 100644 --- a/COMMANDS.md +++ b/COMMANDS.md @@ -386,11 +386,12 @@ List existing pyenv shims. Configure the shell environment for pyenv - Usage: eval "$(pyenv init [-|--path] [--no-rehash] [])" + Usage: eval "$(pyenv init [-|--path] [--no-push-path] [--no-rehash] [])" - Initialize shims directory, print PYENV_SHELL variable, completions path and shell function --path Print shims path + --no-push-path Do not push shim to the start of PATH if they're already there --no-rehash Add no rehash command to output ## `pyenv completions` diff --git a/libexec/pyenv-init b/libexec/pyenv-init index 24ef3b16..7d222377 100755 --- a/libexec/pyenv-init +++ b/libexec/pyenv-init @@ -1,6 +1,6 @@ #!/usr/bin/env bash # Summary: Configure the shell environment for pyenv -# Usage: eval "$(pyenv init [-|--path] [--no-rehash] [])" +# Usage: eval "$(pyenv init [-|--path] [--no-push-path] [--no-rehash] [])" set -e [ -n "$PYENV_DEBUG" ] && set -x @@ -9,6 +9,7 @@ set -e if [ "$1" = "--complete" ]; then echo - echo --path + echo --no-push-path echo --no-rehash echo bash echo fish @@ -19,6 +20,7 @@ fi mode="help" no_rehash="" +no_push_path="" for args in "$@" do if [ "$args" = "-" ]; then @@ -30,6 +32,11 @@ do mode="path" shift fi + + if [ "$args" = "--no-push-path" ]; then + no_push_path=1 + shift + fi if [ "$args" = "--no-rehash" ]; then no_rehash=1 @@ -141,28 +148,56 @@ function init_dirs() { } function print_path() { - case "$shell" in - fish ) - echo 'while set index (contains -i -- '\'"${PYENV_ROOT}/shims"\'' $PATH)' - echo 'set -eg PATH[$index]; end; set -e index' - echo 'set -gx PATH '\'"${PYENV_ROOT}/shims"\'' $PATH' - ;; - * ) - # Some distros (notably Debian-based) set Bash's SSH_SOURCE_BASHRC compilation option - # that makes it source `bashrc` under SSH even when not interactive. - # This is inhibited by a guard in Debian's stock `bashrc` but some people remove it - # in order to get proper environment for noninteractive remote commands - # (SSH provides /etc/ssh/sshrc and ~/.ssh/rc for that but no-one seems to use them for some reason). - # This has caused an infinite `bashrc` execution loop for those people in the below nested Bash invocation (#2367). - # --norc negates this behavior of such a customized Bash. - echo 'PATH="$(bash --norc -ec '\''IFS=:; paths=($PATH); ' - echo 'for i in ${!paths[@]}; do ' - echo 'if [[ ${paths[i]} == "'\'\'"${PYENV_ROOT}/shims"\'\''" ]]; then unset '\'\\\'\''paths[i]'\'\\\'\''; ' - echo 'fi; done; ' - echo 'echo "${paths[*]}"'\'')"' - echo 'export PATH="'"${PYENV_ROOT}"'/shims:${PATH}"' - ;; - esac + # if no_push_path is set, guard the PATH manipulation with a check on whether + # the shim is already in the PATH. + if [ -n "$no_push_path" ]; then + case "$shell" in + fish ) + echo 'if not contains -- "'"${PYENV_ROOT}/shims"'" $PATH' + print_path_prepend_shims + echo 'end' + ;; + * ) + echo 'if [[ ":$PATH:" != *'\':"${PYENV_ROOT}"/shims:\''* ]]; then' + print_path_prepend_shims + echo 'fi' + ;; + esac + else + case "$shell" in + fish ) + echo 'while set pyenv_index (contains -i -- "'"${PYENV_ROOT}/shims"'" $PATH)' + echo 'set -eg PATH[$pyenv_index]; end; set -e pyenv_index' + print_path_prepend_shims + ;; + * ) + # Some distros (notably Debian-based) set Bash's SSH_SOURCE_BASHRC compilation option + # that makes it source `bashrc` under SSH even when not interactive. + # This is inhibited by a guard in Debian's stock `bashrc` but some people remove it + # in order to get proper environment for noninteractive remote commands + # (SSH provides /etc/ssh/sshrc and ~/.ssh/rc for that but no-one seems to use them for some reason). + # This has caused an infinite `bashrc` execution loop for those people in the below nested Bash invocation (#2367). + # --norc negates this behavior of such a customized Bash. + echo 'PATH="$(bash --norc -ec '\''IFS=:; paths=($PATH); ' + echo 'for i in ${!paths[@]}; do ' + echo 'if [[ ${paths[i]} == "'\'\'"${PYENV_ROOT}/shims"\'\''" ]]; then unset '\'\\\'\''paths[i]'\'\\\'\''; ' + echo 'fi; done; ' + echo 'echo "${paths[*]}"'\'')"' + print_path_prepend_shims + ;; + esac + fi +} + +function print_path_prepend_shims() { + case "$shell" in + fish ) + echo 'set -gx PATH '\'"${PYENV_ROOT}/shims"\'' $PATH' + ;; + * ) + echo 'export PATH="'"${PYENV_ROOT}"'/shims:${PATH}"' + ;; + esac } function print_env() { diff --git a/test/init.bats b/test/init.bats index 154d340b..bfe253e3 100755 --- a/test/init.bats +++ b/test/init.bats @@ -98,7 +98,6 @@ echo "\$PATH" command -v fish >/dev/null || skip "-- fish not installed" OLDPATH="$PATH" export PATH="${BATS_TEST_DIRNAME}/nonexistent:${PYENV_ROOT}/shims:$PATH" - # fish 2 (Ubuntu Bionic) adds spurious messages when setting PATH, messing up the output run fish </dev/null || skip "-- fish not installed" + export PATH="${BATS_TEST_DIRNAME}/../libexec:/usr/bin:/bin:/usr/local/bin" + run fish </dev/null || skip "-- fish not installed" + export PATH="${BATS_TEST_DIRNAME}/../libexec:/usr/bin:${PYENV_ROOT}/shims:/bin:/usr/local/bin" + run fish <