diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml new file mode 100644 index 0000000..59cf7d4 --- /dev/null +++ b/.github/workflows/tests.yml @@ -0,0 +1,37 @@ +name: tests +on: [pull_request, push] +jobs: + tests: + strategy: + fail-fast: false + matrix: + os: + - ubuntu-22.04 + - ubuntu-20.04 + - macos-12 + - macos-11 + runs-on: ${{ matrix.os }} + steps: + - uses: actions/checkout@v2 + # Normally, we would use the superbly maintained... + # - uses: actions/setup-python@v2 + # with: + # python-version: ${{ matrix.python-version }} + # ... but in the repo, we want to test pyenv builds on Ubuntu + # - run: | + # sudo apt-get install -y build-essential libssl-dev zlib1g-dev libbz2-dev \ + # libreadline-dev libsqlite3-dev wget curl llvm libncurses5-dev libncursesw5-dev \ + # xz-utils tk-dev libffi-dev liblzma-dev python-openssl git + # https://github.com/pyenv/pyenv#installation + #- env: + # PYENV_ROOT: /home/runner/work/pyenv/pyenv + # run: | + # echo $PYENV_ROOT + # echo "$PYENV_ROOT/shims:$PYENV_ROOT/bin" >> $GITHUB_PATH + # macos-11 Github Actions env has an old `readlink` and lacks `greadlink` which causes Bats to break + - run: | + if [[ $RUNNER_OS == "macOS" ]] && [[ $(sw_vers -productVersion | awk -F. '{print $1}') -lt 12 ]]; then + brew install coreutils + fi + - run: git clone https://github.com/bats-core/bats-core.git --depth=1 -b v1.2.0 bats + - run: bats/bin/bats --tap test diff --git a/.gitignore b/.gitignore index c860e56..75a199c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +/bats/ /libexec/pyenv-virtualenv/*/*.class /libexec/pyenv-virtualenv/*/*.pyc /libexec/pyenv-virtualenv/*/*.pyo diff --git a/.travis.yml b/.travis.yml index 64342c6..b7849da 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,5 @@ sudo: false -install: git clone https://github.com/sstephenson/bats.git +install: git clone --depth=1 https://github.com/sstephenson/bats.git script: bats/bin/bats --tap test language: c notifications: diff --git a/CHANGELOG.md b/CHANGELOG.md index 769b5f6..cda5b0d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,7 @@ #### 1.1.4 * Support newer conda (#290) -* Prefer `python3.x` executable if avaialble (#206, #282, #296) +* Prefer `python3.x` executable if available (#206, #282, #296) #### 1.1.3 diff --git a/bin/pyenv-virtualenv b/bin/pyenv-virtualenv index 83dd8b0..fa60c00 100755 --- a/bin/pyenv-virtualenv +++ b/bin/pyenv-virtualenv @@ -145,7 +145,7 @@ detect_venv() { if [ -x "${prefix}/bin/virtualenv" ]; then HAS_VIRTUALENV=1 fi - # Prefer `python3.x` executable if avaialble (#206, #282) + # Prefer `python3.x` executable if available (#206, #282) local python for python in "python${PYENV_VERSION%.*}" "python${PYENV_VERSION%%.*}" "python"; do if pyenv-exec "${python}" -m venv --help 1>/dev/null 2>&1; then diff --git a/bin/pyenv-virtualenv-delete b/bin/pyenv-virtualenv-delete index aa21410..5fe1a46 100755 --- a/bin/pyenv-virtualenv-delete +++ b/bin/pyenv-virtualenv-delete @@ -75,7 +75,7 @@ else if pyenv-virtualenv-prefix "${VERSION_NAME}" 1>/dev/null 2>&1; then PREFIX="${PYENV_ROOT}/versions/${VERSION_NAME}" unset COMPAT_PREFIX - else + elif [ -z "$FORCE" ]; then echo "pyenv-virtualenv: \`${DEFINITION}' is not a virtualenv." 1>&2 exit 1 fi diff --git a/bin/pyenv-virtualenv-init b/bin/pyenv-virtualenv-init index 1a60c53..a24a785 100755 --- a/bin/pyenv-virtualenv-init +++ b/bin/pyenv-virtualenv-init @@ -129,7 +129,7 @@ esac if [[ "$shell" != "fish" ]]; then cat </dev/null || true)" - REAL_DEFINITION="${REAL_PREFIX#${PYENV_ROOT}/versions/}" - if [[ "${REAL_DEFINITION}" != "${REAL_DEFINITION%/envs/*}" ]]; then - # Uninstall virtualenv by short name - exec pyenv-virtualenv-delete ${FORCE+-f} "${REAL_DEFINITION}" - exit 128 - fi +uninstall_related_virtual_env() { + if [ -n "${DEFINITION}" ]; then + if [[ "${DEFINITION}" != "${DEFINITION%/envs/*}" ]]; then + # Uninstall virtualenv by long name + exec pyenv-virtualenv-delete ${FORCE+-f} "${DEFINITION}" + exit 128 else - # Uninstall all virtualenvs inside `envs` directory too - shopt -s nullglob - for virtualenv in "${PREFIX}/envs/"*; do - pyenv-virtualenv-delete ${FORCE+-f} "${DEFINITION}/envs/${virtualenv##*/}" - done - shopt -u nullglob + VERSION_NAME="${VERSION_NAME:-${DEFINITION##*/}}" + PREFIX="${PREFIX:-${PYENV_ROOT}/versions/${VERSION_NAME}}" + if [ -L "${PREFIX}" ]; then + REAL_PREFIX="$(resolve_link "${PREFIX}" 2>/dev/null || true)" + REAL_DEFINITION="${REAL_PREFIX#${PYENV_ROOT}/versions/}" + if [[ "${REAL_DEFINITION}" != "${REAL_DEFINITION%/envs/*}" ]]; then + # Uninstall virtualenv by short name + exec pyenv-virtualenv-delete ${FORCE+-f} "${REAL_DEFINITION}" + exit 128 + fi + else + # Uninstall all virtualenvs inside `envs` directory too + shopt -s nullglob + for virtualenv in "${PREFIX}/envs/"*; do + pyenv-virtualenv-delete ${FORCE+-f} "${DEFINITION}/envs/${virtualenv##*/}" + done + shopt -u nullglob + fi fi fi -fi +} + +before_uninstall "uninstall_related_virtual_env" diff --git a/libexec/pyenv-virtualenv-realpath b/libexec/pyenv-virtualenv-realpath index 8a70128..de0bf5f 100644 --- a/libexec/pyenv-virtualenv-realpath +++ b/libexec/pyenv-virtualenv-realpath @@ -3,7 +3,7 @@ # Usage: . pyenv-virtualenv-realpath if ! { - enable -f "${BASH_SOURCE%/*}"/../libexec/pyenv-realpath.dylib realpath || + enable -f "${BASH_SOURCE%/*}"/../../../libexec/pyenv-realpath.dylib realpath || type realpath } >/dev/null 2>&1; then if [ -n "$PYENV_NATIVE_EXT" ]; then diff --git a/test/deactivate.bats b/test/deactivate.bats index d0b6dea..53ed0cb 100644 --- a/test/deactivate.bats +++ b/test/deactivate.bats @@ -1,4 +1,4 @@ -#!/usr/bin/env bats + #!/usr/bin/env bats load test_helper @@ -54,7 +54,7 @@ EOS export VIRTUAL_ENV="${PYENV_ROOT}/versions/venv" export PYENV_ACTIVATE_SHELL= - PYENV_SHELL="bash" run pyenv-sh-deactivate --quit + PYENV_SHELL="bash" run pyenv-sh-deactivate --quiet assert_success assert_output </dev/null 2>&1; then - unset -f deactivate; -fi; -EOS -} - @test "deactivate virtualenv (with shell activation)" { export PYENV_VIRTUALENV_INIT=1 export PYENV_VIRTUAL_ENV="${PYENV_ROOT}/versions/venv" diff --git a/test/init.bats b/test/init.bats index 74b0e2b..85f2b42 100644 --- a/test/init.bats +++ b/test/init.bats @@ -6,7 +6,7 @@ load test_helper unset PYENV_SHELL SHELL=/bin/false run pyenv-virtualenv-init - assert_success - assert_output_contains ' PROMPT_COMMAND="_pyenv_virtualenv_hook;$PROMPT_COMMAND";' + assert_output_contains ' PROMPT_COMMAND="_pyenv_virtualenv_hook;${PROMPT_COMMAND-}"' } @test "detect parent shell from script (sh)" { @@ -15,7 +15,7 @@ load test_helper chmod +x ${TMP}/script.sh run ${TMP}/script.sh assert_success - assert_output_contains_not ' PROMPT_COMMAND="_pyenv_virtualenv_hook;$PROMPT_COMMAND";' + assert_output_contains_not ' PROMPT_COMMAND="_pyenv_virtualenv_hook;${PROMPT_COMMAND-}"' rm -f "${TMP}/script.sh" } @@ -25,7 +25,7 @@ load test_helper chmod +x ${TMP}/script.sh run ${TMP}/script.sh assert_success - assert_output_contains ' PROMPT_COMMAND="_pyenv_virtualenv_hook;$PROMPT_COMMAND";' + assert_output_contains ' PROMPT_COMMAND="_pyenv_virtualenv_hook;${PROMPT_COMMAND-}"' rm -f "${TMP}/script.sh" } @@ -54,15 +54,15 @@ export PATH="${TMP}/pyenv/plugins/pyenv-virtualenv/shims:\${PATH}"; export PYENV_VIRTUALENV_INIT=1; _pyenv_virtualenv_hook() { local ret=\$? - if [ -n "\$VIRTUAL_ENV" ]; then + if [ -n "\${VIRTUAL_ENV-}" ]; then eval "\$(pyenv sh-activate --quiet || pyenv sh-deactivate --quiet || true)" || true else eval "\$(pyenv sh-activate --quiet || true)" || true fi return \$ret }; -if ! [[ "\$PROMPT_COMMAND" =~ _pyenv_virtualenv_hook ]]; then - PROMPT_COMMAND="_pyenv_virtualenv_hook;\$PROMPT_COMMAND"; +if ! [[ "\${PROMPT_COMMAND-}" =~ _pyenv_virtualenv_hook ]]; then + PROMPT_COMMAND="_pyenv_virtualenv_hook;\${PROMPT_COMMAND-}" fi EOS } @@ -72,6 +72,8 @@ EOS run pyenv-virtualenv-init - fish assert_success assert_output <