Skip to content

Commit e489163

Browse files
committed
Merge pull request #106 from yyuu/uninstall-rehash-envs
Support uninstall and rehash of virtual environments created in `envs`
2 parents 5c9909f + 07b31aa commit e489163

File tree

4 files changed

+197
-0
lines changed

4 files changed

+197
-0
lines changed

bin/pyenv-virtualenv-delete

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
#!/usr/bin/env bash
2+
#
3+
# Summary: Uninstall a specific Python virtualenv
4+
#
5+
# Usage: pyenv virtualenv-delete [-f|--force] <virtualenv>
6+
#
7+
# -f Attempt to remove the specified virtualenv without prompting
8+
# for confirmation. If the virtualenv does not exist, do not
9+
# display an error message.
10+
#
11+
# See `pyenv virtualenvs` for a complete list of installed versions.
12+
#
13+
set -e
14+
15+
# Provide pyenv completions
16+
if [ "$1" = "--complete" ]; then
17+
exec pyenv virtualenvs --bare
18+
fi
19+
20+
resolve_link() {
21+
$(type -p greadlink readlink | head -1) "$1"
22+
}
23+
24+
usage() {
25+
pyenv-help virtualenv-delete 2>/dev/null
26+
[ -z "$1" ] || exit "$1"
27+
}
28+
29+
if [ -z "$PYENV_ROOT" ]; then
30+
PYENV_ROOT="${HOME}/.pyenv"
31+
fi
32+
33+
if [ "$1" = "-h" ] || [ "$1" = "--help" ]; then
34+
usage 0
35+
fi
36+
37+
unset FORCE
38+
if [ "$1" = "-f" ] || [ "$1" = "--force" ]; then
39+
FORCE=true
40+
shift
41+
fi
42+
43+
[ "$#" -eq 1 ] || usage 1 >&2
44+
45+
DEFINITION="$1"
46+
case "$DEFINITION" in
47+
"" | -* )
48+
usage 1 >&2
49+
;;
50+
esac
51+
52+
VERSION_NAME="${DEFINITION##*/}"
53+
COMPAT_PREFIX="${PYENV_ROOT}/versions/${VERSION_NAME}"
54+
55+
if [[ "${DEFINITION}" != "${DEFINITION%/envs/*}" ]]; then
56+
PREFIX="${PYENV_ROOT}/versions/${DEFINITION}"
57+
else
58+
if [ -L "${COMPAT_PREFIX}" ]; then
59+
PREFIX="$(resolve_link "${COMPAT_PREFIX}" 2>/dev/null || true)"
60+
if [[ "${PREFIX}" == "${PREFIX%/envs/*}" ]]; then
61+
echo "pyenv-virtualenv: \`${PREFIX}' is a symlink for unknown location." 1>&2
62+
exit 1
63+
fi
64+
else
65+
if pyenv-virtualenv-prefix "${VERSION_NAME}" 1>/dev/null 2>&1; then
66+
PREFIX="${PYENV_ROOT}/versions/${VERSION_NAME}"
67+
unset COMPAT_PREFIX
68+
else
69+
echo "pyenv-virtualenv: \`${DEFINITION}' is not a virtualenv." 1>&2
70+
exit 1
71+
fi
72+
fi
73+
fi
74+
75+
if [ -z "$FORCE" ]; then
76+
if [ ! -d "$PREFIX" ]; then
77+
echo "pyenv-virtualenv: virtualenv \`$VERSION_NAME' not installed" >&2
78+
exit 1
79+
fi
80+
81+
read -p "pyenv-virtualenv: remove $PREFIX? "
82+
case "$REPLY" in
83+
y* | Y* ) ;;
84+
* ) exit 1 ;;
85+
esac
86+
fi
87+
88+
if [ -d "$PREFIX" ]; then
89+
rm -rf "$PREFIX"
90+
if [ -L "$COMPAT_PREFIX" ]; then
91+
rm -rf "$COMPAT_PREFIX"
92+
fi
93+
pyenv-rehash
94+
fi

etc/pyenv.d/rehash/envs.bash

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
virtualenv_list_executable_names() {
2+
local file
3+
shopt -s nullglob
4+
for file in "$PYENV_ROOT"/versions/*/envs/*/bin/*; do
5+
echo "${file##*/}"
6+
done
7+
shopt -u nullglob
8+
}
9+
if declare -f make_shims 1>/dev/null 2>&1; then
10+
make_shims $(virtualenv_list_executable_names | sort -u)
11+
fi

etc/pyenv.d/uninstall/envs.bash

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
resolve_link() {
2+
$(type -p greadlink readlink | head -1) "$1"
3+
}
4+
5+
if [ -n "${DEFINITION}" ]; then
6+
if [[ "${DEFINITION}" != "${DEFINITION%/envs/*}" ]]; then
7+
exec pyenv-virtualenv-delete ${FORCE+-f} "${DEFINITION}"
8+
exit 128
9+
else
10+
VERSION_NAME="${VERSION_NAME:-${DEFINITION##*/}}"
11+
PREFIX="${PREFIX:-${PYENV_ROOT}/versions/${VERSION_NAME}}"
12+
if [ -L "${PREFIX}" ]; then
13+
REAL_PREFIX="$(resolve_link "${PREFIX}" 2>/dev/null || true)"
14+
REAL_DEFINITION="${REAL_PREFIX#${PYENV_ROOT}/versions/}"
15+
if [[ "${REAL_DEFINITION}" != "${REAL_DEFINITION%/envs/*}" ]]; then
16+
exec pyenv-virtualenv-delete ${FORCE+-f} "${REAL_DEFINITION}"
17+
exit 128
18+
fi
19+
fi
20+
fi
21+
fi

test/delete.bats

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
#!/usr/bin/env bats
2+
3+
load test_helper
4+
5+
setup() {
6+
export PYENV_ROOT="${TMP}/pyenv"
7+
}
8+
9+
@test "delete virtualenv" {
10+
mkdir -p "${PYENV_ROOT}/versions/venv27"
11+
12+
stub pyenv-virtualenv-prefix "venv27 : true"
13+
stub pyenv-rehash "true"
14+
15+
run pyenv-virtualenv-delete -f "venv27"
16+
17+
assert_success
18+
19+
unstub pyenv-virtualenv-prefix
20+
unstub pyenv-rehash
21+
22+
[ ! -d "${PYENV_ROOT}/versions/venv27" ]
23+
}
24+
25+
@test "delete virtualenv by symlink" {
26+
mkdir -p "${PYENV_ROOT}/versions/2.7.10/envs/venv27"
27+
ln -fs "${PYENV_ROOT}/versions/2.7.10/envs/venv27" "${PYENV_ROOT}/versions/venv27"
28+
29+
stub pyenv-rehash "true"
30+
31+
run pyenv-virtualenv-delete -f "venv27"
32+
33+
assert_success
34+
35+
unstub pyenv-rehash
36+
37+
[ ! -d "${PYENV_ROOT}/versions/2.7.10/envs/venv27" ]
38+
[ ! -L "${PYENV_ROOT}/versions/venv27" ]
39+
}
40+
41+
@test "delete virtualenv with symlink" {
42+
mkdir -p "${PYENV_ROOT}/versions/2.7.10/envs/venv27"
43+
ln -fs "${PYENV_ROOT}/versions/2.7.10/envs/venv27" "${PYENV_ROOT}/versions/venv27"
44+
45+
stub pyenv-rehash "true"
46+
47+
run pyenv-virtualenv-delete -f "2.7.10/envs/venv27"
48+
49+
assert_success
50+
51+
unstub pyenv-rehash
52+
53+
[ ! -d "${PYENV_ROOT}/versions/2.7.10/envs/venv27" ]
54+
[ ! -L "${PYENV_ROOT}/versions/venv27" ]
55+
}
56+
57+
@test "not delete virtualenv with same name" {
58+
mkdir -p "${PYENV_ROOT}/versions/2.7.10/envs/venv27"
59+
mkdir -p "${PYENV_ROOT}/versions/venv27"
60+
61+
stub pyenv-rehash "true"
62+
63+
run pyenv-virtualenv-delete -f "2.7.10/envs/venv27"
64+
65+
assert_success
66+
67+
unstub pyenv-rehash
68+
69+
[ ! -d "${PYENV_ROOT}/versions/2.7.10/envs/venv27" ]
70+
[ -d "${PYENV_ROOT}/versions/venv27" ]
71+
}

0 commit comments

Comments
 (0)