mirror of
https://github.com/pyenv/pyenv.git
synced 2024-11-21 20:47:00 -05:00
Allow multiple versions for pyenv-install
This commit is contained in:
parent
ff93c58bab
commit
31f372034d
2 changed files with 202 additions and 146 deletions
|
@ -2,7 +2,7 @@
|
||||||
#
|
#
|
||||||
# Summary: Install a Python version using python-build
|
# Summary: Install a Python version using python-build
|
||||||
#
|
#
|
||||||
# Usage: pyenv install [-f] [-kvp] <version>
|
# Usage: pyenv install [-f] [-kvp] <version>...
|
||||||
# pyenv install [-f] [-kvp] <definition-file>
|
# pyenv install [-f] [-kvp] <definition-file>
|
||||||
# pyenv install -l|--list
|
# pyenv install -l|--list
|
||||||
# pyenv install --version
|
# pyenv install --version
|
||||||
|
@ -113,17 +113,15 @@ for option in "${OPTIONS[@]}"; do
|
||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
|
|
||||||
[ "${#ARGUMENTS[@]}" -le 1 ] || usage 1 >&2
|
|
||||||
|
|
||||||
unset VERSION_NAME
|
unset VERSION_NAME
|
||||||
|
|
||||||
# The first argument contains the definition to install. If the
|
# The first argument contains the definition to install. If the
|
||||||
# argument is missing, try to install whatever local app-specific
|
# argument is missing, try to install whatever local app-specific
|
||||||
# version is specified by pyenv. Show usage instructions if a local
|
# version is specified by pyenv. Show usage instructions if a local
|
||||||
# version is not specified.
|
# version is not specified.
|
||||||
DEFINITION="${ARGUMENTS[0]}"
|
DEFINITIONS=("${ARGUMENTS[@]}")
|
||||||
[ -n "$DEFINITION" ] || DEFINITION="$(pyenv-local 2>/dev/null || true)"
|
[ -n "${DEFINITIONS[*]}" ] || DEFINITIONS=($(pyenv-local 2>/dev/null || true))
|
||||||
[ -n "$DEFINITION" ] || usage 1 >&2
|
[ -n "${DEFINITIONS[*]}" ] || usage 1 >&2
|
||||||
|
|
||||||
# Define `before_install` and `after_install` functions that allow
|
# Define `before_install` and `after_install` functions that allow
|
||||||
# plugin hooks to register a string of code for execution before or
|
# plugin hooks to register a string of code for execution before or
|
||||||
|
@ -140,27 +138,35 @@ after_install() {
|
||||||
after_hooks["${#after_hooks[@]}"]="$hook"
|
after_hooks["${#after_hooks[@]}"]="$hook"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Plan cleanup on unsuccessful installation.
|
||||||
|
cleanup() {
|
||||||
|
[ -z "${PREFIX_EXISTS}" ] && rm -rf "$PREFIX"
|
||||||
|
}
|
||||||
|
|
||||||
|
trap cleanup SIGINT
|
||||||
|
|
||||||
|
|
||||||
OLDIFS="$IFS"
|
OLDIFS="$IFS"
|
||||||
IFS=$'\n' scripts=(`pyenv-hooks install`)
|
IFS=$'\n' scripts=(`pyenv-hooks install`)
|
||||||
IFS="$OLDIFS"
|
IFS="$OLDIFS"
|
||||||
for script in "${scripts[@]}"; do source "$script"; done
|
for script in "${scripts[@]}"; do source "$script"; done
|
||||||
|
|
||||||
# Try to resolve a prefix if user indeed gave a prefix.
|
for DEFINITION in "${DEFINITIONS[@]}";do
|
||||||
# We install the version under the resolved name
|
# Try to resolve a prefix if user indeed gave a prefix.
|
||||||
# and hooks also see the resolved name
|
# We install the version under the resolved name
|
||||||
DEFINITION="$(pyenv-latest -q -k "$DEFINITION" || echo "$DEFINITION")"
|
# and hooks also see the resolved name
|
||||||
|
DEFINITION="$(pyenv-latest -q -k "$DEFINITION" || echo "$DEFINITION")"
|
||||||
|
|
||||||
# Set VERSION_NAME from $DEFINITION, if it is not already set. Then
|
# Set VERSION_NAME from $DEFINITION. Then compute the installation prefix.
|
||||||
# compute the installation prefix.
|
VERSION_NAME="${DEFINITION##*/}"
|
||||||
[ -n "$VERSION_NAME" ] || VERSION_NAME="${DEFINITION##*/}"
|
[ -n "$DEBUG" ] && VERSION_NAME="${VERSION_NAME}-debug"
|
||||||
[ -n "$DEBUG" ] && VERSION_NAME="${VERSION_NAME}-debug"
|
PREFIX="${PYENV_ROOT}/versions/${VERSION_NAME}"
|
||||||
PREFIX="${PYENV_ROOT}/versions/${VERSION_NAME}"
|
|
||||||
|
|
||||||
[ -d "${PREFIX}" ] && PREFIX_EXISTS=1
|
[ -d "${PREFIX}" ] && PREFIX_EXISTS=1
|
||||||
|
|
||||||
# If the installation prefix exists, prompt for confirmation unless
|
# If the installation prefix exists, prompt for confirmation unless
|
||||||
# the --force option was specified.
|
# the --force option was specified.
|
||||||
if [ -d "${PREFIX}/bin" ]; then
|
if [ -d "${PREFIX}/bin" ]; then
|
||||||
if [ -z "$FORCE" ] && [ -z "$SKIP_EXISTING" ]; then
|
if [ -z "$FORCE" ] && [ -z "$SKIP_EXISTING" ]; then
|
||||||
echo "pyenv: $PREFIX already exists" >&2
|
echo "pyenv: $PREFIX already exists" >&2
|
||||||
read -p "continue with installation? (y/N) "
|
read -p "continue with installation? (y/N) "
|
||||||
|
@ -173,23 +179,23 @@ if [ -d "${PREFIX}/bin" ]; then
|
||||||
# Since we know the python version is already installed, and are opting to
|
# Since we know the python version is already installed, and are opting to
|
||||||
# not force installation of existing versions, we just `exit 0` here to
|
# not force installation of existing versions, we just `exit 0` here to
|
||||||
# leave things happy
|
# leave things happy
|
||||||
exit 0
|
continue
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
fi
|
|
||||||
|
|
||||||
# If PYENV_BUILD_ROOT is set, always pass keep options to python-build.
|
# If PYENV_BUILD_ROOT is set, always pass keep options to python-build.
|
||||||
if [ -n "${PYENV_BUILD_ROOT}" ]; then
|
if [ -n "${PYENV_BUILD_ROOT}" ]; then
|
||||||
export PYTHON_BUILD_BUILD_PATH="${PYENV_BUILD_ROOT}/${VERSION_NAME}"
|
export PYTHON_BUILD_BUILD_PATH="${PYENV_BUILD_ROOT}/${VERSION_NAME}"
|
||||||
KEEP="-k"
|
KEEP="-k"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Set PYTHON_BUILD_CACHE_PATH to $PYENV_ROOT/cache, if the directory
|
# Set PYTHON_BUILD_CACHE_PATH to $PYENV_ROOT/cache, if the directory
|
||||||
# exists and the variable is not already set.
|
# exists and the variable is not already set.
|
||||||
if [ -z "${PYTHON_BUILD_CACHE_PATH}" ] && [ -d "${PYENV_ROOT}/cache" ]; then
|
if [ -z "${PYTHON_BUILD_CACHE_PATH}" ] && [ -d "${PYENV_ROOT}/cache" ]; then
|
||||||
export PYTHON_BUILD_CACHE_PATH="${PYENV_ROOT}/cache"
|
export PYTHON_BUILD_CACHE_PATH="${PYENV_ROOT}/cache"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -z "${PYENV_BOOTSTRAP_VERSION}" ]; then
|
if [ -z "${PYENV_BOOTSTRAP_VERSION}" ]; then
|
||||||
case "${VERSION_NAME}" in
|
case "${VERSION_NAME}" in
|
||||||
[23]"."* )
|
[23]"."* )
|
||||||
# Default PYENV_VERSION to the friendly Python version. (The
|
# Default PYENV_VERSION to the friendly Python version. (The
|
||||||
|
@ -231,28 +237,21 @@ if [ -z "${PYENV_BOOTSTRAP_VERSION}" ]; then
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -n "${PYENV_BOOTSTRAP_VERSION}" ]; then
|
if [ -n "${PYENV_BOOTSTRAP_VERSION}" ]; then
|
||||||
export PYENV_VERSION="${PYENV_BOOTSTRAP_VERSION}"
|
export PYENV_VERSION="${PYENV_BOOTSTRAP_VERSION}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Execute `before_install` hooks.
|
# Execute `before_install` hooks.
|
||||||
for hook in "${before_hooks[@]}"; do eval "$hook"; done
|
for hook in "${before_hooks[@]}"; do eval "$hook"; done
|
||||||
|
|
||||||
# Plan cleanup on unsuccessful installation.
|
# Invoke `python-build` and record the exit status in $STATUS.
|
||||||
cleanup() {
|
STATUS=0
|
||||||
[ -z "${PREFIX_EXISTS}" ] && rm -rf "$PREFIX"
|
python-build $KEEP $VERBOSE $HAS_PATCH $DEBUG "$DEFINITION" "$PREFIX" || STATUS="$?"
|
||||||
}
|
|
||||||
|
|
||||||
trap cleanup SIGINT
|
# Display a more helpful message if the definition wasn't found.
|
||||||
|
if [ "$STATUS" == "2" ]; then
|
||||||
# Invoke `python-build` and record the exit status in $STATUS.
|
|
||||||
STATUS=0
|
|
||||||
python-build $KEEP $VERBOSE $HAS_PATCH $DEBUG "$DEFINITION" "$PREFIX" || STATUS="$?"
|
|
||||||
|
|
||||||
# Display a more helpful message if the definition wasn't found.
|
|
||||||
if [ "$STATUS" == "2" ]; then
|
|
||||||
{ candidates="$(definitions "$DEFINITION")"
|
{ candidates="$(definitions "$DEFINITION")"
|
||||||
here="$(dirname "${0%/*}")/../.."
|
here="$(dirname "${0%/*}")/../.."
|
||||||
if [ -n "$candidates" ]; then
|
if [ -n "$candidates" ]; then
|
||||||
|
@ -274,16 +273,19 @@ if [ "$STATUS" == "2" ]; then
|
||||||
printf ".\n"
|
printf ".\n"
|
||||||
fi
|
fi
|
||||||
} >&2
|
} >&2
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Execute `after_install` hooks.
|
# Execute `after_install` hooks.
|
||||||
for hook in "${after_hooks[@]}"; do eval "$hook"; done
|
for hook in "${after_hooks[@]}"; do eval "$hook"; done
|
||||||
|
|
||||||
# Run `pyenv-rehash` after a successful installation.
|
# Run `pyenv-rehash` after a successful installation.
|
||||||
if [ "$STATUS" == "0" ]; then
|
if [ "$STATUS" == "0" ]; then
|
||||||
pyenv-rehash
|
pyenv-rehash
|
||||||
else
|
else
|
||||||
|
break
|
||||||
cleanup
|
cleanup
|
||||||
fi
|
fi
|
||||||
|
|
||||||
exit "$STATUS"
|
done
|
||||||
|
|
||||||
|
exit "${STATUS:-0}"
|
||||||
|
|
|
@ -10,7 +10,7 @@ setup() {
|
||||||
|
|
||||||
stub_python_build() {
|
stub_python_build() {
|
||||||
stub python-build "--lib : $BATS_TEST_DIRNAME/../bin/python-build --lib" "$@"
|
stub python-build "--lib : $BATS_TEST_DIRNAME/../bin/python-build --lib" "$@"
|
||||||
stub pyenv-latest " : false"
|
stub pyenv-latest ": false"
|
||||||
}
|
}
|
||||||
|
|
||||||
@test "install proper" {
|
@test "install proper" {
|
||||||
|
@ -24,6 +24,26 @@ stub_python_build() {
|
||||||
unstub pyenv-rehash
|
unstub pyenv-rehash
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@test "install proper multi versions" {
|
||||||
|
#stub python-build "--lib : $BATS_TEST_DIRNAME/../bin/python-build --lib" 'echo python-build "$@"' 'echo python-build "$@"'
|
||||||
|
#stub pyenv-latest ": false" ": false"
|
||||||
|
stub_python_build 'echo python-build "$@"' 'echo python-build "$@"'
|
||||||
|
stub pyenv-latest ": false"
|
||||||
|
stub pyenv-rehash 'true'
|
||||||
|
|
||||||
|
run pyenv-install 3.4.1 3.4.2
|
||||||
|
assert_success
|
||||||
|
assert_output <<OUT
|
||||||
|
python-build 3.4.1 ${TMP}/pyenv/versions/3.4.1
|
||||||
|
python-build 3.4.2 ${TMP}/pyenv/versions/3.4.2
|
||||||
|
OUT
|
||||||
|
|
||||||
|
unstub python-build
|
||||||
|
unstub pyenv-latest
|
||||||
|
unstub pyenv-hooks
|
||||||
|
unstub pyenv-rehash
|
||||||
|
}
|
||||||
|
|
||||||
@test "install resolves a prefix" {
|
@test "install resolves a prefix" {
|
||||||
stub_python_build 'echo python-build "$@"'
|
stub_python_build 'echo python-build "$@"'
|
||||||
stub pyenv-latest '-q -k 3.4 : echo 3.4.2'
|
stub pyenv-latest '-q -k 3.4 : echo 3.4.2'
|
||||||
|
@ -37,6 +57,24 @@ stub_python_build() {
|
||||||
unstub pyenv-rehash
|
unstub pyenv-rehash
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@test "install resolves a prefix with multi versions" {
|
||||||
|
stub_python_build 'echo python-build "$@"' 'echo python-build "$@"'
|
||||||
|
stub pyenv-latest '-q -k 3.4 : echo 3.4.2' '-q -k 3.5 : echo 3.5.2'
|
||||||
|
stub pyenv-rehash 'true'
|
||||||
|
pyenv-latest || true # pass through the stub entry added by stub_python_build
|
||||||
|
|
||||||
|
run pyenv-install 3.4 3.5
|
||||||
|
assert_success <<OUT
|
||||||
|
python-build 3.4.2 ${PYENV_ROOT}/versions/3.4.2
|
||||||
|
python-build 3.5.2 ${PYENV_ROOT}/versions/3.5.2
|
||||||
|
OUT
|
||||||
|
|
||||||
|
|
||||||
|
unstub python-build
|
||||||
|
unstub pyenv-hooks
|
||||||
|
unstub pyenv-rehash
|
||||||
|
}
|
||||||
|
|
||||||
@test "install pyenv local version by default" {
|
@test "install pyenv local version by default" {
|
||||||
stub_python_build 'echo python-build "$1"'
|
stub_python_build 'echo python-build "$1"'
|
||||||
stub pyenv-local 'echo 3.4.2'
|
stub pyenv-local 'echo 3.4.2'
|
||||||
|
@ -48,6 +86,21 @@ stub_python_build() {
|
||||||
unstub pyenv-local
|
unstub pyenv-local
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@test "install pyenv local multi versions by default" {
|
||||||
|
stub_python_build 'echo python-build "$1"' 'echo python-build "$1"'
|
||||||
|
stub pyenv-local 'printf "%s\n%s\n" 3.4.2 3.4.1'
|
||||||
|
stub pyenv-latest ": false"
|
||||||
|
|
||||||
|
run pyenv-install
|
||||||
|
assert_success <<OUT
|
||||||
|
python-build 3.4.2"
|
||||||
|
python-build 3.4.1"
|
||||||
|
OUT
|
||||||
|
|
||||||
|
unstub python-build
|
||||||
|
unstub pyenv-local
|
||||||
|
}
|
||||||
|
|
||||||
@test "list available versions" {
|
@test "list available versions" {
|
||||||
stub_python_build \
|
stub_python_build \
|
||||||
"--definitions : echo 2.6.9 2.7.9-rc1 2.7.9-rc2 3.4.2 | tr ' ' $'\\n'"
|
"--definitions : echo 2.6.9 2.7.9-rc1 2.7.9-rc2 3.4.2 | tr ' ' $'\\n'"
|
||||||
|
@ -169,22 +222,23 @@ ${PYENV_ROOT}/plugins/foo/share/python-build
|
||||||
OUT
|
OUT
|
||||||
}
|
}
|
||||||
|
|
||||||
@test "not enough arguments for pyenv-install" {
|
@test "not enough arguments for pyenv-install if no local version" {
|
||||||
stub_python_build
|
stub_python_build
|
||||||
stub pyenv-help 'install : true'
|
stub pyenv-help 'install : true'
|
||||||
|
|
||||||
run pyenv-install
|
run pyenv-install
|
||||||
assert_failure
|
assert_failure
|
||||||
unstub pyenv-help
|
unstub pyenv-help
|
||||||
|
assert_output ""
|
||||||
}
|
}
|
||||||
|
|
||||||
@test "too many arguments for pyenv-install" {
|
@test "multi arguments for pyenv-install" {
|
||||||
stub_python_build
|
stub_python_build
|
||||||
stub pyenv-help 'install : true'
|
stub pyenv-help 'install : true'
|
||||||
|
|
||||||
run pyenv-install 3.4.1 3.4.2
|
run pyenv-install 3.4.1 3.4.2
|
||||||
assert_failure
|
assert_success
|
||||||
unstub pyenv-help
|
assert_output ""
|
||||||
}
|
}
|
||||||
|
|
||||||
@test "show help for pyenv-install" {
|
@test "show help for pyenv-install" {
|
||||||
|
|
Loading…
Reference in a new issue