#!/bin/sh
# Copyright (c) 2016-2018 Mark Allen
# Copyright (c) 2011, 2012 Spawngrid, Inc
# Copyright (c) 2011 Evax Software <contact(at)evax(dot)org>
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
unset ERL_TOP
# Make sure CDPATH doesn't affect cd in case path is relative.
unset CDPATH
KERL_VERSION='1.8.3'
DOCSH_GITHUB_URL='https://github.com/erszcz/docsh.git'
ERLANG_DOWNLOAD_URL='https://www.erlang.org/download'
KERL_CONFIG_STORAGE_FILENAME='.kerl_config'
if [ -z "$HOME" ]; then
# shellcheck disable=SC2016
echo 'Error: $HOME is empty or not set.' 1>&2
exit 1
fi
# Default values
OTP_GITHUB_URL=${OTP_GITHUB_URL:='https://github.com/erlang/otp'}
KERL_BASE_DIR=${KERL_BASE_DIR:="$HOME"/.kerl}
KERL_CONFIG=${KERL_CONFIG:="$HOME"/.kerlrc}
KERL_DOWNLOAD_DIR=${KERL_DOWNLOAD_DIR:="${KERL_BASE_DIR:?}"/archives}
KERL_BUILD_DIR=${KERL_BUILD_DIR:="${KERL_BASE_DIR:?}"/builds}
KERL_GIT_DIR=${KERL_GIT_DIR:="${KERL_BASE_DIR:?}"/gits}
if [ -n "$OTP_GITHUB_URL" ]; then
_OGU="$OTP_GITHUB_URL"
fi
if [ -n "$KERL_CONFIGURE_OPTIONS" ]; then
_KCO="$KERL_CONFIGURE_OPTIONS"
fi
if [ -n "$KERL_CONFIGURE_APPLICATIONS" ]; then
_KCA="$KERL_CONFIGURE_APPLICATIONS"
fi
if [ -n "$KERL_CONFIGURE_DISABLE_APPLICATIONS" ]; then
_KCDA="$KERL_CONFIGURE_DISABLE_APPLICATIONS"
fi
if [ -n "$KERL_SASL_STARTUP" ]; then
_KSS="$KERL_SASL_STARTUP"
fi
if [ -n "$KERL_DEPLOY_SSH_OPTIONS" ]; then
_KDSSH="$KERL_DEPLOY_SSH_OPTIONS"
fi
if [ -n "$KERL_DEPLOY_RSYNC_OPTIONS" ]; then
_KDRSYNC="$KERL_DEPLOY_RSYNC_OPTIONS"
fi
if [ -n "$KERL_INSTALL_MANPAGES" ]; then
_KIM="$KERL_INSTALL_MANPAGES"
fi
if [ -n "$KERL_INSTALL_HTMLDOCS" ]; then
_KIHD="$KERL_INSTALL_HTMLDOCS"
fi
if [ -n "$KERL_BUILD_PLT" ]; then
_KBPLT="$KERL_BUILD_PLT"
fi
if [ -n "$KERL_BUILD_DOCS" ]; then
_KBD="$KERL_BUILD_DOCS"
fi
if [ -n "$KERL_BUILD_BACKEND" ]; then
_KBB="$KERL_BUILD_BACKEND"
fi
OTP_GITHUB_URL=
KERL_CONFIGURE_OPTIONS=
KERL_CONFIGURE_APPLICATIONS=
KERL_CONFIGURE_DISABLE_APPLICATIONS=
KERL_SASL_STARTUP=
KERL_DEPLOY_SSH_OPTIONS=
KERL_DEPLOY_RSYNC_OPTIONS=
KERL_INSTALL_MANPAGES=
KERL_INSTALL_HTMLDOCS=
KERL_BUILD_PLT=
KERL_BUILD_DOCS=
KERL_BUILD_BACKEND=
# ensure the base dir exists
mkdir -p "$KERL_BASE_DIR" || exit 1
# source the config file if available
if [ -f "$KERL_CONFIG" ]; then
# shellcheck source=/dev/null
. "$KERL_CONFIG"
fi
if [ -n "$_OGU" ]; then
OTP_GITHUB_URL="$_OGU"
fi
if [ -n "$_KCO" ]; then
KERL_CONFIGURE_OPTIONS="$_KCO"
fi
if [ -n "$_KCA" ]; then
KERL_CONFIGURE_APPLICATIONS="$_KCA"
fi
if [ -n "$_KCDA" ]; then
KERL_CONFIGURE_DISABLE_APPLICATIONS="$_KCDA"
fi
if [ -n "$_KSS" ]; then
KERL_SASL_STARTUP="$_KSS"
fi
if [ -n "$_KDSSH" ]; then
KERL_DEPLOY_SSH_OPTIONS="$_KDSSH"
fi
if [ -n "$_KDRSYNC" ]; then
KERL_DEPLOY_RSYNC_OPTIONS="$_KDRSYNC"
fi
if [ -n "$_KIM" ]; then
KERL_INSTALL_MANPAGES="$_KIM"
fi
if [ -n "$_KIHD" ]; then
KERL_INSTALL_HTMLDOCS="$_KIHD"
fi
if [ -n "$_KBPLT" ]; then
KERL_BUILD_PLT="$_KBPLT"
fi
if [ -n "$_KBD" ]; then
KERL_BUILD_DOCS="$_KBD"
fi
if [ -n "$_KBB" ]; then
KERL_BUILD_BACKEND="$_KBB"
fi
if [ -z "$KERL_SASL_STARTUP" ]; then
INSTALL_OPT='-minimal'
else
INSTALL_OPT='-sasl'
fi
if [ -z "$KERL_BUILD_BACKEND" ]; then
KERL_BUILD_BACKEND='tarball'
else
KERL_BUILD_BACKEND='git'
KERL_USE_AUTOCONF=1
fi
KERL_SYSTEM=$(uname -s)
case "$KERL_SYSTEM" in
Darwin|FreeBSD|OpenBSD)
MD5SUM='openssl md5'
MD5SUM_FIELD=2
SED_OPT=-E
CP_OPT=-a
;;
*)
MD5SUM=md5sum
MD5SUM_FIELD=1
SED_OPT=-r
CP_OPT=-pr
;;
esac
usage() {
echo 'kerl: build and install Erlang/OTP'
echo "usage: $0 <command> [options ...]"
printf '\n <command> Command to be executed\n\n'
echo 'Valid commands are:'
echo ' build Build specified release or git repository'
echo ' install Install the specified release at the given location'
echo ' deploy Deploy the specified installation to the given host and location'
echo ' update Update the list of available releases from your source provider'
echo ' list List releases, builds and installations'
echo ' delete Delete builds and installations'
echo ' install-docsh Install erl shell documentation access extension - docsh'
echo ' path Print the path of a given installation'
echo ' active Print the path of the active installation'
echo ' plt Print Dialyzer PLT path for the active installation'
echo ' status Print available builds and installations'
echo ' prompt Print a string suitable for insertion in prompt'
echo ' cleanup Remove compilation artifacts (use after installation)'
echo " version Print current version (current: $KERL_VERSION)"
exit 1
}
if [ $# -eq 0 ]; then usage; fi
get_releases() {
if [ "$KERL_BUILD_BACKEND" = 'git' ]; then
get_git_releases
else
get_tarball_releases
fi
}
get_git_releases() {
git ls-remote --tags "$OTP_GITHUB_URL" \
| grep -E -o 'OTP[_-][^^{}]+' \
| sed $SED_OPT 's/OTP[_-]//' \
| sort -n \
| uniq
}
get_tarball_releases() {
tmp="$(mktemp /tmp/kerl.XXXXXX)"
if [ 200 = "$(curl -qsL --output "$tmp" --write-out '%{http_code}' $ERLANG_DOWNLOAD_URL/)" ]; then
sed $SED_OPT \
-e 's/^.*<[aA] [hH][rR][eE][fF]=\"otp_src_([-0-9A-Za-z_.]+)\.tar\.gz\">.*$/\1/' \
-e '/^R1|^[0-9]/!d' "$tmp" \
| sed -e 's/^R\(.*\)/\1:R\1/' \
| sed -e 's/^\([^\:]*\)$/\1-z:\1/' \
| sort | cut -d: -f2
rm "$tmp"
return 0
fi
rm "$tmp"
exit 1
}
update_checksum_file() {
if [ "$KERL_BUILD_BACKEND" = 'git' ]; then
return 0
else
echo 'Getting checksum file from erlang.org...'
curl -f -L -o "$KERL_DOWNLOAD_DIR"/MD5 "$ERLANG_DOWNLOAD_URL"/MD5 || exit 1
fi
}
ensure_checksum_file() {
if [ ! -s "$KERL_DOWNLOAD_DIR"/MD5 ]; then
update_checksum_file
fi
}
check_releases() {
if [ ! -f "$KERL_BASE_DIR"/otp_releases ]; then
get_releases >"$KERL_BASE_DIR"/otp_releases
fi
}
is_valid_release() {
check_releases
while read -r rel; do
if [ "$1" = "$rel" ]; then
return 0
fi
done <"$KERL_BASE_DIR"/otp_releases
return 1
}
assert_valid_release() {
if ! is_valid_release "$1"; then
echo "$1 is not a valid Erlang/OTP release"
exit 1
fi
return 0
}
get_release_from_name() {
if [ -f "$KERL_BASE_DIR"/otp_builds ]; then
while read -r l; do
rel=$(echo "$l" | cut -d, -f1)
name=$(echo "$l" | cut -d, -f2)
if [ "$name" = "$1" ]; then
echo "$rel"
return 0
fi
done <"$KERL_BASE_DIR"/otp_builds
fi
return 1
}
get_newest_valid_release() {
check_releases
rel=$(tail -1 "$KERL_BASE_DIR"/otp_releases)
if [ ! -z "$rel" ]; then
echo "$rel"
return 0
fi
return 1
}
is_valid_installation() {
if [ -f "$KERL_BASE_DIR"/otp_installations ]; then
while read -r l; do
name=$(echo "$l" | cut -d' ' -f1)
path=$(echo "$l" | cut -d' ' -f2)
if [ "$name" = "$1" ] || [ "$path" = "$1" ]; then
if [ -f "$path"/activate ]; then
return 0
fi
fi
done <"$KERL_BASE_DIR"/otp_installations
fi
return 1
}
assert_valid_installation() {
if ! is_valid_installation "$1"; then
echo "$1 is not a kerl-managed Erlang/OTP installation"
exit 1
fi
return 0
}
assert_build_name_unused() {
if [ -f "$KERL_BASE_DIR"/otp_builds ]; then
while read -r l; do
name=$(echo "$l" | cut -d, -f2)
if [ "$name" = "$1" ]; then
echo "There's already a build named $1"
exit 1
fi
done <"$KERL_BASE_DIR"/otp_builds
fi
}
_check_required_pkgs() {
has_dpkg=$(command -v dpkg)
has_rpm=$(command -v rpm)
if [ -n "$has_dpkg" ] || [ -n "$has_rpm" ]; then
# found either dpkg or rpm (or maybe even both!)
if [ -n "$has_dpkg" ] && [ -n "$has_rpm" ]; then
echo 'WARNING: You appear to have BOTH rpm and dpkg. This is very strange. No package checks done.'
elif [ -n "$has_dpkg" ]; then
_check_dpkg
elif [ -n "$has_rpm" ]; then
_check_rpm
fi
fi
}
_dpkg_is_installed() {
# gratefully stolen from
# https://superuser.com/questions/427318/test-if-a-package-is-installed-in-apt
# returns 0 (true) if found, 1 otherwise
dpkg-query -Wf'${db:Status-abbrev}' "$1" 2>/dev/null | grep -q '^i'
}
_check_dpkg() {
required='
libssl-dev
make
automake
autoconf
libncurses5-dev
gcc
'
for pkg in $required; do
if ! _dpkg_is_installed "$pkg"; then
echo "WARNING: It appears that a required development package '$pkg' is not installed."
fi
done
}
_rpm_is_installed() {
rpm --quiet -q "$1" >/dev/null 2>&1
}
_check_rpm() {
required='
openssl-devel
make
automake
autoconf
ncurses-devel
gcc
'
for pkg in $required; do
if ! _rpm_is_installed "$pkg"; then
echo "WARNING: It appears a required development package '$pkg' is not installed."
fi
done
}
do_git_build() {
assert_build_name_unused "$3"
GIT=$(printf '%s' "$1" | $MD5SUM | cut -d ' ' -f $MD5SUM_FIELD)
mkdir -p "$KERL_GIT_DIR" || exit 1
cd "$KERL_GIT_DIR" || exit 1
echo "Checking out Erlang/OTP git repository from $1..."
if [ ! -d "$GIT" ]; then
if ! git clone -q --mirror "$1" "$GIT" >/dev/null 2>&1; then
echo 'Error mirroring remote git repository'
exit 1
fi
fi
cd "$GIT" || exit 1
if ! git remote update --prune >/dev/null 2>&1; then
echo 'Error updating remote git repository'
exit 1
fi
rm -Rf "${KERL_BUILD_DIR:?}/$3"
mkdir -p "$KERL_BUILD_DIR/$3" || exit 1
cd "$KERL_BUILD_DIR/$3" || exit 1
if ! git clone -l "$KERL_GIT_DIR/$GIT" otp_src_git >/dev/null 2>&1; then
echo 'Error cloning local git repository'
exit 1
fi
cd otp_src_git || exit 1
if ! git checkout "$2" >/dev/null 2>&1; then
if ! git checkout -b "$2" "$2" >/dev/null 2>&1; then
echo 'Could not checkout specified version'
rm -Rf "${KERL_BUILD_DIR:?}/$3"
exit 1
fi
fi
if [ ! -x otp_build ]; then
echo 'Not a valid Erlang/OTP repository'
rm -Rf "${KERL_BUILD_DIR:?}/$3"
exit 1
fi
echo "Building Erlang/OTP $3 from git, please wait..."
if [ -z "$KERL_BUILD_AUTOCONF" ]; then
KERL_USE_AUTOCONF=1
fi
_do_build 'git' "$3"
echo "Erlang/OTP $3 from git has been successfully built"
list_add builds git,"$3"
}
get_otp_version() {
echo "$1" | sed $SED_OPT -e 's/R?([0-9]{1,2}).+/\1/'
}
get_perl_version() {
if assert_perl; then
# This is really evil but it's portable and it works. Don't @ me bro
perl -e 'print int(($] - 5)*1000)'
else
echo 'FATAL: could not find perl which is required to compile Erlang.'
exit 1
fi
}
assert_perl() {
perl_loc=$(command -v perl)
if [ -z "$perl_loc" ]; then
return 1
else
# 0 to bash is "true" because of Unix exit code conventions
return 0
fi
}
get_javac_version() {
java_loc=$(command -v javac)
if [ -z "$java_loc" ]; then
# Java's not installed, so just return 0
0
else
javaout=$(javac -version 2>&1)
echo "$javaout" | cut -d' ' -f2 | cut -d. -f2
fi
}
show_configuration_warnings() {
# $1 is logfile
# $2 is section header (E.g. "APPLICATIONS DISABLED")
# Find the row number for the section we are looking for
INDEX=$(grep -n -m1 "$2" "$1" | cut -d: -f1)
# If there are no warnings, the section won't appear in the log
if [ -n "$INDEX" ]; then
# Skip the section header, find the end line and skip it
# then print the results indented
tail -n +$((INDEX+3)) "$1" | \
sed -n '1,/\*/p' | \
awk -F: -v logfile="$1" -v section="$2" \
'BEGIN { printf "%s (See: %s)\n", section, logfile }
/^[^\*]/ { print " *", $0 }
END { print "" } '
fi
}
show_logfile() {
echo "$1"
tail "$2"
echo
echo "Please see $2 for full details."
}
maybe_patch() {
# $1 = OS platform e.g., Darwin, etc
# $2 = OTP release
release=$(get_otp_version "$2")
case "$1" in
Darwin)
maybe_patch_darwin "$release"
;;
SunOS)
maybe_patch_sunos "$release"
;;
*)
;;
esac
maybe_patch_all "$release"
}
maybe_patch_all() {
perlver=$(get_perl_version)
if [ "$perlver" -ge 22 ]; then
case "$1" in
14)
apply_r14_beam_makeops_patch >>"$LOGFILE"
;;
15)
apply_r15_beam_makeops_patch >>"$LOGFILE"
;;
*)
;;
esac
fi
# Are we building docs?
if [ -n "$KERL_BUILD_DOCS" ]; then
if [ "$1" -le 16 ]; then
javaver=$(get_javac_version)
if [ "$javaver" -ge 8 ]; then
apply_javadoc_linting_patch >>"$LOGFILE"
fi
fi
fi
# Maybe apply zlib patch
if [ "$1" -ge 17 ] && [ "$1" -le 19 ]; then
apply_zlib_patch >> "$LOGFILE"
fi
}
maybe_patch_darwin() {
# Reminder: $1 = OTP release version
if [ "$1" -le 14 ]; then
CFLAGS='-DERTS_DO_INCL_GLB_INLINE_FUNC_DEF'
apply_darwin_compiler_patch >>"$LOGFILE"
elif [ "$1" -eq 16 ]; then
# TODO: Maybe check if clang version == 9
apply_r16_wx_ptr_patch >>"$LOGFILE"
elif [ "$1" -ge 17 ] && [ "$1" -le 19 ]; then
apply_wx_ptr_patch >>"$LOGFILE"
fi
}
maybe_patch_sunos() {
if [ "$1" -le 14 ]; then
apply_solaris_networking_patch >>"$LOGFILE"
fi
}
do_normal_build() {
assert_valid_release "$1"
assert_build_name_unused "$2"
FILENAME=""
download "$1"
mkdir -p "$KERL_BUILD_DIR/$2" || exit 1
if [ ! -d "$KERL_BUILD_DIR/$2/$FILENAME" ]; then
echo 'Extracting source code'
UNTARDIRNAME="$KERL_BUILD_DIR/$2/$FILENAME-kerluntar-$$"
rm -rf "$UNTARDIRNAME"
mkdir -p "$UNTARDIRNAME" || exit 1
# github tarballs have a directory in the form of "otp[_-]TAGNAME"
# Ericsson tarballs have the classic otp_src_RELEASE pattern
# Standardize on Ericsson format because that's what the rest of the script expects
(cd "$UNTARDIRNAME" && tar xzf "$KERL_DOWNLOAD_DIR/$FILENAME".tar.gz && mv -f ./* "$KERL_BUILD_DIR/$2/otp_src_$1")
rm -rf "$UNTARDIRNAME"
fi
echo "Building Erlang/OTP $1 ($2), please wait..."
_do_build "$1" "$2"
echo "Erlang/OTP $1 ($2) has been successfully built"
list_add builds "$1,$2"
}
_flags() {
# We need to munge the LD and DED flags for clang 9 shipped with
# High Sierra (macOS 10.13)
case "$KERL_SYSTEM" in
Darwin)
osver=$(uname -r)
case "$osver" in
17*)
# Make sure we don't overwrite values that someone who
# knows better than us set.
if [ -z "$DED_LD" ]; then
DED_LD='clang'
fi
if [ -z "$CC" ]; then
CC='clang'
fi
if [ -z "$DED_LDFLAGS" ]; then
host=$(./erts/autoconf/config.guess)
DED_LDFLAGS="-m64 -bundle -bundle_loader ${ERL_TOP}/bin/$host/beam.smp"
fi
CFLAGS="$CFLAGS" DED_LD="$DED_LD" CC="$CC" DED_LDFLAGS="$DED_LDFLAGS" "$@"
;;
*)
CFLAGS="$CFLAGS" "$@"
;;
esac
;;
*)
CFLAGS="$CFLAGS" "$@"
;;
esac
}
_do_build() {
case "$KERL_SYSTEM" in
Darwin)
OSVERSION=$(uname -r)
# Ensure that the --enable-darwin-64bit flag is set on all macOS
# That way even on older Erlangs we get 64 bit Erlang builds
# macOS has been mandatory 64 bit for a while
if ! echo "$KERL_CONFIGURE_OPTIONS" | grep 'darwin-64bit' >/dev/null 2>&1; then
KERL_CONFIGURE_OPTIONS="$KERL_CONFIGURE_OPTIONS "--enable-darwin-64bit
fi
case "$OSVERSION" in
17*|16*|15*)
if ! echo "$KERL_CONFIGURE_OPTIONS" | grep 'ssl' >/dev/null 2>&1; then
whichbrew=$(command -v brew)
if [ -n "$whichbrew" ] && [ -x "$whichbrew" ]; then
brew_prefix=$(brew --prefix openssl)
if [ -n "$brew_prefix" ] && [ -d "$brew_prefix" ]; then
KERL_CONFIGURE_OPTIONS="$KERL_CONFIGURE_OPTIONS "--with-ssl=$brew_prefix
fi
elif [ ! -d /usr/include/openssl ] || [ ! -d /usr/local/include/openssl ]; then
# Apple removed OpenSSL from El Capitan, but its still in this
# funky location, so set ssl headers to look here
xc_ssl='/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift-migrator/sdk/MacOSX.sdk/usr'
if [ -d "$xc_ssl"/include/openssl ]; then
KERL_CONFIGURE_OPTIONS="$KERL_CONFIGURE_OPTIONS --with-ssl=$xc_ssl"
fi
unset xc_ssl
fi
fi
;;
*)
;;
esac
;;
Linux)
# we are going to check here to see if the Linux uses dpkg or rpms
#
# this is a "best effort" attempt to discover if a Linux has the
# packages needed to build Erlang. We will always assume the user
# knows better than us and are going to go ahead and try to build
# Erlang anyway. But at least it will be a clear warning to the
# user if a build fails.
_check_required_pkgs
;;
*)
;;
esac
if [ -n "$KERL_BUILD_DOCS" ]; then
KERL_CONFIGURE_OPTIONS="$KERL_CONFIGURE_OPTIONS --prefix=$KERL_BUILD_DIR/$2/release_$1"
fi
ERL_TOP="$KERL_BUILD_DIR/$2/otp_src_$1"
cd "$ERL_TOP" || exit 1
LOGFILE="$KERL_BUILD_DIR/$2/otp_build_$1.log"
# Set configuation flags given applications white/black lists
if [ -n "$KERL_CONFIGURE_APPLICATIONS" ]; then
for app in $KERL_CONFIGURE_APPLICATIONS; do
case "$KERL_CONFIGURE_OPTIONS" in
*"--with-$app"*)
echo "Option '--with-$app' in KERL_CONFIGURE_OPTIONS is superfluous" ;;
*)
KERL_CONFIGURE_OPTIONS="$KERL_CONFIGURE_OPTIONS --with-$app" ;;
esac
done
fi
if [ -n "$KERL_CONFIGURE_DISABLE_APPLICATIONS" ]; then
for app in $KERL_CONFIGURE_DISABLE_APPLICATIONS; do
case "$KERL_CONFIGURE_OPTIONS" in
*"--without-$app"*)
echo "Option '--without-$app' in KERL_CONFIGURE_OPTIONS is superfluous" ;;
*)
KERL_CONFIGURE_OPTIONS="$KERL_CONFIGURE_OPTIONS --without-$app" ;;
esac
done
fi
# Check to see if configuration options need to be stored or have changed
TMPOPT="/tmp/kerloptions.$$"
echo "$CFLAGS" >"$TMPOPT"
echo "$KERL_CONFIGURE_OPTIONS" >>"$TMPOPT"
SUM=$($MD5SUM "$TMPOPT" | cut -d ' ' -f $MD5SUM_FIELD)
# Check for a .kerl_config.md5 file
if [ -e ./"$KERL_CONFIG_STORAGE_FILENAME".md5 ]; then
# Compare our current options to the saved ones
read -r OLD_SUM <./"$KERL_CONFIG_STORAGE_FILENAME".md5
if [ "$SUM" != "$OLD_SUM" ]; then
echo 'Configure options have changed. Reconfiguring...'
rm -f configure
mv "$TMPOPT" ./"$KERL_CONFIG_STORAGE_FILENAME"
echo "$SUM" >./"$KERL_CONFIG_STORAGE_FILENAME".md5
else
# configure options are the same
rm -f "$TMPOPT"
fi
else
# no file exists, so write one
mv "$TMPOPT" .kerl_config
echo "$SUM" >.kerl_config.md5
fi
# Don't apply patches to "custom" git builds. We have no idea if they will apply
# cleanly or not.
if [ "$1" != 'git' ]; then
maybe_patch "$KERL_SYSTEM" "$1"
fi
if [ -n "$KERL_USE_AUTOCONF" ]; then
# shellcheck disable=SC2086
./otp_build autoconf $KERL_CONFIGURE_OPTIONS >>"$LOGFILE" 2>&1 && \
_flags ./otp_build configure $KERL_CONFIGURE_OPTIONS >>"$LOGFILE" 2>&1
else
# shellcheck disable=SC2086
_flags ./otp_build configure $KERL_CONFIGURE_OPTIONS >>"$LOGFILE" 2>&1
fi
if ! echo "$KERL_CONFIGURE_OPTIONS" | grep '--enable-native-libs' >/dev/null 2>&1; then
make clean >>"$LOGFILE" 2>&1
# shellcheck disable=SC2086
if ! _flags ./otp_build configure $KERL_CONFIGURE_OPTIONS >>"$LOGFILE" 2>&1; then
show_logfile 'Configure failed.' "$LOGFILE"
list_remove builds "$1 $2"
exit 1
fi
fi
for SECTION in 'APPLICATIONS DISABLED' \
'APPLICATIONS INFORMATION' \
'DOCUMENTATION INFORMATION'; do
show_configuration_warnings "$LOGFILE" "$SECTION"
done
if [ -n "$KERL_CONFIGURE_APPLICATIONS" ]; then
find ./lib -maxdepth 1 -type d -exec touch -f {}/SKIP \;
for app in $KERL_CONFIGURE_APPLICATIONS; do
if ! rm ./lib/"$app"/SKIP; then
echo "Couldn't prepare '$app' application for building"
list_remove builds "$1 $2"
exit 1
fi
done
fi
if [ -n "$KERL_CONFIGURE_DISABLE_APPLICATIONS" ]; then
for app in $KERL_CONFIGURE_DISABLE_APPLICATIONS; do
if ! touch -f ./lib/"$app"/SKIP; then
echo "Couldn't disable '$app' application for building"
exit 1
fi
done
fi
# shellcheck disable=SC2086
if ! _flags ./otp_build boot -a $KERL_CONFIGURE_OPTIONS >>"$LOGFILE" 2>&1; then
show_logfile 'Build failed.' "$LOGFILE"
list_remove builds "$1 $2"
exit 1
fi
if [ -n "$KERL_BUILD_DOCS" ]; then
echo 'Building docs...'
if ! make docs >>"$LOGFILE" 2>&1; then
show_logfile 'Building docs failed.' "$LOGFILE"
list_remove builds "$1 $2"
exit 1
fi
if ! make install-docs >>"$LOGFILE" 2>&1; then
show_logfile 'Installing docs failed.' "$LOGFILE"
list_remove builds "$1 $2"
exit 1
fi
fi
rm -f "$LOGFILE"
ERL_TOP="$ERL_TOP" ./otp_build release -a "$KERL_BUILD_DIR/$2/release_$1" >/dev/null 2>&1
cd "$KERL_BUILD_DIR/$2/release_$1" || exit 1
./Install $INSTALL_OPT "$KERL_BUILD_DIR/$2/release_$1" >/dev/null 2>&1
}
do_install() {
if ! rel=$(get_release_from_name "$1"); then
echo "No build named $1"
exit 1
fi
if ! is_valid_install_path "$2"; then
exit 1
fi
mkdir -p "$2" || exit 1
absdir=$(cd "$2" && pwd)
echo "Installing Erlang/OTP $rel ($1) in $absdir..."
ERL_TOP="$KERL_BUILD_DIR/$1/otp_src_$rel"
cd "$ERL_TOP" || exit 1
if ! (ERL_TOP="$ERL_TOP" ./otp_build release -a "$absdir" >/dev/null 2>&1 &&
cd "$absdir" && ./Install $INSTALL_OPT "$absdir" >/dev/null 2>&1); then
echo "Couldn't install Erlang/OTP $rel ($1) in $absdir"
exit 1
fi
list_add installations "$1 $absdir";
cat <<ACTIVATE >"$absdir"/activate
#!/bin/sh
# credits to virtualenv
kerl_deactivate() {
if [ -n "\$_KERL_SAVED_ERL_AFLAGS" ]; then
ERL_AFLAGS="\$_KERL_SAVED_ERL_AFLAGS"
export ERL_AFLAGS
unset _KERL_SAVED_ERL_AFLAGS
fi
if [ -n "\$_KERL_PATH_REMOVABLE" ]; then
# shellcheck disable=SC2001
PATH="\$(echo "\$PATH" | sed -e "s#\$_KERL_PATH_REMOVABLE:##")"
export PATH
unset _KERL_PATH_REMOVABLE
fi
if [ -n "\$_KERL_MANPATH_REMOVABLE" ]; then
# shellcheck disable=SC2001
MANPATH="\$(echo "\$MANPATH" | sed -e "s#\$_KERL_MANPATH_REMOVABLE:##")"
export MANPATH
unset _KERL_MANPATH_REMOVABLE
fi
if [ -n "\$_KERL_SAVED_REBAR_PLT_DIR" ]; then
REBAR_PLT_DIR="\$_KERL_SAVED_REBAR_PLT_DIR"
export REBAR_PLT_DIR
unset _KERL_SAVED_REBAR_PLT_DIR
fi
if [ -n "\$_KERL_ACTIVE_DIR" ]; then
unset _KERL_ACTIVE_DIR
fi
if [ -n "\$_KERL_SAVED_PS1" ]; then
PS1="\$_KERL_SAVED_PS1"
export PS1
unset _KERL_SAVED_PS1
fi
if [ -n "\$_KERL_DOCSH_DOT_ERLANG" ]; then
rm "\$HOME/.erlang"
unset _KERL_DOCSH_DOT_ERLANG
fi
if [ -n "\$_KERL_DOCSH_USER_DEFAULT" ]; then
unset DOCSH_USER_DEFAULT
unset _KERL_DOCSH_USER_DEFAULT
fi
if [ -n "\$BASH" ] || [ -n "\$ZSH_VERSION" ]; then
hash -r
fi
if [ ! "\$1" = "nondestructive" ]; then
unset -f kerl_deactivate
fi
unset KERL_ENABLE_PROMPT
unset KERL_PROMPT_FORMAT
}
kerl_deactivate nondestructive
_KERL_SAVED_REBAR_PLT_DIR="\$REBAR_PLT_DIR"
export _KERL_SAVED_REBAR_PLT_DIR
_KERL_PATH_REMOVABLE="$absdir/bin"
PATH="\${_KERL_PATH_REMOVABLE}:\$PATH"
export PATH _KERL_PATH_REMOVABLE
_KERL_MANPATH_REMOVABLE="$absdir/lib/erlang/man:$absdir/man"
MANPATH="\${_KERL_MANPATH_REMOVABLE}:\$MANPATH"
export MANPATH _KERL_MANPATH_REMOVABLE
REBAR_PLT_DIR="$absdir"
export REBAR_PLT_DIR
_KERL_ACTIVE_DIR="$absdir"
export _KERL_ACTIVE_DIR
# https://twitter.com/mononcqc/status/877544929496629248
export _KERL_SAVED_ERL_AFLAGS=" \$ERL_AFLAGS"
kernel_history=\$(echo "\$ERL_AFLAGS" | grep 'kernel shell_history' || true)
if [ -z "\$kernel_history" ]; then
export ERL_AFLAGS="-kernel shell_history enabled \$ERL_AFLAGS"
fi
# shellcheck source=/dev/null
if [ -f "$KERL_CONFIG" ]; then . "$KERL_CONFIG"; fi
if [ -n "\$KERL_ENABLE_PROMPT" ]; then
_KERL_SAVED_PS1="\$PS1"
export _KERL_SAVED_PS1
if [ -n "\$KERL_PROMPT_FORMAT" ]; then
FRMT="\$KERL_PROMPT_FORMAT"
else
FRMT="(%BUILDNAME%)"
fi
PRMPT=\$(echo "\$FRMT" | sed 's^%RELEASE%^$rel^;s^%BUILDNAME%^$1^')
PS1="\$PRMPT\$PS1"
export PS1
fi
if [ -d "$absdir/lib/docsh" ]; then
export DOCSH_USER_DEFAULT="$absdir/lib/docsh/user_default"
export _KERL_DOCSH_USER_DEFAULT=yes
if [ -f "\$HOME/.erlang" ]; then
# shellcheck disable=SC2153
if [ ! x"\$KERL_DOCSH_DOT_ERLANG" = x'exists' ]; then
echo "Couldn't symlink correct \$HOME/.erlang - file exists - docsh might not work."
echo "Please make sure \$HOME/.erlang contains code"
echo "from $absdir/lib/docsh/dot.erlang"
echo 'and export KERL_DOCSH_DOT_ERLANG=exists to suppress this warning.'
fi
else
ln -s "$absdir/lib/docsh/dot.erlang" "\$HOME/.erlang"
export _KERL_DOCSH_DOT_ERLANG=yes
fi
fi
if [ -n "\$BASH" ] || [ -n "\$ZSH_VERSION" ]; then
hash -r
fi
ACTIVATE
cat <<ACTIVATE_FISH >"$absdir"/activate.fish
# credits to virtualenv
function _kerl_remove_el --description 'remove element from array'
set -l new_array
for el in \$\$argv[1]
if test \$el != \$argv[2]
set new_array \$new_array \$el
end
end
set -x \$argv[1] \$new_array
end
function kerl_deactivate --description "deactivate erlang environment"
if set --query _KERL_PATH_REMOVABLE
_kerl_remove_el PATH "\$_KERL_PATH_REMOVABLE"
set --erase _KERL_PATH_REMOVABLE
end
if set --query _KERL_MANPATH_REMOVABLE
_kerl_remove_el MANPATH "\$_KERL_MANPATH_REMOVABLE"
set --erase _KERL_MANPATH_REMOVABLE
end
if set --query _KERL_SAVED_REBAR_PLT_DIR
set -x REBAR_PLT_DIR "\$_KERL_SAVED_REBAR_PLT_DIR"
set --erase _KERL_SAVED_REBAR_PLT_DIR
end
if set --query _KERL_ACTIVE_DIR
set --erase _KERL_ACTIVE_DIR
end
if functions --query _kerl_saved_prompt
functions --erase fish_prompt
# functions --copy complains about about fish_prompt already being defined
# so we take a page from virtualenv's book
. ( begin
printf "function fish_prompt\\n\\t#"
functions _kerl_saved_prompt
end | psub )
functions --erase _kerl_saved_prompt
end
if set --query _KERL_DOCSH_DOT_ERLANG
rm "\$HOME/.erlang"
set --erase _KERL_DOCSH_DOT_ERLANG
end
if set --query _KERL_DOCSH_USER_DEFAULT
set --erase DOCSH_USER_DEFAULT
set --erase _KERL_DOCSH_USER_DEFAULT
end
if test "\$argv[1]" != "nondestructive"
functions --erase kerl_deactivate
functions --erase _kerl_remove_el
end
end
kerl_deactivate nondestructive
set -x _KERL_SAVED_REBAR_PLT_DIR "\$REBAR_PLT_DIR"
set -x _KERL_PATH_REMOVABLE "$absdir/bin"
set -x PATH "\$_KERL_PATH_REMOVABLE" \$PATH
set -x _KERL_MANPATH_REMOVABLE "$absdir/lib/erlang/man" "$absdir/man"
set -x MANPATH \$MANPATH "\$_KERL_MANPATH_REMOVABLE"
set -x REBAR_PLT_DIR "$absdir"
set -x _KERL_ACTIVE_DIR "$absdir"
if test -f "$KERL_CONFIG.fish"
source "$KERL_CONFIG.fish"
end
if set --query KERL_ENABLE_PROMPT
functions --copy fish_prompt _kerl_saved_prompt
function fish_prompt
echo -n "($1)"
_kerl_saved_prompt
end
end
if test -d "$absdir/lib/docsh"
set -x DOCSH_USER_DEFAULT "$absdir/lib/docsh/user_default"
set -x _KERL_DOCSH_USER_DEFAULT yes
if test -f "\$HOME/.erlang"
if test ! x"\$KERL_DOCSH_DOT_ERLANG" = x"exists"
echo "Couldn't symlink correct \$HOME/.erlang - file exists - docsh might not work."
echo "Please make sure \$HOME/.erlang contains code"
echo "from $absdir/lib/docsh/dot.erlang"
echo "and export KERL_DOCSH_DOT_ERLANG=exists to suppress this warning."
end
else
ln -s "$absdir/lib/docsh/dot.erlang" "\$HOME/.erlang"
set -x _KERL_DOCSH_DOT_ERLANG yes
end
end
ACTIVATE_FISH
cat <<ACTIVATE_CSH >"$absdir"/activate.csh
# This file must be used with "source bin/activate.csh" *from csh*.
# You cannot run it directly.
alias kerl_deactivate 'test \$?_KERL_SAVED_PATH != 0 && setenv PATH "\$_KERL_SAVED_PATH" && unset _KERL_SAVED_PATH; rehash; test \$?_KERL_SAVED_MANPATH != 0 && setenv MANPATH "\$_KERL_SAVED_MANPATH" && unset _KERL_SAVED_MANPATH; test \$?_KERL_SAVED_REBAR_PLT_DIR != 0 && setenv REBAR_PLT_DIR "\$_KERL_SAVED_REBAR_PLT_DIR" && unset _KERL_SAVED_REBAR_PLT_DIR; test \$?_KERL_ACTIVE_DIR != 0 && unset _KERL_ACTIVE_DIR; test \$?_KERL_DOCSH_USER_DEFAULT != 0 && unsetenv DOCSH_USER_DEFAULT && unset _KERL_DOCSH_USER_DEFAULT; test \$?_KERL_DOCSH_DOT_ERLANG != 0 && rm "\$HOME/.erlang" && unset _KERL_DOCSH_DOT_ERLANG; test \$?_KERL_SAVED_PROMPT != 0 && set prompt="\$_KERL_SAVED_PROMPT" && unset _KERL_SAVED_PROMPT; test "!:*" != "nondestructive" && unalias deactivate'
# Unset irrelevant variables.
kerl_deactivate nondestructive
if ( \$?REBAR_PLT_DIR ) then
set _KERL_SAVED_REBAR_PLT_DIR = "\$REBAR_PLT_DIR"
else
set _KERL_SAVED_REBAR_PLT_DIR=""
endif
set _KERL_PATH_REMOVABLE = "$absdir/bin"
set _KERL_SAVED_PATH = "\$PATH"
setenv PATH "\${_KERL_PATH_REMOVABLE}:\$PATH"
if ( ! \$?MANPATH ) then
set MANPATH = ""
endif
set _KERL_MANPATH_REMOVABLE = "$absdir/lib/erlang/man:$absdir/man"
set _KERL_SAVED_MANPATH = "\$MANPATH"
setenv MANPATH "\${_KERL_MANPATH_REMOVABLE}:\$MANPATH"
setenv REBAR_PLT_DIR "$absdir"
set _KERL_ACTIVE_DIR = "$absdir"
if ( -f "$KERL_CONFIG.csh" ) then
source "$KERL_CONFIG.csh"
endif
if ( \$?KERL_ENABLE_PROMPT ) then
set _KERL_SAVED_PROMPT = "\$prompt"
if ( \$?KERL_PROMPT_FORMAT ) then
set FRMT = "\$KERL_PROMPT_FORMAT"
else
set FRMT = "(%BUILDNAME%)"
endif
set PROMPT = \$(echo "\$FRMT" | sed 's^%RELEASE%^$rel^;s^%BUILDNAME%^$1^')
set prompt = "\$PROMPT\$prompt"
endif
if ( -d "$absdir/lib/docsh" ) then
setenv DOCSH_USER_DEFAULT "$absdir/lib/docsh/user_default"
set _KERL_DOCSH_USER_DEFAULT = "yes"
if ( -f "\$HOME/.erlang" ) then
if ( \$?KERL_DOCSH_DOT_ERLANG == 0 ) then
echo "Couldn't symlink correct \$HOME/.erlang - file exists - docsh might not work."
echo "Please make sure \$HOME/.erlang contains code"
echo "from $absdir/lib/docsh/dot.erlang"
echo "and export KERL_DOCSH_DOT_ERLANG=exists to suppress this warning."
endif
else
ln -s "$absdir/lib/docsh/dot.erlang" "\$HOME/.erlang"
set _KERL_DOCSH_DOT_ERLANG = "yes"
endif
endif
rehash
ACTIVATE_CSH
if [ -n "$KERL_BUILD_DOCS" ]; then
DOC_DIR="$KERL_BUILD_DIR/$1/release_$rel"/lib/erlang
if [ -d "$DOC_DIR" ]; then
echo 'Installing docs...'
cp $CP_OPT "$DOC_DIR/" "$absdir"/lib
if [ -d "$absdir"/lib/erlang/man ]; then
ln -s "$absdir"/lib/erlang/man "$absdir"/man
ln -s "$absdir"/lib/erlang/doc "$absdir"/html
elif [ -d "$absdir"/lib/man ]; then
ln -s "$absdir"/lib/man "$absdir"/man
ln -s "$absdir"/lib/doc "$absdir"/html
fi
fi
else
if [ "$KERL_BUILD_BACKEND" = 'tarball' ]; then
if [ "$rel" != 'git' ]; then
if [ -n "$KERL_INSTALL_MANPAGES" ]; then
echo 'Fetching and installing manpages...'
download_manpages "$rel"
fi
if [ -n "$KERL_INSTALL_HTMLDOCS" ]; then
echo 'Fetching and installing HTML docs...'
download_htmldocs "$rel"
fi
fi
fi
fi
KERL_CONFIG_STORAGE_PATH="$KERL_BUILD_DIR/$1/otp_src_$rel/$KERL_CONFIG_STORAGE_FILENAME"
[ -e "$KERL_CONFIG_STORAGE_PATH" ] && cp "$KERL_CONFIG_STORAGE_PATH" "$absdir/$KERL_CONFIG_STORAGE_FILENAME"
if [ -n "$KERL_BUILD_PLT" ]; then
echo 'Building Dialyzer PLT...'
build_plt "$absdir"
fi
if command -v apk >/dev/null 2>&1; then
# Running on Alpine Linux, assuming non-exotic shell
SHELL_SUFFIX=''
else
PID=$$
PARENT_PID=$(ps -p $PID -o ppid=) || exit 1
# shellcheck disable=SC2086
PARENT_CMD=$(ps -p $PARENT_PID -o ucomm | tail -n 1)
case "$PARENT_CMD" in
fish)
SHELL_SUFFIX='.fish'
;;
csh)
SHELL_SUFFIX='.csh'
;;
*)
SHELL_SUFFIX=''
;;
esac
fi
echo 'You can activate this installation running the following command:'
echo ". $absdir/activate$SHELL_SUFFIX"
echo 'Later on, you can leave the installation typing:'
echo 'kerl_deactivate'
}
install_docsh() {
REPO_URL=$DOCSH_GITHUB_URL
GIT=$(printf '%s' $REPO_URL | $MD5SUM | cut -d' ' -f $MD5SUM_FIELD)
BUILDNAME="$1"
DOCSH_DIR="$KERL_BUILD_DIR/$BUILDNAME/docsh"
DOCSH_REF='0.5.0'
ACTIVE_PATH="$2"
OTP_VERSION=$(get_otp_version "$1")
# This has to be updated with docsh updates
DOCSH_SUPPORTED='^1[89]\|20$'
if ! echo "$OTP_VERSION" | grep "$DOCSH_SUPPORTED" >/dev/null 2>&1; then
echo "Erlang/OTP version $OTP_VERSION not supported by docsh (does not match regex $DOCSH_SUPPORTED)"
exit 1
fi
mkdir -p "$KERL_GIT_DIR" || exit 1
cd "$KERL_GIT_DIR" || exit 1
echo "Checking out docsh git repository from $REPO_URL..."
if [ ! -d "$GIT" ]; then
if ! git clone -q --mirror "$REPO_URL" "$GIT" >/dev/null 2>&1; then
echo 'Error mirroring remote git repository'
exit 1
fi
fi
cd "$GIT" || exit 1
if ! git remote update --prune >/dev/null 2>&1; then
echo 'Error updating remote git repository'
exit 1
fi
rm -Rf "$DOCSH_DIR"
mkdir -p "$DOCSH_DIR" || exit 1
cd "$DOCSH_DIR" || exit 1
if ! git clone -l "$KERL_GIT_DIR/$GIT" "$DOCSH_DIR" >/dev/null 2>&1; then
echo 'Error cloning local git repository'
exit 1
fi
cd "$DOCSH_DIR" || exit 1
if ! git checkout "$DOCSH_REF" >/dev/null 2>&1; then
if ! git checkout -b "$DOCSH_REF" "$DOCSH_REF" >/dev/null 2>&1; then
echo 'Could not checkout specified version'
rm -Rf "$DOCSH_DIR"
exit 1
fi
fi
if ! ./rebar3 compile; then
echo 'Could not compile docsh'
rm -Rf "$DOCSH_DIR"
exit 1
fi
## Install docsh
if [ -f "$ACTIVE_PATH"/lib/docsh ]; then
echo "Couldn't install $ACTIVE_PATH/lib/docsh - the directory already exists"
rm -Rf "$DOCSH_DIR"
exit 1
else
cp -R "$DOCSH_DIR"/_build/default/lib/docsh "$ACTIVE_PATH"/lib/
fi
## Prepare dot.erlang for linking as $HOME/.erlang
if [ -f "$ACTIVE_PATH"/lib/docsh/dot.erlang ]; then
echo "Couldn't install $ACTIVE_PATH/lib/docsh/dot.erlang - the file already exists"
rm -Rf "$DOCSH_DIR"
exit 1
else
cat "$DOCSH_DIR"/templates/dot.erlang >"$ACTIVE_PATH"/lib/docsh/dot.erlang
fi
## Warn if $HOME/.erlang exists
if [ -f "$HOME"/.erlang ]; then
echo "$HOME/.erlang exists - kerl won't be able to symlink a docsh-compatible version."
echo "Please make sure your $HOME/.erlang contains code"
echo "from $ACTIVE_PATH/lib/docsh/dot.erlang"
echo 'and export KERL_DOCSH_DOT_ERLANG=exists to suppress further warnings'
fi
## Install docsh user_default
if [ -f "$ACTIVE_PATH"/lib/docsh/user_default.beam ]; then
echo "Couldn't install $ACTIVE_PATH/lib/docsh/user_default.beam - the file already exists"
rm -Rf "$DOCSH_DIR"
exit 1
else
erlc -I "$DOCSH_DIR"/include -o "$ACTIVE_PATH"/lib/docsh/ "$DOCSH_DIR"/templates/user_default.erl
fi
}
download_manpages() {
FILENAME=otp_doc_man_$1.tar.gz
tarball_download "$FILENAME"
echo 'Extracting manpages'
cd "$absdir" && tar xzf "$KERL_DOWNLOAD_DIR/$FILENAME"
}
download_htmldocs() {
FILENAME=otp_doc_html_"$1".tar.gz
tarball_download "$FILENAME"
echo 'Extracting HTML docs'
(cd "$absdir" && mkdir -p html && tar -C "$absdir"/html -xzf "$KERL_DOWNLOAD_DIR/$FILENAME")
}
build_plt() {
dialyzerd="$1"/dialyzer
mkdir -p "$dialyzerd" || exit 1
plt="$dialyzerd"/plt
build_log="$dialyzerd"/build.log
dirs=$(find "$1"/lib -maxdepth 2 -name ebin -type d -exec dirname {} \;)
apps=$(for app in $dirs; do basename "$app" | cut -d- -f1 ; done | grep -Ev 'erl_interface|jinterface' | xargs echo)
# shellcheck disable=SC2086
"$1"/bin/dialyzer --output_plt "$plt" --build_plt --apps $apps >>"$build_log" 2>&1
status=$?
if [ $status -eq 0 ] || [ $status -eq 2 ]; then
echo "Done building $plt"
return 0
else
echo "Error building PLT, see $build_log for details"
return 1
fi
}
do_plt() {
ACTIVE_PATH="$1"
if [ -n "$ACTIVE_PATH" ]; then
plt="$ACTIVE_PATH"/dialyzer/plt
if [ -f "$plt" ]; then
echo 'Dialyzer PLT for the active installation is:'
echo "$plt"
return 0
else
echo 'There is no Dialyzer PLT for the active installation'
return 1
fi
else
echo 'No Erlang/OTP installation is currently active'
return 2
fi
}
print_buildopts() {
buildopts="$1/$KERL_CONFIG_STORAGE_FILENAME"
if [ -f "$buildopts" ]; then
echo 'The build options for the active installation are:'
cat "$buildopts"
return 0
else
echo 'The build options for the active installation are not available.'
return 1
fi
}
do_deploy() {
if [ -z "$1" ]; then
echo 'No host given'
exit 1
fi
host="$1"
assert_valid_installation "$2"
rel="$(get_name_from_install_path "$2")"
path="$2"
remotepath="$path"
if [ ! -z "$3" ]; then
remotepath="$3"
fi
# shellcheck disable=SC2086
if ! ssh $KERL_DEPLOY_SSH_OPTIONS "$host" true >/dev/null 2>&1; then
echo "Couldn't ssh to $host"
exit 1
fi
echo "Cloning Erlang/OTP $rel ($path) to $host ($remotepath) ..."
# shellcheck disable=SC2086
if ! rsync -aqz -e "ssh $KERL_DEPLOY_SSH_OPTIONS" $KERL_DEPLOY_RSYNC_OPTIONS "$path/" "$host:$remotepath/"; then
echo "Couldn't rsync Erlang/OTP $rel ($path) to $host ($remotepath)"
exit 1
fi
# shellcheck disable=SC2086,SC2029
if ! ssh $KERL_DEPLOY_SSH_OPTIONS "$host" "cd \"$remotepath\" && env ERL_TOP=\"\$(pwd)\" ./Install $INSTALL_OPT \"\$(pwd)\" >/dev/null 2>&1"; then
echo "Couldn't install Erlang/OTP $rel to $host ($remotepath)"
exit 1
fi
# shellcheck disable=SC2086,SC2029
if ! ssh $KERL_DEPLOY_SSH_OPTIONS "$host" "cd \"$remotepath\" && sed -i -e \"s#$path#\"\$(pwd)\"#g\" activate"; then
echo "Couldn't completely install Erlang/OTP $rel to $host ($remotepath)"
exit 1
fi
echo "On $host, you can activate this installation running the following command:"
echo ". $remotepath/activate"
echo 'Later on, you can leave the installation typing:'
echo 'kerl_deactivate'
}
# Quoted from https://github.com/mkropat/sh-realpath
# LICENSE: MIT
realpath() {
canonicalize_path "$(resolve_symlinks "$1")"
}
resolve_symlinks() {
_resolve_symlinks "$1"
}
_resolve_symlinks() {
_assert_no_path_cycles "$@" || return
if path=$(readlink -- "$1"); then
dir_context=$(dirname -- "$1")
_resolve_symlinks "$(_prepend_dir_context_if_necessary "$dir_context" "$path")" "$@"
else
printf '%s\n' "$1"
fi
}
_prepend_dir_context_if_necessary() {
if [ "$1" = . ]; then
printf '%s\n' "$2"
else
_prepend_path_if_relative "$1" "$2"
fi
}
_prepend_path_if_relative() {
case "$2" in
/* ) printf '%s\n' "$2" ;;
* ) printf '%s\n' "$1/$2" ;;
esac
}
_assert_no_path_cycles() {
target=$1
shift
for path in "$@"; do
if [ "$path" = "$target" ]; then
return 1
fi
done
}
canonicalize_path() {
if [ -d "$1" ]; then
_canonicalize_dir_path "$1"
else
_canonicalize_file_path "$1"
fi
}
_canonicalize_dir_path() {
(cd "$1" 2>/dev/null && pwd -P)
}
_canonicalize_file_path() {
dir=$(dirname -- "$1")
file=$(basename -- "$1")
(cd "$dir" 2>/dev/null && printf '%s/%s\n' "$(pwd -P)" "$file")
}
# END QUOTE
is_valid_install_path() {
# don't allow installs into .erlang because
# it's a special configuration file location for OTP
if [ "$(basename -- "$1")" = '.erlang' ]; then
echo 'ERROR: You cannot install a build into .erlang. (It is a special configuration file location for OTP.)'
return 1
fi
candidate=$(realpath "$1")
canonical_home=$(realpath "$HOME")
canonical_base_dir=$(realpath "$KERL_BASE_DIR")
# don't allow installs into home directory
if [ "$candidate" = "$canonical_home" ]; then
echo "ERROR: You cannot install a build into $HOME. It's a really bad idea."
return 1
fi
# don't install into our base directory either.
if [ "$candidate" = "$canonical_base_dir" ]; then
echo "ERROR: You cannot install a build into $KERL_BASE_DIR."
return 1
fi
INSTALLED_NAME=$(get_name_from_install_path "$candidate")
if [ -n "$INSTALLED_NAME" ]; then
echo "ERROR: Installation ($INSTALLED_NAME) already registered for this location ($1)"
return 1
fi
# if the install directory exists,
# do not allow installs into a directory that is not empty
if [ -e "$1" ]; then
if [ ! -d "$1" ]; then
echo "ERROR: $1 is not a directory."
return 1
else
count=$(find "$1" | wc -l)
if [ "$count" -ne 1 ]; then
echo "ERROR: $1 does not appear to be an empty directory."
return 1
fi
fi
fi
return 0
}
maybe_remove() {
candidate=$(realpath "$1")
canonical_home=$(realpath "$HOME")
if [ "$candidate" = "$canonical_home" ]; then
echo "WARNING: You cannot remove an install from $HOME; it's your home directory."
return 0
fi
ACTIVE_PATH="$(get_active_path)"
if [ "$candidate" = "$ACTIVE_PATH" ]; then
echo 'ERROR: You cannot delete the active installation. Deactivate it first.'
exit 1
fi
rm -Rf "$1"
}
list_print() {
if [ -f "$KERL_BASE_DIR/otp_$1" ]; then
if [ "$(wc -l "$KERL_BASE_DIR/otp_$1")" != '0' ]; then
cat "$KERL_BASE_DIR/otp_$1"
return 0
fi
fi
echo "There are no $1 available"
}
list_add() {
if [ -f "$KERL_BASE_DIR/otp_$1" ]; then
while read -r l; do
if [ "$l" = "$2" ]; then
return 1
fi
done <"$KERL_BASE_DIR/otp_$1"
echo "$2" >>"$KERL_BASE_DIR/otp_$1" || exit 1
else
echo "$2" >"$KERL_BASE_DIR/otp_$1" || exit 1
fi
}
list_remove() {
if [ -f "$KERL_BASE_DIR/otp_$1" ]; then
sed $SED_OPT -i -e "/^.*$2$/d" "$KERL_BASE_DIR/otp_$1" || exit 1
fi
}
list_has() {
if [ -f "$KERL_BASE_DIR/otp_$1" ]; then
grep "$2" "$KERL_BASE_DIR/otp_$1" >/dev/null 2>&1 && return 0
fi
return 1
}
path_usage() {
echo "usage: $0 path [<install_name>]"
}
list_usage() {
echo "usage: $0 list <releases|builds|installations>"
}
delete_usage() {
echo "usage: $0 delete <build|installation> <build_name or path>"
}
cleanup_usage() {
echo "usage: $0 cleanup <build_name|all>"
}
update_usage() {
echo "usage: $0 update releases"
}
get_active_path() {
if [ -n "$_KERL_ACTIVE_DIR" ]; then
echo "$_KERL_ACTIVE_DIR"
fi
return 0
}
get_name_from_install_path() {
if [ -f "$KERL_BASE_DIR"/otp_installations ]; then
grep -m1 -E "$1$" "$KERL_BASE_DIR"/otp_installations | cut -d' ' -f1
fi
return 0
}
get_install_path_from_name() {
if [ -f "$KERL_BASE_DIR"/otp_installations ]; then
grep -m1 -E "$1$" "$KERL_BASE_DIR"/otp_installations | cut -d' ' -f2
fi
return 0
}
do_active() {
ACTIVE_PATH="$(get_active_path)"
if [ -n "$ACTIVE_PATH" ]; then
echo 'The current active installation is:'
echo "$ACTIVE_PATH"
return 0
else
echo 'No Erlang/OTP installation is currently active'
return 1
fi
}
make_filename() {
release=$(get_otp_version "$1")
if [ "$release" -ge 17 ]; then
echo "OTP-$1"
else
echo "OTP_$1"
fi
}
download() {
mkdir -p "$KERL_DOWNLOAD_DIR" || exit 1
if [ "$KERL_BUILD_BACKEND" = 'git' ]; then
FILENAME=$(make_filename "$1")
github_download "$FILENAME".tar.gz
else
FILENAME="otp_src_$1"
tarball_download "$FILENAME".tar.gz
fi
}
github_download() {
# if the file doesn't exist or the file has no size
if [ ! -s "$KERL_DOWNLOAD_DIR/$1" ]; then
echo "Downloading $1 to $KERL_DOWNLOAD_DIR"
curl -f -L -o "$KERL_DOWNLOAD_DIR/$1" "$OTP_GITHUB_URL/archive/$1" || exit 1
fi
}
tarball_download() {
if [ ! -s "$KERL_DOWNLOAD_DIR/$1" ]; then
echo "Downloading $1 to $KERL_DOWNLOAD_DIR"
curl -f -L -o "$KERL_DOWNLOAD_DIR/$1" "$ERLANG_DOWNLOAD_URL/$1" || exit 1
update_checksum_file
fi
ensure_checksum_file
echo 'Verifying archive checksum...'
SUM="$($MD5SUM "$KERL_DOWNLOAD_DIR/$1" | cut -d' ' -f $MD5SUM_FIELD)"
ORIG_SUM="$(grep -F "$1" "$KERL_DOWNLOAD_DIR"/MD5 | cut -d' ' -f2)"
if [ "$SUM" != "$ORIG_SUM" ]; then
echo "Checksum error, check the files in $KERL_DOWNLOAD_DIR"
exit 1
fi
echo "Checksum verified ($SUM)"
}
apply_solaris_networking_patch() {
patch -p1 <<_END_PATCH
--- otp-a/erts/emulator/drivers/common/inet_drv.c
+++ otp-b/erts/emulator/drivers/common/inet_drv.c
@@ -4166,16 +4166,7 @@
break;
case INET_IFOPT_HWADDR: {
-#ifdef SIOCGIFHWADDR
- if (ioctl(desc->s, SIOCGIFHWADDR, (char *)&ifreq) < 0)
- break;
- buf_check(sptr, s_end, 1+2+IFHWADDRLEN);
- *sptr++ = INET_IFOPT_HWADDR;
- put_int16(IFHWADDRLEN, sptr); sptr += 2;
- /* raw memcpy (fix include autoconf later) */
- sys_memcpy(sptr, (char*)(&ifreq.ifr_hwaddr.sa_data), IFHWADDRLEN);
- sptr += IFHWADDRLEN;
-#elif defined(SIOCGENADDR)
+#if defined(SIOCGENADDR)
if (ioctl(desc->s, SIOCGENADDR, (char *)&ifreq) < 0)
break;
buf_check(sptr, s_end, 1+2+sizeof(ifreq.ifr_enaddr));
_END_PATCH
}
apply_darwin_compiler_patch() {
patch -p0 <<_END_PATCH
--- erts/emulator/beam/beam_bp.c.orig 2011-10-03 13:12:07.000000000 -0500
+++ erts/emulator/beam/beam_bp.c 2013-10-04 13:42:03.000000000 -0500
@@ -496,7 +496,8 @@
}
/* bp_hash */
-ERTS_INLINE Uint bp_sched2ix() {
+#ifndef ERTS_DO_INCL_GLB_INLINE_FUNC_DEF
+ERTS_GLB_INLINE Uint bp_sched2ix() {
#ifdef ERTS_SMP
ErtsSchedulerData *esdp;
esdp = erts_get_scheduler_data();
@@ -505,6 +506,7 @@
return 0;
#endif
}
+#endif
static void bp_hash_init(bp_time_hash_t *hash, Uint n) {
Uint size = sizeof(bp_data_time_item_t)*n;
Uint i;
--- erts/emulator/beam/beam_bp.h.orig 2011-10-03 13:12:07.000000000 -0500
+++ erts/emulator/beam/beam_bp.h 2013-10-04 13:42:08.000000000 -0500
@@ -144,7 +144,19 @@
#define ErtsSmpBPUnlock(BDC)
#endif
-ERTS_INLINE Uint bp_sched2ix(void);
+ERTS_GLB_INLINE Uint bp_sched2ix(void);
+
+#ifdef ERTS_DO_INCL_GLB_INLINE_FUNC_DEF
+ERTS_GLB_INLINE Uint bp_sched2ix() {
+#ifdef ERTS_SMP
+ ErtsSchedulerData *esdp;
+ esdp = erts_get_scheduler_data();
+ return esdp->no - 1;
+#else
+ return 0;
+#endif
+}
+#endif
#ifdef ERTS_SMP
#define bp_sched2ix_proc(p) ((p)->scheduler_data->no - 1)
_END_PATCH
}
# javadoc 8 includes always-enabled document linting which causes
# documentation builds to fail on older OTP releases.
apply_javadoc_linting_patch() {
# The _END_PATCH token is quoted below to disable parameter substitution
patch -p0 <<'_END_PATCH'
--- lib/jinterface/doc/src/Makefile.orig 2016-05-23 14:34:48.000000000 -0500
+++ lib/jinterface/doc/src/Makefile 2016-05-23 14:35:48.000000000 -0500
@@ -142,7 +142,7 @@
rm -f errs core *~
jdoc:$(JAVA_SRC_FILES)
- (cd ../../java_src;$(JAVADOC) -sourcepath . -d $(JAVADOC_DEST) \
+ (cd ../../java_src;$(JAVADOC) -Xdoclint:none -sourcepath . -d $(JAVADOC_DEST) \
-windowtitle $(JAVADOC_TITLE) $(JAVADOC_PKGS))
man:
_END_PATCH
}
# perl 5.24 fatalizes the warning this causes
apply_r14_beam_makeops_patch() {
patch -p0 <<'_END_PATCH'
--- erts/emulator/utils/beam_makeops.orig 2016-05-23 21:40:42.000000000 -0500
+++ erts/emulator/utils/beam_makeops 2016-05-23 21:41:08.000000000 -0500
@@ -1576,7 +1576,7 @@
if $min_window{$key} > $min_window;
pop(@{$gen_transform{$key}})
- if defined @{$gen_transform{$key}}; # Fail
+ if defined $gen_transform{$key}; # Fail
my(@prefix) = (&make_op($comment), &make_op('', 'try_me_else', &tr_code_len(@code)));
unshift(@code, @prefix);
push(@{$gen_transform{$key}}, @code, &make_op('', 'fail'));
_END_PATCH
}
# https://github.com/erlang/otp/commit/21ca6d3a137034f19862db769a5b7f1c5528dbc4.diff
apply_r15_beam_makeops_patch() {
patch -p1 <<'_END_PATCH'
--- a/erts/emulator/utils/beam_makeops
+++ b/erts/emulator/utils/beam_makeops
@@ -1711,7 +1711,7 @@ sub tr_gen_to {
my $prev_last;
$prev_last = pop(@{$gen_transform{$key}})
- if defined @{$gen_transform{$key}}; # Fail
+ if defined $gen_transform{$key}; # Fail
if ($prev_last && !is_instr($prev_last, 'fail')) {
error("Line $line: A previous transformation shadows '$orig_transform'");
_END_PATCH
}
#https://github.com/erlang/otp/commit/a64c4d806fa54848c35632114585ad82b98712e8.diff
apply_wx_ptr_patch() {
patch -p1 <<'_END_PATCH'
diff --git a/lib/wx/c_src/wxe_impl.cpp b/lib/wx/c_src/wxe_impl.cpp
index 0d2da5d4a79..8118136d30e 100644
--- a/lib/wx/c_src/wxe_impl.cpp
+++ b/lib/wx/c_src/wxe_impl.cpp
@@ -666,7 +666,7 @@ void * WxeApp::getPtr(char * bp, wxeMemEnv *memenv) {
throw wxe_badarg(index);
}
void * temp = memenv->ref2ptr[index];
- if((index < memenv->next) && ((index == 0) || (temp > NULL)))
+ if((index < memenv->next) && ((index == 0) || (temp != (void *)NULL)))
return temp;
else {
throw wxe_badarg(index);
@@ -678,7 +678,7 @@ void WxeApp::registerPid(char * bp, ErlDrvTermData pid, wxeMemEnv * memenv) {
if(!memenv)
throw wxe_badarg(index);
void * temp = memenv->ref2ptr[index];
- if((index < memenv->next) && ((index == 0) || (temp > NULL))) {
+ if((index < memenv->next) && ((index == 0) || (temp != (void *) NULL))) {
ptrMap::iterator it;
it = ptr2ref.find(temp);
if(it != ptr2ref.end()) {
_END_PATCH
}
apply_r16_wx_ptr_patch() {
patch -p1 <<'_END_PATCH'
diff --git a/lib/wx/c_src/wxe_impl.cpp b/lib/wx/c_src/wxe_impl.cpp
index cc9bcc995..1b1912630 100644
--- a/lib/wx/c_src/wxe_impl.cpp
+++ b/lib/wx/c_src/wxe_impl.cpp
@@ -757,7 +757,7 @@ void * WxeApp::getPtr(char * bp, wxeMemEnv *memenv) {
throw wxe_badarg(index);
}
void * temp = memenv->ref2ptr[index];
- if((index < memenv->next) && ((index == 0) || (temp > NULL)))
+ if((index < memenv->next) && ((index == 0) || (temp != (void *)NULL)))
return temp;
else {
throw wxe_badarg(index);
@@ -769,7 +769,7 @@ void WxeApp::registerPid(char * bp, ErlDrvTermData pid, wxeMemEnv * memenv) {
if(!memenv)
throw wxe_badarg(index);
void * temp = memenv->ref2ptr[index];
- if((index < memenv->next) && ((index == 0) || (temp > NULL))) {
+ if((index < memenv->next) && ((index == 0) || (temp != (void *)NULL))) {
ptrMap::iterator it;
it = ptr2ref.find(temp);
if(it != ptr2ref.end()) {
_END_PATCH
}
# https://github.com/erlang/otp/commit/e27119948fc6ab28bea81019720bddaac5b655a7.patch
apply_zlib_patch()
{
patch -p1 <<'_END_PATCH'
diff --git a/erts/emulator/beam/external.c b/erts/emulator/beam/external.c
index 656de7c49ad..4491d486837 100644
--- a/erts/emulator/beam/external.c
+++ b/erts/emulator/beam/external.c
@@ -1193,6 +1193,7 @@ typedef struct B2TContext_t {
} u;
} B2TContext;
+static B2TContext* b2t_export_context(Process*, B2TContext* src);
static uLongf binary2term_uncomp_size(byte* data, Sint size)
{
@@ -1225,7 +1226,7 @@ static uLongf binary2term_uncomp_size(byte* data, Sint size)
static ERTS_INLINE int
binary2term_prepare(ErtsBinary2TermState *state, byte *data, Sint data_size,
- B2TContext* ctx)
+ B2TContext** ctxp, Process* p)
{
byte *bytes = data;
Sint size = data_size;
@@ -1239,8 +1240,8 @@ binary2term_prepare(ErtsBinary2TermState *state, byte *data, Sint data_size,
size--;
if (size < 5 || *bytes != COMPRESSED) {
state->extp = bytes;
- if (ctx)
- ctx->state = B2TSizeInit;
+ if (ctxp)
+ (*ctxp)->state = B2TSizeInit;
}
else {
uLongf dest_len = (Uint32) get_int32(bytes+1);
@@ -1257,16 +1258,26 @@ binary2term_prepare(ErtsBinary2TermState *state, byte *data, Sint data_size,
return -1;
}
state->extp = erts_alloc(ERTS_ALC_T_EXT_TERM_DATA, dest_len);
- ctx->reds -= dest_len;
+ if (ctxp)
+ (*ctxp)->reds -= dest_len;
}
state->exttmp = 1;
- if (ctx) {
+ if (ctxp) {
+ /*
+ * Start decompression by exporting trap context
+ * so we don't have to deal with deep-copying z_stream.
+ */
+ B2TContext* ctx = b2t_export_context(p, *ctxp);
+ ASSERT(state = &(*ctxp)->b2ts);
+ state = &ctx->b2ts;
+
if (erl_zlib_inflate_start(&ctx->u.uc.stream, bytes, size) != Z_OK)
return -1;
ctx->u.uc.dbytes = state->extp;
ctx->u.uc.dleft = dest_len;
ctx->state = B2TUncompressChunk;
+ *ctxp = ctx;
}
else {
uLongf dlen = dest_len;
@@ -1308,7 +1319,7 @@ erts_binary2term_prepare(ErtsBinary2TermState *state, byte *data, Sint data_size
{
Sint res;
- if (binary2term_prepare(state, data, data_size, NULL) < 0 ||
+ if (binary2term_prepare(state, data, data_size, NULL, NULL) < 0 ||
(res=decoded_size(state->extp, state->extp + state->extsize, 0, NULL)) < 0) {
if (state->exttmp)
@@ -1435,7 +1446,7 @@ static Eterm binary_to_term_int(Process* p, Uint32 flags, Eterm bin, Binary* con
if (ctx->aligned_alloc) {
ctx->reds -= bin_size / 8;
}
- if (binary2term_prepare(&ctx->b2ts, bytes, bin_size, ctx) < 0) {
+ if (binary2term_prepare(&ctx->b2ts, bytes, bin_size, &ctx, p) < 0) {
ctx->state = B2TBadArg;
}
break;
_END_PATCH
}
case "$1" in
version)
echo "$KERL_VERSION"
exit 0
;;
build)
if [ "$2" = 'git' ]; then
if [ $# -ne 5 ]; then
echo "usage: $0 $1 $2 <git_url> <git_version> <build_name>"
exit 1
fi
do_git_build "$3" "$4" "$5"
else
if [ $# -lt 3 ]; then
echo "usage: $0 $1 <release> <build_name>"
exit 1
fi
do_normal_build "$2" "$3"
fi
;;
install)
if [ $# -lt 2 ]; then
echo "usage: $0 $1 <build_name> [directory]"
exit 1
fi
if [ $# -eq 3 ]; then
do_install "$2" "$3"
else
if [ -z "$KERL_DEFAULT_INSTALL_DIR" ]; then
do_install "$2" "$PWD"
else
do_install "$2" "$KERL_DEFAULT_INSTALL_DIR/$2"
fi
fi
;;
install-docsh)
ACTIVE_PATH="$(get_active_path)"
if [ -n "$ACTIVE_PATH" ]; then
ACTIVE_NAME="$(get_name_from_install_path "$ACTIVE_PATH")"
if [ -z "$ACTIVE_NAME" ]; then
## TODO: Are git builds installed the usual way
## or do we need this clause to provide a fallback?
#BUILDNAME="$(basename "$ACTIVE_PATH")"
echo "$ACTIVE_PATH is not a kerl installation"
exit 1
else
BUILDNAME="$ACTIVE_NAME"
fi
install_docsh "$BUILDNAME" "$ACTIVE_PATH"
echo 'Please kerl_deactivate and activate again to enable docsh'
else
echo 'No Erlang/OTP installation is currently active - cannot install docsh'
exit 1
fi
;;
deploy)
if [ $# -lt 2 ]; then
echo "usage: $0 $1 <[user@]host> [directory] [remote_directory]"
exit 1
fi
if [ $# -eq 4 ]; then
do_deploy "$2" "$3" "$4"
else
if [ $# -eq 3 ]; then
do_deploy "$2" "$3"
else
do_deploy "$2" .
fi
fi
;;
update)
if [ $# -lt 2 ]; then
update_usage
exit 1
fi
case "$2" in
releases)
rm -f "${KERL_BASE_DIR:?}"/otp_releases
check_releases
echo 'The available releases are:'
list_print releases
;;
*)
update_usage
exit 1
;;
esac
;;
list)
if [ $# -ne 2 ]; then
list_usage
exit 1
fi
case "$2" in
releases)
check_releases
list_print "$2"
echo "Run '$0 update releases' to update this list from erlang.org"
;;
builds)
list_print "$2"
;;
installations)
list_print "$2"
;;
*)
echo "Cannot list $2"
list_usage
exit 1
;;
esac
;;
path)
# Usage:
# kerl path
# # Print currently active installation path, else non-zero exit
# kerl path <install>
# Print path to installation with name <install>, else non-zero exit
if [ -z "$2" ]; then
activepath=$(get_active_path)
if [ -z "$activepath" ]; then
echo 'No active kerl-managed erlang installation'
exit 1
fi
echo "$activepath"
else
# There are some possible extensions to this we could
# consider, such as:
# - if 2+ matches: prefer one in a subdir from $PWD
# - prefer $KERL_DEFAULT_INSTALL_DIR
match=
for ins in $(list_print installations | cut -d' ' -f2); do
if [ "$(basename "$ins")" = "$2" ]; then
if [ -z "$match" ]; then
match="$ins"
else
echo 'Error: too many matching installations' >&2
exit 2
fi
fi
done
[ -n "$match" ] && echo "$match" && exit 0
echo 'Error: no matching installation found' >&2 && exit 1
fi
;;
delete)
if [ $# -ne 3 ]; then
delete_usage
exit 1
fi
case "$2" in
build)
rel="$(get_release_from_name "$3")"
if [ -d "${KERL_BUILD_DIR:?}/$3" ]; then
maybe_remove "${KERL_BUILD_DIR:?}/$3"
else
if [ -z "$rel" ]; then
echo "No build named $3"
exit 1
fi
fi
list_remove "$2"s "$rel,$3"
echo "The $3 build has been deleted"
;;
installation)
assert_valid_installation "$3"
if [ -d "$3" ]; then
maybe_remove "$3"
else
maybe_remove "$(get_install_path_from_name "$3")"
fi
escaped="$(echo "$3" | sed $SED_OPT -e 's#/$##' -e 's#\/#\\\/#g')"
list_remove "$2"s "$escaped"
echo "The installation \"$3\" has been deleted"
;;
*)
echo "Cannot delete $2"
delete_usage
exit 1
;;
esac
;;
active)
if ! do_active; then
exit 1;
fi
;;
plt)
ACTIVE_PATH=$(get_active_path)
if ! do_plt "$ACTIVE_PATH"; then
exit 1;
fi
;;
status)
echo 'Available builds:'
list_print builds
echo '----------'
echo 'Available installations:'
list_print installations
echo '----------'
if do_active; then
ACTIVE_PATH=$(get_active_path)
if [ -n "$ACTIVE_PATH" ]; then
do_plt "$ACTIVE_PATH"
print_buildopts "$ACTIVE_PATH"
else
echo 'No Erlang/OTP installation is currently active'
exit 1
fi
fi
exit 0
;;
prompt)
FMT=' (%s)'
if [ -n "$2" ]; then
FMT="$2"
fi
ACTIVE_PATH="$(get_active_path)"
if [ -n "$ACTIVE_PATH" ]; then
ACTIVE_NAME="$(get_name_from_install_path "$ACTIVE_PATH")"
if [ -z "$ACTIVE_NAME" ]; then
VALUE="$(basename "$ACTIVE_PATH")*"
else
VALUE="$ACTIVE_NAME"
fi
# shellcheck disable=SC2059
printf "$FMT" "$VALUE"
fi
exit 0
;;
cleanup)
if [ $# -ne 2 ]; then
cleanup_usage
exit 1
fi
case "$2" in
all)
echo 'Cleaning up compilation products for ALL builds'
rm -rf "${KERL_BUILD_DIR:?}"/*
rm -rf "${KERL_DOWNLOAD_DIR:?}"/*
rm -rf "${KERL_GIT_DIR:?}"/*
echo "Cleaned up all compilation products under $KERL_BUILD_DIR"
;;
*)
echo "Cleaning up compilation products for $3"
rm -rf "${KERL_BUILD_DIR:?}/$3"
echo "Cleaned up compilation products for $3 under $KERL_BUILD_DIR"
;;
esac
;;
*)
echo "unknown command: $1"; usage; exit 1
;;
esac