mirror of
https://github.com/rbenv/ruby-build.git
synced 2026-05-15 16:56:54 -04:00
When requested via `-h|--help`, usage text should be displayed on stdout and the exit status should be 0. When usage text is shown due to invalid arguments, it should be printed to stderr and exit status should be 1.
231 lines
6.2 KiB
Bash
Executable file
231 lines
6.2 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
#
|
|
# Summary: Install a Ruby version using ruby-build
|
|
#
|
|
# Usage: rbenv install [-f] [-kvp] <version>
|
|
# rbenv install [-f] [-kvp] <definition-file>
|
|
# rbenv install -l|--list
|
|
#
|
|
# -l/--list List all available versions
|
|
# -f/--force Install even if the version appears to be installed already
|
|
# -s/--skip-existing Skip if the version appears to be installed already
|
|
#
|
|
# ruby-build options:
|
|
#
|
|
# -k/--keep Keep source tree in $RBENV_BUILD_ROOT after installation
|
|
# (defaults to $RBENV_ROOT/sources)
|
|
# -v/--verbose Verbose mode: print compilation status to stdout
|
|
# -p/--patch Apply a patch from stdin before building
|
|
#
|
|
# For detailed information on installing Ruby versions with
|
|
# ruby-build, including a list of environment variables for adjusting
|
|
# compilation, see: https://github.com/sstephenson/ruby-build#usage
|
|
#
|
|
set -e
|
|
[ -n "$RBENV_DEBUG" ] && set -x
|
|
|
|
if [ -z "$RBENV_ROOT" ]; then
|
|
RBENV_ROOT="${HOME}/.rbenv"
|
|
fi
|
|
|
|
# Add `share/ruby-build/` directory from each rbenv plugin to the list of
|
|
# paths where build definitions are looked up.
|
|
shopt -s nullglob
|
|
for plugin_path in "$RBENV_ROOT"/plugins/*/share/ruby-build; do
|
|
RUBY_BUILD_DEFINITIONS="${RUBY_BUILD_DEFINITIONS}:${plugin_path}"
|
|
done
|
|
export RUBY_BUILD_DEFINITIONS
|
|
shopt -u nullglob
|
|
|
|
# Provide rbenv completions
|
|
if [ "$1" = "--complete" ]; then
|
|
exec ruby-build --definitions
|
|
fi
|
|
|
|
# Load shared library functions
|
|
eval "$(ruby-build --lib)"
|
|
|
|
usage() {
|
|
# We can remove the sed fallback once rbenv 0.4.0 is widely available.
|
|
rbenv-help install 2>/dev/null || sed -ne '/^#/!q;s/.//;s/.//;1,4d;p' < "$0"
|
|
[ -z "$1" ] || exit "$1"
|
|
}
|
|
|
|
definitions() {
|
|
local query="$1"
|
|
ruby-build --definitions | $(type -p ggrep grep | head -1) -F "$query" || true
|
|
}
|
|
|
|
indent() {
|
|
sed 's/^/ /'
|
|
}
|
|
|
|
unset FORCE
|
|
unset SKIP_EXISTING
|
|
unset KEEP
|
|
unset VERBOSE
|
|
unset HAS_PATCH
|
|
|
|
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
|
|
;;
|
|
"s" | "skip-existing" )
|
|
SKIP_EXISTING=true
|
|
;;
|
|
"k" | "keep" )
|
|
[ -n "${RBENV_BUILD_ROOT}" ] || RBENV_BUILD_ROOT="${RBENV_ROOT}/sources"
|
|
;;
|
|
"v" | "verbose" )
|
|
VERBOSE="-v"
|
|
;;
|
|
"p" | "patch" )
|
|
HAS_PATCH="-p"
|
|
;;
|
|
"version" )
|
|
exec ruby-build --version
|
|
;;
|
|
* )
|
|
usage 1 >&2
|
|
;;
|
|
esac
|
|
done
|
|
|
|
[ "${#ARGUMENTS[@]}" -le 1 ] || usage 1 >&2
|
|
|
|
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 rbenv. Show usage instructions if a local
|
|
# version is not specified.
|
|
DEFINITION="${ARGUMENTS[0]}"
|
|
[ -n "$DEFINITION" ] || DEFINITION="$(rbenv-local 2>/dev/null || true)"
|
|
[ -n "$DEFINITION" ] || usage 1 >&2
|
|
|
|
# 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"
|
|
}
|
|
|
|
OLDIFS="$IFS"
|
|
IFS=$'\n' scripts=(`rbenv-hooks install`)
|
|
IFS="$OLDIFS"
|
|
for script in "${scripts[@]}"; 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##*/}"
|
|
PREFIX="${RBENV_ROOT}/versions/${VERSION_NAME}"
|
|
|
|
[ -d "${PREFIX}" ] && PREFIX_EXISTS=1
|
|
|
|
# If the installation prefix exists, prompt for confirmation unless
|
|
# the --force option was specified.
|
|
if [ -d "${PREFIX}/bin" ]; then
|
|
if [ -z "$FORCE" ] && [ -z "$SKIP_EXISTING" ]; then
|
|
echo "rbenv: $PREFIX already exists" >&2
|
|
read -p "continue with installation? (y/N) "
|
|
|
|
case "$REPLY" in
|
|
y* | Y* ) ;;
|
|
* ) exit 1 ;;
|
|
esac
|
|
elif [ -n "$SKIP_EXISTING" ]; then
|
|
# Since we know the ruby version is already installed, and are opting to
|
|
# not force installation of existing versions, we just `exit 0` here to
|
|
# leave things happy
|
|
exit 0
|
|
fi
|
|
fi
|
|
|
|
# If RBENV_BUILD_ROOT is set, always pass keep options to ruby-build.
|
|
if [ -n "${RBENV_BUILD_ROOT}" ]; then
|
|
export RUBY_BUILD_BUILD_PATH="${RBENV_BUILD_ROOT}/${VERSION_NAME}"
|
|
KEEP="-k"
|
|
fi
|
|
|
|
# Set RUBY_BUILD_CACHE_PATH to $RBENV_ROOT/cache, if the directory
|
|
# exists and the variable is not already set.
|
|
if [ -z "${RUBY_BUILD_CACHE_PATH}" ] && [ -d "${RBENV_ROOT}/cache" ]; then
|
|
export RUBY_BUILD_CACHE_PATH="${RBENV_ROOT}/cache"
|
|
fi
|
|
|
|
# Default RBENV_VERSION to the globally-specified Ruby version. (The
|
|
# REE installer requires an existing Ruby installation to run. An
|
|
# unsatisfied local .ruby-version file can cause the installer to
|
|
# fail.)
|
|
export RBENV_VERSION="$(rbenv-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 `ruby-build` and record the exit status in $STATUS.
|
|
STATUS=0
|
|
ruby-build $KEEP $VERBOSE $HAS_PATCH "$DEFINITION" "$PREFIX" || STATUS="$?"
|
|
|
|
# Display a more helpful message if the definition wasn't found.
|
|
if [ "$STATUS" == "2" ]; then
|
|
{ candidates="$(definitions "$DEFINITION")"
|
|
here="$(dirname "${0%/*}")"
|
|
if [ -n "$candidates" ]; then
|
|
echo
|
|
echo "The following versions contain \`$DEFINITION' in the name:"
|
|
echo "$candidates" | indent
|
|
fi
|
|
echo
|
|
echo "See all available versions with \`rbenv install --list'."
|
|
echo
|
|
echo -n "If the version you need is missing, try upgrading ruby-build"
|
|
if [ "$here" != "${here#$(brew --prefix 2>/dev/null)}" ]; then
|
|
printf ":\n\n"
|
|
echo " brew update && brew upgrade ruby-build"
|
|
elif [ -d "${here}/.git" ]; then
|
|
printf ":\n\n"
|
|
echo " cd ${here} && git pull"
|
|
else
|
|
printf ".\n"
|
|
fi
|
|
} >&2
|
|
fi
|
|
|
|
# Execute `after_install` hooks.
|
|
for hook in "${after_hooks[@]}"; do eval "$hook"; done
|
|
|
|
# Run `rbenv-rehash` after a successful installation.
|
|
if [ "$STATUS" == "0" ]; then
|
|
rbenv-rehash
|
|
else
|
|
cleanup
|
|
fi
|
|
|
|
exit "$STATUS"
|