Skip to content

Support uninstall and rehash of virtual environments created in envs #106

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Nov 5, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
94 changes: 94 additions & 0 deletions bin/pyenv-virtualenv-delete
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
#!/usr/bin/env bash
#
# Summary: Uninstall a specific Python virtualenv
#
# Usage: pyenv virtualenv-delete [-f|--force] <virtualenv>
#
# -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
11 changes: 11 additions & 0 deletions etc/pyenv.d/rehash/envs.bash
Original file line number Diff line number Diff line change
@@ -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
21 changes: 21 additions & 0 deletions etc/pyenv.d/uninstall/envs.bash
Original file line number Diff line number Diff line change
@@ -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
71 changes: 71 additions & 0 deletions test/delete.bats
Original file line number Diff line number Diff line change
@@ -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" ]
}