From 0df362e8c85472534573efda992860f1447e7488 Mon Sep 17 00:00:00 2001 From: "Yamashita, Yuu" Date: Wed, 4 Nov 2015 14:03:21 +0000 Subject: [PATCH 1/3] Support deletion of virtualenv created in `envs` --- bin/pyenv-virtualenv-delete | 94 +++++++++++++++++++++++++++++++++ etc/pyenv.d/uninstall/envs.bash | 21 ++++++++ 2 files changed, 115 insertions(+) create mode 100755 bin/pyenv-virtualenv-delete create mode 100644 etc/pyenv.d/uninstall/envs.bash diff --git a/bin/pyenv-virtualenv-delete b/bin/pyenv-virtualenv-delete new file mode 100755 index 00000000..612b233f --- /dev/null +++ b/bin/pyenv-virtualenv-delete @@ -0,0 +1,94 @@ +#!/usr/bin/env bash +# +# Summary: Uninstall a specific Python virtualenv +# +# Usage: pyenv virtualenv-delete [-f|--force] +# +# -f Attempt to remove the specified virtualenv without prompting +# for confirmation. If the virtualenv does not exist, do not +# display an error message. +# +# See `pyenv virtualenvs` for a complete list of installed versions. +# +set -e + +# Provide pyenv completions +if [ "$1" = "--complete" ]; then + exec pyenv virtualenvs --bare +fi + +resolve_link() { + $(type -p greadlink readlink | head -1) "$1" +} + +usage() { + pyenv-help virtualenv-delete 2>/dev/null + [ -z "$1" ] || exit "$1" +} + +if [ -z "$PYENV_ROOT" ]; then + PYENV_ROOT="${HOME}/.pyenv" +fi + +if [ "$1" = "-h" ] || [ "$1" = "--help" ]; then + usage 0 +fi + +unset FORCE +if [ "$1" = "-f" ] || [ "$1" = "--force" ]; then + FORCE=true + shift +fi + +[ "$#" -eq 1 ] || usage 1 >&2 + +DEFINITION="$1" +case "$DEFINITION" in +"" | -* ) + usage 1 >&2 + ;; +esac + +VERSION_NAME="${DEFINITION##*/}" +COMPAT_PREFIX="${PYENV_ROOT}/versions/${VERSION_NAME}" + +if [[ "${DEFINITION}" != "${DEFINITION%/envs/*}" ]]; then + PREFIX="${PYENV_ROOT}/versions/${DEFINITION}" +else + if [ -L "${COMPAT_PREFIX}" ]; then + PREFIX="$(resolve_link "${COMPAT_PREFIX}" 2>/dev/null || true)" + if [[ "${PREFIX}" == "${PREFIX%/envs/*}" ]]; then + echo "pyenv-virtualenv: \`${PREFIX}' is a symlink for unknown location." 1>&2 + exit 1 + fi + else + if pyenv-virtualenv-prefix "${VERSION_NAME}" 1>/dev/null 2>&1; then + PREFIX="${PYENV_ROOT}/versions/${VERSION_NAME}" + unset COMPAT_PREFIX + else + echo "pyenv-virtualenv: \`${DEFINITION}' is not a virtualenv." 1>&2 + exit 1 + fi + fi +fi + +if [ -z "$FORCE" ]; then + if [ ! -d "$PREFIX" ]; then + echo "pyenv-virtualenv: virtualenv \`$VERSION_NAME' not installed" >&2 + exit 1 + fi + + read -p "pyenv-virtualenv: remove $PREFIX? " + case "$REPLY" in + y* | Y* ) ;; + * ) exit 1 ;; + esac +fi + +if [ -d "$PREFIX" ]; then + rm -rf "$PREFIX" + if [ -L "$COMPAT_PREFIX" ]; then + rm -rf "$COMPAT_PREFIX" + fi + pyenv-rehash +fi diff --git a/etc/pyenv.d/uninstall/envs.bash b/etc/pyenv.d/uninstall/envs.bash new file mode 100644 index 00000000..c7c499db --- /dev/null +++ b/etc/pyenv.d/uninstall/envs.bash @@ -0,0 +1,21 @@ +resolve_link() { + $(type -p greadlink readlink | head -1) "$1" +} + +if [ -n "${DEFINITION}" ]; then + if [[ "${DEFINITION}" != "${DEFINITION%/envs/*}" ]]; then + exec pyenv-virtualenv-delete ${FORCE+-f} "${DEFINITION}" + exit 128 + else + 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 + exec pyenv-virtualenv-delete ${FORCE+-f} "${REAL_DEFINITION}" + exit 128 + fi + fi + fi +fi From 7e821de319c5ec7daa757ad044df2b269187d215 Mon Sep 17 00:00:00 2001 From: "Yamashita, Yuu" Date: Wed, 4 Nov 2015 14:03:46 +0000 Subject: [PATCH 2/3] Support creating shims of virtual environments in `envs` (#103) --- etc/pyenv.d/rehash/envs.bash | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 etc/pyenv.d/rehash/envs.bash diff --git a/etc/pyenv.d/rehash/envs.bash b/etc/pyenv.d/rehash/envs.bash new file mode 100644 index 00000000..586c896c --- /dev/null +++ b/etc/pyenv.d/rehash/envs.bash @@ -0,0 +1,11 @@ +virtualenv_list_executable_names() { + local file + shopt -s nullglob + for file in "$PYENV_ROOT"/versions/*/envs/*/bin/*; do + echo "${file##*/}" + done + shopt -u nullglob +} +if declare -f make_shims 1>/dev/null 2>&1; then + make_shims $(virtualenv_list_executable_names | sort -u) +fi From 07b31aa2f667d097ca9fb405ce8e2a5523c6540b Mon Sep 17 00:00:00 2001 From: "Yamashita, Yuu" Date: Thu, 5 Nov 2015 05:42:10 +0000 Subject: [PATCH 3/3] Add tests for `virtualenv-delete` --- test/delete.bats | 71 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 test/delete.bats diff --git a/test/delete.bats b/test/delete.bats new file mode 100644 index 00000000..304beec2 --- /dev/null +++ b/test/delete.bats @@ -0,0 +1,71 @@ +#!/usr/bin/env bats + +load test_helper + +setup() { + export PYENV_ROOT="${TMP}/pyenv" +} + +@test "delete virtualenv" { + mkdir -p "${PYENV_ROOT}/versions/venv27" + + stub pyenv-virtualenv-prefix "venv27 : true" + stub pyenv-rehash "true" + + run pyenv-virtualenv-delete -f "venv27" + + assert_success + + unstub pyenv-virtualenv-prefix + unstub pyenv-rehash + + [ ! -d "${PYENV_ROOT}/versions/venv27" ] +} + +@test "delete virtualenv by symlink" { + mkdir -p "${PYENV_ROOT}/versions/2.7.10/envs/venv27" + ln -fs "${PYENV_ROOT}/versions/2.7.10/envs/venv27" "${PYENV_ROOT}/versions/venv27" + + stub pyenv-rehash "true" + + run pyenv-virtualenv-delete -f "venv27" + + assert_success + + unstub pyenv-rehash + + [ ! -d "${PYENV_ROOT}/versions/2.7.10/envs/venv27" ] + [ ! -L "${PYENV_ROOT}/versions/venv27" ] +} + +@test "delete virtualenv with symlink" { + mkdir -p "${PYENV_ROOT}/versions/2.7.10/envs/venv27" + ln -fs "${PYENV_ROOT}/versions/2.7.10/envs/venv27" "${PYENV_ROOT}/versions/venv27" + + stub pyenv-rehash "true" + + run pyenv-virtualenv-delete -f "2.7.10/envs/venv27" + + assert_success + + unstub pyenv-rehash + + [ ! -d "${PYENV_ROOT}/versions/2.7.10/envs/venv27" ] + [ ! -L "${PYENV_ROOT}/versions/venv27" ] +} + +@test "not delete virtualenv with same name" { + mkdir -p "${PYENV_ROOT}/versions/2.7.10/envs/venv27" + mkdir -p "${PYENV_ROOT}/versions/venv27" + + stub pyenv-rehash "true" + + run pyenv-virtualenv-delete -f "2.7.10/envs/venv27" + + assert_success + + unstub pyenv-rehash + + [ ! -d "${PYENV_ROOT}/versions/2.7.10/envs/venv27" ] + [ -d "${PYENV_ROOT}/versions/venv27" ] +}