- #!/usr/bin/env bash
- #
- # Summary: Install a Python version using the python-build plugin
- #
- # Usage: pyenv install [-f|--force] [-g|--debug] [-k|--keep] [-v|--verbose] <version>
- # pyenv install [-f|--force] [-g|--debug] [-k|--keep] [-v|--verbose] <definition-file>
- # pyenv install -l|--list
- #
- # -l/--list List all available versions
- # -f/--force Install even if the version appears to be installed already
- # -k/--keep Keep source tree in $PYENV_BUILD_ROOT after installation
- # (defaults to $PYENV_ROOT/sources)
- # -g/--debug Build a debug version
- # -v/--verbose Verbose mode: print compilation status to stdout
- #
- # For detailed information on installing Python versions with
- # python-build, including a list of environment variables for adjusting
- # compilation, see: https://github.com/yyuu/pyenv#readme
- #
- set -e
- [ -n "$PYENV_DEBUG" ] && set -x
-
- # Provide pyenv completions
- if [ "$1" = "--complete" ]; then
- exec python-build --definitions
- fi
-
- if [ -z "$PYENV_ROOT" ]; then
- PYENV_ROOT="${HOME}/.pyenv"
- fi
-
- # Load shared library functions
- eval "$(python-build --lib)"
-
- usage() {
- # We can remove the sed fallback once pyenv 0.4.0 is widely available.
- pyenv-help install 2>/dev/null || sed -ne '/^#/!q;s/.//;s/.//;1,4d;p' < "$0"
- [ -z "$1" ] || exit "$1"
- }
-
- definitions() {
- local query="$1"
- python-build --definitions | grep -F "$query" || true
- }
-
- indent() {
- sed 's/^/ /'
- }
-
- unset FORCE
- unset KEEP
- unset VERBOSE
- unset DEBUG
-
- parse_options "$@"
- for option in "${OPTIONS[@]}"; do
- case "$option" in
- "h" | "help" )
- usage 0
- ;;
- "l" | "list" )
- echo "Available versions:"
- definitions | indent
- exit
- ;;
- "f" | "force" )
- FORCE=true
- ;;
- "k" | "keep" )
- [ -n "${PYENV_BUILD_ROOT}" ] || PYENV_BUILD_ROOT="${PYENV_ROOT}/sources"
- ;;
- "v" | "verbose" )
- VERBOSE="-v"
- ;;
- "g" | "debug" )
- DEBUG="-g"
- ;;
- "version" )
- exec python-build --version
- ;;
- * )
- usage 1
- ;;
- esac
- done
-
- unset VERSION_NAME
-
- # The first argument contains the definition to install. If the
- # argument is missing, try to install whatever local app-specific
- # version is specified by pyenv. Show usage instructions if a local
- # version is not specified.
- DEFINITION="${ARGUMENTS[0]}"
- [ -n "$DEFINITION" ] || DEFINITION="$(pyenv local 2>/dev/null || true)"
- [ -n "$DEFINITION" ] || usage 1
-
-
- # Define `before_install` and `after_install` functions that allow
- # plugin hooks to register a string of code for execution before or
- # after the installation process.
- declare -a before_hooks after_hooks
-
- before_install() {
- local hook="$1"
- before_hooks["${#before_hooks[@]}"]="$hook"
- }
-
- after_install() {
- local hook="$1"
- after_hooks["${#after_hooks[@]}"]="$hook"
- }
-
- # Load plugin hooks.
- for script in $(pyenv-hooks install); do
- source "$script"
- done
-
-
- # Set VERSION_NAME from $DEFINITION, if it is not already set. Then
- # compute the installation prefix.
- [ -n "$VERSION_NAME" ] || VERSION_NAME="${DEFINITION##*/}"
- [ -n "$DEBUG" ] && VERSION_NAME="${VERSION_NAME}-debug"
- PREFIX="${PYENV_ROOT}/versions/${VERSION_NAME}"
-
- [ -d "${PREFIX}" ] && PREFIX_EXISTS=1
-
- # If the installation prefix exists, prompt for confirmation unless
- # the --force option was specified.
- if [ -z "$FORCE" ] && [ -d "${PREFIX}/bin" ]; then
- echo "pyenv: $PREFIX already exists" >&2
- read -p "continue with installation? (y/N) "
-
- case "$REPLY" in
- y* | Y* ) ;;
- * ) exit 1 ;;
- esac
- fi
-
- # If PYENV_BUILD_ROOT is set, always pass keep options to python-build.
- if [ -n "${PYENV_BUILD_ROOT}" ]; then
- export PYTHON_BUILD_BUILD_PATH="${PYENV_BUILD_ROOT}/${VERSION_NAME}"
- KEEP="-k"
- fi
-
- # Set PYTHON_BUILD_CACHE_PATH to $PYENV_ROOT/cache, if the directory
- # exists and the variable is not already set.
- if [ -z "${PYTHON_BUILD_CACHE_PATH}" ] && [ -d "${PYENV_ROOT}/cache" ]; then
- export PYTHON_BUILD_CACHE_PATH="${PYENV_ROOT}/cache"
- fi
-
- # Default PYENV_VERSION to the globally-specified Python version. (The
- # CPython installer requires an existing Python installation to run. An
- # unsatisfied local .python-version file can cause the installer to
- # fail.)
- #export PYENV_VERSION="$(pyenv global 2>/dev/null || true)"
-
-
- # Execute `before_install` hooks.
- for hook in "${before_hooks[@]}"; do eval "$hook"; done
-
- # Plan cleanup on unsuccessful installation.
- cleanup() {
- [ -z "${PREFIX_EXISTS}" ] && rm -rf "$PREFIX"
- }
-
- trap cleanup SIGINT
-
- # Invoke `python-build` and record the exit status in $STATUS.
- STATUS=0
- python-build $KEEP $VERBOSE $DEBUG "$DEFINITION" "$PREFIX" || STATUS="$?"
-
- # Display a more helpful message if the definition wasn't found.
- if [ "$STATUS" == "2" ]; then
- { candidates="$(definitions "$DEFINITION")"
- if [ -n "$candidates" ]; then
- echo
- echo "The following versions contain \`$DEFINITION' in the name:"
- echo "$candidates" | indent
- fi
- echo
- echo "You can list all available versions with \`pyenv install --list'."
- echo
- echo "If the version you're looking for is not present, first try upgrading"
- echo "pyenv. If it's still missing, open a request on the pyenv"
- echo "issue tracker: https://github.com/yyuu/pyenv/issues"
- } >&2
- fi
-
- # Execute `after_install` hooks.
- for hook in "${after_hooks[@]}"; do eval "$hook"; done
-
- # Run `pyenv-rehash` after a successful installation.
- if [ "$STATUS" == "0" ]; then
- pyenv rehash
- else
- cleanup
- fi
-
- exit "$STATUS"
|