Fileku / uv-installer.sh
bungandri12's picture
Upload uv-installer.sh
65b3ce7 verified
#!/bin/sh
# shellcheck shell=dash
#
# Licensed under the MIT license
# <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
# option. This file may not be copied, modified, or distributed
# except according to those terms.
if [ "$KSH_VERSION" = 'Version JM 93t+ 2010-03-05' ]; then
# The version of ksh93 that ships with many illumos systems does not
# support the "local" extension. Print a message rather than fail in
# subtle ways later on:
echo 'this installer does not work with this ksh93 version; please try bash!' >&2
exit 1
fi
set -u
APP_NAME="uv"
APP_VERSION="0.5.0"
# Look for GitHub Enterprise-style base URL first
if [ -n "${UV_INSTALLER_GHE_BASE_URL:-}" ]; then
INSTALLER_BASE_URL="$UV_INSTALLER_GHE_BASE_URL"
else
INSTALLER_BASE_URL="${UV_INSTALLER_GITHUB_BASE_URL:-https://github.com}"
fi
if [ -n "${INSTALLER_DOWNLOAD_URL:-}" ]; then
ARTIFACT_DOWNLOAD_URL="$INSTALLER_DOWNLOAD_URL"
else
ARTIFACT_DOWNLOAD_URL="${INSTALLER_BASE_URL}/astral-sh/uv/releases/download/0.5.0"
fi
PRINT_VERBOSE=${INSTALLER_PRINT_VERBOSE:-0}
PRINT_QUIET=${INSTALLER_PRINT_QUIET:-0}
if [ -n "${UV_NO_MODIFY_PATH:-}" ]; then
NO_MODIFY_PATH="$UV_NO_MODIFY_PATH"
else
NO_MODIFY_PATH=${INSTALLER_NO_MODIFY_PATH:-0}
fi
if [ "${UV_DISABLE_UPDATE:-0}" = "1" ]; then
INSTALL_UPDATER=0
else
INSTALL_UPDATER=1
fi
UNMANAGED_INSTALL="${UV_UNMANAGED_INSTALL:-}"
if [ -n "${UNMANAGED_INSTALL}" ]; then
NO_MODIFY_PATH=1
INSTALL_UPDATER=0
fi
read -r RECEIPT <<EORECEIPT
{"binaries":["CARGO_DIST_BINS"],"binary_aliases":{},"cdylibs":["CARGO_DIST_DYLIBS"],"cstaticlibs":["CARGO_DIST_STATICLIBS"],"install_layout":"unspecified","install_prefix":"AXO_INSTALL_PREFIX","modify_path":true,"provider":{"source":"cargo-dist","version":"0.25.1"},"source":{"app_name":"uv","name":"uv","owner":"astral-sh","release_type":"github"},"version":"0.5.0"}
EORECEIPT
RECEIPT_HOME="${HOME}/.config/uv"
usage() {
# print help (this cat/EOF stuff is a "heredoc" string)
cat <<EOF
uv-installer.sh
The installer for uv 0.5.0
This script detects what platform you're on and fetches an appropriate archive from
https://github.com/astral-sh/uv/releases/download/0.5.0
then unpacks the binaries and installs them to the first of the following locations
\$XDG_BIN_HOME
\$XDG_DATA_HOME/../bin
\$HOME/.local/bin
It will then add that dir to PATH by adding the appropriate line to your shell profiles.
USAGE:
uv-installer.sh [OPTIONS]
OPTIONS:
-v, --verbose
Enable verbose output
-q, --quiet
Disable progress output
--no-modify-path
Don't configure the PATH environment variable
-h, --help
Print help information
EOF
}
download_binary_and_run_installer() {
downloader --check
need_cmd uname
need_cmd mktemp
need_cmd chmod
need_cmd mkdir
need_cmd rm
need_cmd tar
need_cmd grep
need_cmd cat
for arg in "$@"; do
case "$arg" in
--help)
usage
exit 0
;;
--quiet)
PRINT_QUIET=1
;;
--verbose)
PRINT_VERBOSE=1
;;
--no-modify-path)
say "--no-modify-path has been deprecated; please set UV_NO_MODIFY_PATH=1 in the environment"
NO_MODIFY_PATH=1
;;
*)
OPTIND=1
if [ "${arg%%--*}" = "" ]; then
err "unknown option $arg"
fi
while getopts :hvq sub_arg "$arg"; do
case "$sub_arg" in
h)
usage
exit 0
;;
v)
# user wants to skip the prompt --
# we don't need /dev/tty
PRINT_VERBOSE=1
;;
q)
# user wants to skip the prompt --
# we don't need /dev/tty
PRINT_QUIET=1
;;
*)
err "unknown option -$OPTARG"
;;
esac
done
;;
esac
done
get_architecture || return 1
local _true_arch="$RETVAL"
assert_nz "$_true_arch" "arch"
local _cur_arch="$_true_arch"
# Lookup what archives support this platform
local _artifact_name
_artifact_name="$(select_archive_for_arch "$_true_arch")" || return 1
local _bins
local _zip_ext
local _arch
# try each archive, checking runtime conditions like libc versions
# accepting the first one that matches, as it's the best match
case "$_artifact_name" in
"uv-aarch64-apple-darwin.tar.gz")
_arch="aarch64-apple-darwin"
_zip_ext=".tar.gz"
_bins="uv uvx"
_bins_js_array='"uv","uvx"'
_libs=""
_libs_js_array=""
_staticlibs=""
_staticlibs_js_array=""
_updater_name=""
_updater_bin=""
;;
"uv-aarch64-unknown-linux-gnu.tar.gz")
_arch="aarch64-unknown-linux-gnu"
_zip_ext=".tar.gz"
_bins="uv uvx"
_bins_js_array='"uv","uvx"'
_libs=""
_libs_js_array=""
_staticlibs=""
_staticlibs_js_array=""
_updater_name=""
_updater_bin=""
;;
"uv-aarch64-unknown-linux-musl.tar.gz")
_arch="aarch64-unknown-linux-musl-static"
_zip_ext=".tar.gz"
_bins="uv uvx"
_bins_js_array='"uv","uvx"'
_libs=""
_libs_js_array=""
_staticlibs=""
_staticlibs_js_array=""
_updater_name=""
_updater_bin=""
;;
"uv-arm-unknown-linux-musleabihf.tar.gz")
_arch="arm-unknown-linux-musl-staticeabihf"
_zip_ext=".tar.gz"
_bins="uv uvx"
_bins_js_array='"uv","uvx"'
_libs=""
_libs_js_array=""
_staticlibs=""
_staticlibs_js_array=""
_updater_name=""
_updater_bin=""
;;
"uv-armv7-unknown-linux-gnueabihf.tar.gz")
_arch="armv7-unknown-linux-gnueabihf"
_zip_ext=".tar.gz"
_bins="uv uvx"
_bins_js_array='"uv","uvx"'
_libs=""
_libs_js_array=""
_staticlibs=""
_staticlibs_js_array=""
_updater_name=""
_updater_bin=""
;;
"uv-armv7-unknown-linux-musleabihf.tar.gz")
_arch="armv7-unknown-linux-musl-staticeabihf"
_zip_ext=".tar.gz"
_bins="uv uvx"
_bins_js_array='"uv","uvx"'
_libs=""
_libs_js_array=""
_staticlibs=""
_staticlibs_js_array=""
_updater_name=""
_updater_bin=""
;;
"uv-i686-pc-windows-msvc.zip")
_arch="i686-pc-windows-msvc"
_zip_ext=".zip"
_bins="uv.exe uvx.exe"
_bins_js_array='"uv.exe","uvx.exe"'
_libs=""
_libs_js_array=""
_staticlibs=""
_staticlibs_js_array=""
_updater_name=""
_updater_bin=""
;;
"uv-i686-unknown-linux-gnu.tar.gz")
_arch="i686-unknown-linux-gnu"
_zip_ext=".tar.gz"
_bins="uv uvx"
_bins_js_array='"uv","uvx"'
_libs=""
_libs_js_array=""
_staticlibs=""
_staticlibs_js_array=""
_updater_name=""
_updater_bin=""
;;
"uv-i686-unknown-linux-musl.tar.gz")
_arch="i686-unknown-linux-musl-static"
_zip_ext=".tar.gz"
_bins="uv uvx"
_bins_js_array='"uv","uvx"'
_libs=""
_libs_js_array=""
_staticlibs=""
_staticlibs_js_array=""
_updater_name=""
_updater_bin=""
;;
"uv-powerpc64-unknown-linux-gnu.tar.gz")
_arch="powerpc64-unknown-linux-gnu"
_zip_ext=".tar.gz"
_bins="uv uvx"
_bins_js_array='"uv","uvx"'
_libs=""
_libs_js_array=""
_staticlibs=""
_staticlibs_js_array=""
_updater_name=""
_updater_bin=""
;;
"uv-powerpc64le-unknown-linux-gnu.tar.gz")
_arch="powerpc64le-unknown-linux-gnu"
_zip_ext=".tar.gz"
_bins="uv uvx"
_bins_js_array='"uv","uvx"'
_libs=""
_libs_js_array=""
_staticlibs=""
_staticlibs_js_array=""
_updater_name=""
_updater_bin=""
;;
"uv-s390x-unknown-linux-gnu.tar.gz")
_arch="s390x-unknown-linux-gnu"
_zip_ext=".tar.gz"
_bins="uv uvx"
_bins_js_array='"uv","uvx"'
_libs=""
_libs_js_array=""
_staticlibs=""
_staticlibs_js_array=""
_updater_name=""
_updater_bin=""
;;
"uv-x86_64-apple-darwin.tar.gz")
_arch="x86_64-apple-darwin"
_zip_ext=".tar.gz"
_bins="uv uvx"
_bins_js_array='"uv","uvx"'
_libs=""
_libs_js_array=""
_staticlibs=""
_staticlibs_js_array=""
_updater_name=""
_updater_bin=""
;;
"uv-x86_64-pc-windows-msvc.zip")
_arch="x86_64-pc-windows-msvc"
_zip_ext=".zip"
_bins="uv.exe uvx.exe"
_bins_js_array='"uv.exe","uvx.exe"'
_libs=""
_libs_js_array=""
_staticlibs=""
_staticlibs_js_array=""
_updater_name=""
_updater_bin=""
;;
"uv-x86_64-unknown-linux-gnu.tar.gz")
_arch="x86_64-unknown-linux-gnu"
_zip_ext=".tar.gz"
_bins="uv uvx"
_bins_js_array='"uv","uvx"'
_libs=""
_libs_js_array=""
_staticlibs=""
_staticlibs_js_array=""
_updater_name=""
_updater_bin=""
;;
"uv-x86_64-unknown-linux-musl.tar.gz")
_arch="x86_64-unknown-linux-musl-static"
_zip_ext=".tar.gz"
_bins="uv uvx"
_bins_js_array='"uv","uvx"'
_libs=""
_libs_js_array=""
_staticlibs=""
_staticlibs_js_array=""
_updater_name=""
_updater_bin=""
;;
*)
err "internal installer error: selected download $_artifact_name doesn't exist!?"
;;
esac
# Replace the placeholder binaries with the calculated array from above
RECEIPT="$(echo "$RECEIPT" | sed s/'"CARGO_DIST_BINS"'/"$_bins_js_array"/)"
RECEIPT="$(echo "$RECEIPT" | sed s/'"CARGO_DIST_DYLIBS"'/"$_libs_js_array"/)"
RECEIPT="$(echo "$RECEIPT" | sed s/'"CARGO_DIST_STATICLIBS"'/"$_staticlibs_js_array"/)"
# download the archive
local _url="$ARTIFACT_DOWNLOAD_URL/$_artifact_name"
local _dir
_dir="$(ensure mktemp -d)" || return 1
local _file="$_dir/input$_zip_ext"
say "downloading $APP_NAME $APP_VERSION ${_arch}" 1>&2
say_verbose " from $_url" 1>&2
say_verbose " to $_file" 1>&2
ensure mkdir -p "$_dir"
if ! downloader "$_url" "$_file"; then
say "failed to download $_url"
say "this may be a standard network error, but it may also indicate"
say "that $APP_NAME's release process is not working. When in doubt"
say "please feel free to open an issue!"
exit 1
fi
# ...and then the updater, if it exists
if [ -n "$_updater_name" ] && [ "$INSTALL_UPDATER" = "1" ]; then
local _updater_url="$ARTIFACT_DOWNLOAD_URL/$_updater_name"
# This renames the artifact while doing the download, removing the
# target triple and leaving just the appname-update format
local _updater_file="$_dir/$APP_NAME-update"
if ! downloader "$_updater_url" "$_updater_file"; then
say "failed to download $_updater_url"
say "this may be a standard network error, but it may also indicate"
say "that $APP_NAME's release process is not working. When in doubt"
say "please feel free to open an issue!"
exit 1
fi
# Add the updater to the list of binaries to install
_bins="$_bins $APP_NAME-update"
fi
# unpack the archive
case "$_zip_ext" in
".zip")
ensure unzip -q "$_file" -d "$_dir"
;;
".tar."*)
ensure tar xf "$_file" --strip-components 1 -C "$_dir"
;;
*)
err "unknown archive format: $_zip_ext"
;;
esac
install "$_dir" "$_bins" "$_libs" "$_staticlibs" "$_arch" "$@"
local _retval=$?
if [ "$_retval" != 0 ]; then
return "$_retval"
fi
ignore rm -rf "$_dir"
# Install the install receipt
if [ "$INSTALL_UPDATER" = "1" ]; then
if ! mkdir -p "$RECEIPT_HOME"; then
err "unable to create receipt directory at $RECEIPT_HOME"
else
echo "$RECEIPT" > "$RECEIPT_HOME/$APP_NAME-receipt.json"
# shellcheck disable=SC2320
local _retval=$?
fi
else
local _retval=0
fi
return "$_retval"
}
# Replaces $HOME with the variable name for display to the user,
# only if $HOME is defined.
replace_home() {
local _str="$1"
if [ -n "${HOME:-}" ]; then
echo "$_str" | sed "s,$HOME,\$HOME,"
else
echo "$_str"
fi
}
json_binary_aliases() {
local _arch="$1"
case "$_arch" in
"aarch64-apple-darwin")
echo '{}'
;;
"aarch64-unknown-linux-gnu")
echo '{}'
;;
"aarch64-unknown-linux-musl-dynamic")
echo '{}'
;;
"aarch64-unknown-linux-musl-static")
echo '{}'
;;
"arm-unknown-linux-gnueabihf")
echo '{}'
;;
"arm-unknown-linux-musl-dynamiceabihf")
echo '{}'
;;
"arm-unknown-linux-musl-staticeabihf")
echo '{}'
;;
"armv7-unknown-linux-gnueabihf")
echo '{}'
;;
"armv7-unknown-linux-musl-dynamiceabihf")
echo '{}'
;;
"armv7-unknown-linux-musl-staticeabihf")
echo '{}'
;;
"i686-pc-windows-gnu")
echo '{}'
;;
"i686-unknown-linux-gnu")
echo '{}'
;;
"i686-unknown-linux-musl-dynamic")
echo '{}'
;;
"i686-unknown-linux-musl-static")
echo '{}'
;;
"powerpc64-unknown-linux-gnu")
echo '{}'
;;
"powerpc64le-unknown-linux-gnu")
echo '{}'
;;
"s390x-unknown-linux-gnu")
echo '{}'
;;
"x86_64-apple-darwin")
echo '{}'
;;
"x86_64-pc-windows-gnu")
echo '{}'
;;
"x86_64-unknown-linux-gnu")
echo '{}'
;;
"x86_64-unknown-linux-musl-dynamic")
echo '{}'
;;
"x86_64-unknown-linux-musl-static")
echo '{}'
;;
*)
echo '{}'
;;
esac
}
aliases_for_binary() {
local _bin="$1"
local _arch="$2"
case "$_arch" in
"aarch64-apple-darwin")
case "$_bin" in
*)
echo ""
;;
esac
;;
"aarch64-unknown-linux-gnu")
case "$_bin" in
*)
echo ""
;;
esac
;;
"aarch64-unknown-linux-musl-dynamic")
case "$_bin" in
*)
echo ""
;;
esac
;;
"aarch64-unknown-linux-musl-static")
case "$_bin" in
*)
echo ""
;;
esac
;;
"arm-unknown-linux-gnueabihf")
case "$_bin" in
*)
echo ""
;;
esac
;;
"arm-unknown-linux-musl-dynamiceabihf")
case "$_bin" in
*)
echo ""
;;
esac
;;
"arm-unknown-linux-musl-staticeabihf")
case "$_bin" in
*)
echo ""
;;
esac
;;
"armv7-unknown-linux-gnueabihf")
case "$_bin" in
*)
echo ""
;;
esac
;;
"armv7-unknown-linux-musl-dynamiceabihf")
case "$_bin" in
*)
echo ""
;;
esac
;;
"armv7-unknown-linux-musl-staticeabihf")
case "$_bin" in
*)
echo ""
;;
esac
;;
"i686-pc-windows-gnu")
case "$_bin" in
*)
echo ""
;;
esac
;;
"i686-unknown-linux-gnu")
case "$_bin" in
*)
echo ""
;;
esac
;;
"i686-unknown-linux-musl-dynamic")
case "$_bin" in
*)
echo ""
;;
esac
;;
"i686-unknown-linux-musl-static")
case "$_bin" in
*)
echo ""
;;
esac
;;
"powerpc64-unknown-linux-gnu")
case "$_bin" in
*)
echo ""
;;
esac
;;
"powerpc64le-unknown-linux-gnu")
case "$_bin" in
*)
echo ""
;;
esac
;;
"s390x-unknown-linux-gnu")
case "$_bin" in
*)
echo ""
;;
esac
;;
"x86_64-apple-darwin")
case "$_bin" in
*)
echo ""
;;
esac
;;
"x86_64-pc-windows-gnu")
case "$_bin" in
*)
echo ""
;;
esac
;;
"x86_64-unknown-linux-gnu")
case "$_bin" in
*)
echo ""
;;
esac
;;
"x86_64-unknown-linux-musl-dynamic")
case "$_bin" in
*)
echo ""
;;
esac
;;
"x86_64-unknown-linux-musl-static")
case "$_bin" in
*)
echo ""
;;
esac
;;
*)
echo ""
;;
esac
}
select_archive_for_arch() {
local _true_arch="$1"
local _archive
case "$_true_arch" in
"aarch64-apple-darwin")
_archive="uv-aarch64-apple-darwin.tar.gz"
if [ -n "$_archive" ]; then
echo "$_archive"
return 0
fi
_archive="uv-x86_64-apple-darwin.tar.gz"
if [ -n "$_archive" ]; then
echo "$_archive"
return 0
fi
;;
"aarch64-pc-windows-msvc")
_archive="uv-x86_64-pc-windows-msvc.zip"
if [ -n "$_archive" ]; then
echo "$_archive"
return 0
fi
_archive="uv-i686-pc-windows-msvc.zip"
if [ -n "$_archive" ]; then
echo "$_archive"
return 0
fi
;;
"aarch64-unknown-linux-gnu")
_archive="uv-aarch64-unknown-linux-gnu.tar.gz"
if ! check_glibc "2" "31"; then
_archive=""
fi
if [ -n "$_archive" ]; then
echo "$_archive"
return 0
fi
_archive="uv-aarch64-unknown-linux-musl.tar.gz"
if [ -n "$_archive" ]; then
echo "$_archive"
return 0
fi
;;
"aarch64-unknown-linux-musl-dynamic")
_archive="uv-aarch64-unknown-linux-musl.tar.gz"
if [ -n "$_archive" ]; then
echo "$_archive"
return 0
fi
;;
"aarch64-unknown-linux-musl-static")
_archive="uv-aarch64-unknown-linux-musl.tar.gz"
if [ -n "$_archive" ]; then
echo "$_archive"
return 0
fi
;;
"arm-unknown-linux-gnueabihf")
_archive="uv-arm-unknown-linux-musleabihf.tar.gz"
if [ -n "$_archive" ]; then
echo "$_archive"
return 0
fi
;;
"arm-unknown-linux-musl-dynamiceabihf")
_archive="uv-arm-unknown-linux-musleabihf.tar.gz"
if [ -n "$_archive" ]; then
echo "$_archive"
return 0
fi
;;
"arm-unknown-linux-musl-staticeabihf")
_archive="uv-arm-unknown-linux-musleabihf.tar.gz"
if [ -n "$_archive" ]; then
echo "$_archive"
return 0
fi
;;
"armv7-unknown-linux-gnueabihf")
_archive="uv-armv7-unknown-linux-gnueabihf.tar.gz"
if ! check_glibc "2" "31"; then
_archive=""
fi
if [ -n "$_archive" ]; then
echo "$_archive"
return 0
fi
_archive="uv-armv7-unknown-linux-musleabihf.tar.gz"
if [ -n "$_archive" ]; then
echo "$_archive"
return 0
fi
;;
"armv7-unknown-linux-musl-dynamiceabihf")
_archive="uv-armv7-unknown-linux-musleabihf.tar.gz"
if [ -n "$_archive" ]; then
echo "$_archive"
return 0
fi
;;
"armv7-unknown-linux-musl-staticeabihf")
_archive="uv-armv7-unknown-linux-musleabihf.tar.gz"
if [ -n "$_archive" ]; then
echo "$_archive"
return 0
fi
;;
"i686-pc-windows-gnu")
_archive="uv-i686-pc-windows-msvc.zip"
if [ -n "$_archive" ]; then
echo "$_archive"
return 0
fi
;;
"i686-pc-windows-msvc")
_archive="uv-i686-pc-windows-msvc.zip"
if [ -n "$_archive" ]; then
echo "$_archive"
return 0
fi
;;
"i686-unknown-linux-gnu")
_archive="uv-i686-unknown-linux-gnu.tar.gz"
if ! check_glibc "2" "31"; then
_archive=""
fi
if [ -n "$_archive" ]; then
echo "$_archive"
return 0
fi
_archive="uv-i686-unknown-linux-musl.tar.gz"
if [ -n "$_archive" ]; then
echo "$_archive"
return 0
fi
;;
"i686-unknown-linux-musl-dynamic")
_archive="uv-i686-unknown-linux-musl.tar.gz"
if [ -n "$_archive" ]; then
echo "$_archive"
return 0
fi
;;
"i686-unknown-linux-musl-static")
_archive="uv-i686-unknown-linux-musl.tar.gz"
if [ -n "$_archive" ]; then
echo "$_archive"
return 0
fi
;;
"powerpc64-unknown-linux-gnu")
_archive="uv-powerpc64-unknown-linux-gnu.tar.gz"
if ! check_glibc "2" "31"; then
_archive=""
fi
if [ -n "$_archive" ]; then
echo "$_archive"
return 0
fi
;;
"powerpc64le-unknown-linux-gnu")
_archive="uv-powerpc64le-unknown-linux-gnu.tar.gz"
if ! check_glibc "2" "31"; then
_archive=""
fi
if [ -n "$_archive" ]; then
echo "$_archive"
return 0
fi
;;
"s390x-unknown-linux-gnu")
_archive="uv-s390x-unknown-linux-gnu.tar.gz"
if ! check_glibc "2" "31"; then
_archive=""
fi
if [ -n "$_archive" ]; then
echo "$_archive"
return 0
fi
;;
"x86_64-apple-darwin")
_archive="uv-x86_64-apple-darwin.tar.gz"
if [ -n "$_archive" ]; then
echo "$_archive"
return 0
fi
;;
"x86_64-pc-windows-gnu")
_archive="uv-x86_64-pc-windows-msvc.zip"
if [ -n "$_archive" ]; then
echo "$_archive"
return 0
fi
;;
"x86_64-pc-windows-msvc")
_archive="uv-x86_64-pc-windows-msvc.zip"
if [ -n "$_archive" ]; then
echo "$_archive"
return 0
fi
_archive="uv-i686-pc-windows-msvc.zip"
if [ -n "$_archive" ]; then
echo "$_archive"
return 0
fi
;;
"x86_64-unknown-linux-gnu")
_archive="uv-x86_64-unknown-linux-gnu.tar.gz"
if ! check_glibc "2" "31"; then
_archive=""
fi
if [ -n "$_archive" ]; then
echo "$_archive"
return 0
fi
_archive="uv-x86_64-unknown-linux-musl.tar.gz"
if [ -n "$_archive" ]; then
echo "$_archive"
return 0
fi
;;
"x86_64-unknown-linux-musl-dynamic")
_archive="uv-x86_64-unknown-linux-musl.tar.gz"
if [ -n "$_archive" ]; then
echo "$_archive"
return 0
fi
;;
"x86_64-unknown-linux-musl-static")
_archive="uv-x86_64-unknown-linux-musl.tar.gz"
if [ -n "$_archive" ]; then
echo "$_archive"
return 0
fi
;;
*)
err "there isn't a download for your platform $_true_arch"
;;
esac
err "no compatible downloads were found for your platform $_true_arch"
}
check_glibc() {
local _min_glibc_major="$1"
local _min_glibc_series="$2"
# Parsing version out from line 1 like:
# ldd (Ubuntu GLIBC 2.35-0ubuntu3.1) 2.35
_local_glibc="$(ldd --version | awk -F' ' '{ if (FNR<=1) print $NF }')"
if [ "$(echo "${_local_glibc}" | awk -F. '{ print $1 }')" = "$_min_glibc_major" ] && [ "$(echo "${_local_glibc}" | awk -F. '{ print $2 }')" -ge "$_min_glibc_series" ]; then
return 0
else
say "System glibc version (\`${_local_glibc}') is too old; checking alternatives" >&2
return 1
fi
}
# See discussion of late-bound vs early-bound for why we use single-quotes with env vars
# shellcheck disable=SC2016
install() {
# This code needs to both compute certain paths for itself to write to, and
# also write them to shell/rc files so that they can look them up to e.g.
# add them to PATH. This requires an active distinction between paths
# and expressions that can compute them.
#
# The distinction lies in when we want env-vars to be evaluated. For instance
# if we determine that we want to install to $HOME/.myapp, which do we add
# to e.g. $HOME/.profile:
#
# * early-bound: export PATH="/home/myuser/.myapp:$PATH"
# * late-bound: export PATH="$HOME/.myapp:$PATH"
#
# In this case most people would prefer the late-bound version, but in other
# cases the early-bound version might be a better idea. In particular when using
# other env-vars than $HOME, they are more likely to be only set temporarily
# for the duration of this install script, so it's more advisable to erase their
# existence with early-bounding.
#
# This distinction is handled by "double-quotes" (early) vs 'single-quotes' (late).
#
# However if we detect that "$SOME_VAR/..." is a subdir of $HOME, we try to rewrite
# it to be '$HOME/...' to get the best of both worlds.
#
# This script has a few different variants, the most complex one being the
# CARGO_HOME version which attempts to install things to Cargo's bin dir,
# potentially setting up a minimal version if the user hasn't ever installed Cargo.
#
# In this case we need to:
#
# * Install to $HOME/.cargo/bin/
# * Create a shell script at $HOME/.cargo/env that:
# * Checks if $HOME/.cargo/bin/ is on PATH
# * and if not prepends it to PATH
# * Edits $HOME/.profile to run $HOME/.cargo/env (if the line doesn't exist)
#
# To do this we need these 4 values:
# The actual path we're going to install to
local _install_dir
# The directory C dynamic/static libraries install to
local _lib_install_dir
# The install prefix we write to the receipt.
# For organized install methods like CargoHome, which have
# subdirectories, this is the root without `/bin`. For other
# methods, this is the same as `_install_dir`.
local _receipt_install_dir
# Path to the an shell script that adds install_dir to PATH
local _env_script_path
# Potentially-late-bound version of install_dir to write env_script
local _install_dir_expr
# Potentially-late-bound version of env_script_path to write to rcfiles like $HOME/.profile
local _env_script_path_expr
# Forces the install to occur at this path, not the default
local _force_install_dir
# Which install layout to use - "flat" or "hierarchical"
local _install_layout="unspecified"
# Check the newer app-specific variable before falling back
# to the older generic one
if [ -n "${UV_INSTALL_DIR:-}" ]; then
_force_install_dir="$UV_INSTALL_DIR"
_install_layout="flat"
elif [ -n "${CARGO_DIST_FORCE_INSTALL_DIR:-}" ]; then
_force_install_dir="$CARGO_DIST_FORCE_INSTALL_DIR"
_install_layout="flat"
elif [ -n "$UNMANAGED_INSTALL" ]; then
_force_install_dir="$UNMANAGED_INSTALL"
_install_layout="flat"
fi
# Workaround for https://github.com/axodotdev/axoupdater/issues/210
# This was manually added to the installer post-release to patch the 0.4.30 -> 0.5.0 upgrade
if [ -n "${_force_install_dir:-}" ]; then
if [ "$_force_install_dir" = "${HOME:-}/.cargo" ] || [ "$_force_install_dir" = "${CARGO_HOME:-}" ]; then
_install_layout="cargo-home"
else
_install_layout="flat"
fi
fi
# Before actually consulting the configured install strategy, see
# if we're overriding it.
if [ -n "${_force_install_dir:-}" ]; then
case "$_install_layout" in
"hierarchical")
_install_dir="$_force_install_dir/bin"
_lib_install_dir="$_force_install_dir/lib"
_receipt_install_dir="$_force_install_dir"
_env_script_path="$_force_install_dir/env"
_install_dir_expr="$(replace_home "$_force_install_dir/bin")"
_env_script_path_expr="$(replace_home "$_force_install_dir/env")"
;;
"cargo-home")
_install_dir="$_force_install_dir/bin"
_lib_install_dir="$_force_install_dir/bin"
_receipt_install_dir="$_force_install_dir"
_env_script_path="$_force_install_dir/env"
_install_dir_expr="$(replace_home "$_force_install_dir/bin")"
_env_script_path_expr="$(replace_home "$_force_install_dir/env")"
;;
"flat")
_install_dir="$_force_install_dir"
_lib_install_dir="$_force_install_dir"
_receipt_install_dir="$_install_dir"
_env_script_path="$_force_install_dir/env"
_install_dir_expr="$(replace_home "$_force_install_dir")"
_env_script_path_expr="$(replace_home "$_force_install_dir/env")"
;;
*)
err "Unrecognized install layout: $_install_layout"
;;
esac
fi
if [ -z "${_install_dir:-}" ]; then
_install_layout="flat"
# Install to $XDG_BIN_HOME
if [ -n "${XDG_BIN_HOME:-}" ]; then
_install_dir="$XDG_BIN_HOME"
_lib_install_dir="$_install_dir"
_receipt_install_dir="$_install_dir"
_env_script_path="$XDG_BIN_HOME/env"
_install_dir_expr="$(replace_home "$_install_dir")"
_env_script_path_expr="$(replace_home "$_env_script_path")"
fi
fi
if [ -z "${_install_dir:-}" ]; then
_install_layout="flat"
# Install to $XDG_DATA_HOME/../bin
if [ -n "${XDG_DATA_HOME:-}" ]; then
_install_dir="$XDG_DATA_HOME/../bin"
_lib_install_dir="$_install_dir"
_receipt_install_dir="$_install_dir"
_env_script_path="$XDG_DATA_HOME/../bin/env"
_install_dir_expr="$(replace_home "$_install_dir")"
_env_script_path_expr="$(replace_home "$_env_script_path")"
fi
fi
if [ -z "${_install_dir:-}" ]; then
_install_layout="flat"
# Install to $HOME/.local/bin
if [ -n "${HOME:-}" ]; then
_install_dir="$HOME/.local/bin"
_lib_install_dir="$HOME/.local/bin"
_receipt_install_dir="$_install_dir"
_env_script_path="$HOME/.local/bin/env"
_install_dir_expr='$HOME/.local/bin'
_env_script_path_expr='$HOME/.local/bin/env'
fi
fi
if [ -z "$_install_dir_expr" ]; then
err "could not find a valid path to install to!"
fi
# Identical to the sh version, just with a .fish file extension
# We place it down here to wait until it's been assigned in every
# path.
_fish_env_script_path="${_env_script_path}.fish"
_fish_env_script_path_expr="${_env_script_path_expr}.fish"
# Replace the temporary cargo home with the calculated one
RECEIPT=$(echo "$RECEIPT" | sed "s,AXO_INSTALL_PREFIX,$_receipt_install_dir,")
# Also replace the aliases with the arch-specific one
RECEIPT=$(echo "$RECEIPT" | sed "s'\"binary_aliases\":{}'\"binary_aliases\":$(json_binary_aliases "$_arch")'")
# And replace the install layout
RECEIPT=$(echo "$RECEIPT" | sed "s'\"install_layout\":\"unspecified\"'\"install_layout\":\"$_install_layout\"'")
if [ "$NO_MODIFY_PATH" = "1" ]; then
RECEIPT=$(echo "$RECEIPT" | sed "s'\"modify_path\":true'\"modify_path\":false'")
fi
say "installing to $_install_dir"
ensure mkdir -p "$_install_dir"
ensure mkdir -p "$_lib_install_dir"
# copy all the binaries to the install dir
local _src_dir="$1"
local _bins="$2"
local _libs="$3"
local _staticlibs="$4"
local _arch="$5"
for _bin_name in $_bins; do
local _bin="$_src_dir/$_bin_name"
ensure mv "$_bin" "$_install_dir"
# unzip seems to need this chmod
ensure chmod +x "$_install_dir/$_bin_name"
for _dest in $(aliases_for_binary "$_bin_name" "$_arch"); do
ln -sf "$_install_dir/$_bin_name" "$_install_dir/$_dest"
done
say " $_bin_name"
done
# Like the above, but no aliases
for _lib_name in $_libs; do
local _lib="$_src_dir/$_lib_name"
ensure mv "$_lib" "$_lib_install_dir"
# unzip seems to need this chmod
ensure chmod +x "$_lib_install_dir/$_lib_name"
say " $_lib_name"
done
for _lib_name in $_staticlibs; do
local _lib="$_src_dir/$_lib_name"
ensure mv "$_lib" "$_lib_install_dir"
# unzip seems to need this chmod
ensure chmod +x "$_lib_install_dir/$_lib_name"
say " $_lib_name"
done
say "everything's installed!"
# Avoid modifying the users PATH if they are managing their PATH manually
case :$PATH:
in *:$_install_dir:*) NO_MODIFY_PATH=1 ;;
*) ;;
esac
if [ "0" = "$NO_MODIFY_PATH" ]; then
add_install_dir_to_ci_path "$_install_dir"
add_install_dir_to_path "$_install_dir_expr" "$_env_script_path" "$_env_script_path_expr" ".profile" "sh"
exit1=$?
shotgun_install_dir_to_path "$_install_dir_expr" "$_env_script_path" "$_env_script_path_expr" ".profile .bashrc .bash_profile .bash_login" "sh"
exit2=$?
add_install_dir_to_path "$_install_dir_expr" "$_env_script_path" "$_env_script_path_expr" ".zshrc .zshenv" "sh"
exit3=$?
# This path may not exist by default
ensure mkdir -p "$HOME/.config/fish/conf.d"
exit4=$?
add_install_dir_to_path "$_install_dir_expr" "$_fish_env_script_path" "$_fish_env_script_path_expr" ".config/fish/conf.d/$APP_NAME.env.fish" "fish"
exit5=$?
if [ "${exit1:-0}" = 1 ] || [ "${exit2:-0}" = 1 ] || [ "${exit3:-0}" = 1 ] || [ "${exit4:-0}" = 1 ] || [ "${exit5:-0}" = 1 ]; then
say ""
say "To add $_install_dir_expr to your PATH, either restart your shell or run:"
say ""
say " source $_env_script_path_expr (sh, bash, zsh)"
say " source $_fish_env_script_path_expr (fish)"
fi
fi
}
print_home_for_script() {
local script="$1"
local _home
case "$script" in
# zsh has a special ZDOTDIR directory, which if set
# should be considered instead of $HOME
.zsh*)
if [ -n "${ZDOTDIR:-}" ]; then
_home="$ZDOTDIR"
else
_home="$HOME"
fi
;;
*)
_home="$HOME"
;;
esac
echo "$_home"
}
add_install_dir_to_ci_path() {
# Attempt to do CI-specific rituals to get the install-dir on PATH faster
local _install_dir="$1"
# If GITHUB_PATH is present, then write install_dir to the file it refs.
# After each GitHub Action, the contents will be added to PATH.
# So if you put a curl | sh for this script in its own "run" step,
# the next step will have this dir on PATH.
#
# Note that GITHUB_PATH will not resolve any variables, so we in fact
# want to write install_dir and not install_dir_expr
if [ -n "${GITHUB_PATH:-}" ]; then
ensure echo "$_install_dir" >> "$GITHUB_PATH"
fi
}
add_install_dir_to_path() {
# Edit rcfiles ($HOME/.profile) to add install_dir to $PATH
#
# We do this slightly indirectly by creating an "env" shell script which checks if install_dir
# is on $PATH already, and prepends it if not. The actual line we then add to rcfiles
# is to just source that script. This allows us to blast it into lots of different rcfiles and
# have it run multiple times without causing problems. It's also specifically compatible
# with the system rustup uses, so that we don't conflict with it.
local _install_dir_expr="$1"
local _env_script_path="$2"
local _env_script_path_expr="$3"
local _rcfiles="$4"
local _shell="$5"
if [ -n "${HOME:-}" ]; then
local _target
local _home
# Find the first file in the array that exists and choose
# that as our target to write to
for _rcfile_relative in $_rcfiles; do
_home="$(print_home_for_script "$_rcfile_relative")"
local _rcfile="$_home/$_rcfile_relative"
if [ -f "$_rcfile" ]; then
_target="$_rcfile"
break
fi
done
# If we didn't find anything, pick the first entry in the
# list as the default to create and write to
if [ -z "${_target:-}" ]; then
local _rcfile_relative
_rcfile_relative="$(echo "$_rcfiles" | awk '{ print $1 }')"
_home="$(print_home_for_script "$_rcfile_relative")"
_target="$_home/$_rcfile_relative"
fi
# `source x` is an alias for `. x`, and the latter is more portable/actually-posix.
# This apparently comes up a lot on freebsd. It's easy enough to always add
# the more robust line to rcfiles, but when telling the user to apply the change
# to their current shell ". x" is pretty easy to misread/miscopy, so we use the
# prettier "source x" line there. Hopefully people with Weird Shells are aware
# this is a thing and know to tweak it (or just restart their shell).
local _robust_line=". \"$_env_script_path_expr\""
local _pretty_line="source \"$_env_script_path_expr\""
# Add the env script if it doesn't already exist
if [ ! -f "$_env_script_path" ]; then
say_verbose "creating $_env_script_path"
if [ "$_shell" = "sh" ]; then
write_env_script_sh "$_install_dir_expr" "$_env_script_path"
else
write_env_script_fish "$_install_dir_expr" "$_env_script_path"
fi
else
say_verbose "$_env_script_path already exists"
fi
# Check if the line is already in the rcfile
# grep: 0 if matched, 1 if no match, and 2 if an error occurred
#
# Ideally we could use quiet grep (-q), but that makes "match" and "error"
# have the same behaviour, when we want "no match" and "error" to be the same
# (on error we want to create the file, which >> conveniently does)
#
# We search for both kinds of line here just to do the right thing in more cases.
if ! grep -F "$_robust_line" "$_target" > /dev/null 2>/dev/null && \
! grep -F "$_pretty_line" "$_target" > /dev/null 2>/dev/null
then
# If the script now exists, add the line to source it to the rcfile
# (This will also create the rcfile if it doesn't exist)
if [ -f "$_env_script_path" ]; then
local _line
# Fish has deprecated `.` as an alias for `source` and
# it will be removed in a later version.
# https://fishshell.com/docs/current/cmds/source.html
# By contrast, `.` is the traditional syntax in sh and
# `source` isn't always supported in all circumstances.
if [ "$_shell" = "fish" ]; then
_line="$_pretty_line"
else
_line="$_robust_line"
fi
say_verbose "adding $_line to $_target"
# prepend an extra newline in case the user's file is missing a trailing one
ensure echo "" >> "$_target"
ensure echo "$_line" >> "$_target"
return 1
fi
else
say_verbose "$_install_dir already on PATH"
fi
fi
}
shotgun_install_dir_to_path() {
# Edit rcfiles ($HOME/.profile) to add install_dir to $PATH
# (Shotgun edition - write to all provided files that exist rather than just the first)
local _install_dir_expr="$1"
local _env_script_path="$2"
local _env_script_path_expr="$3"
local _rcfiles="$4"
local _shell="$5"
if [ -n "${HOME:-}" ]; then
local _found=false
local _home
for _rcfile_relative in $_rcfiles; do
_home="$(print_home_for_script "$_rcfile_relative")"
local _rcfile_abs="$_home/$_rcfile_relative"
if [ -f "$_rcfile_abs" ]; then
_found=true
add_install_dir_to_path "$_install_dir_expr" "$_env_script_path" "$_env_script_path_expr" "$_rcfile_relative" "$_shell"
fi
done
# Fall through to previous "create + write to first file in list" behavior
if [ "$_found" = false ]; then
add_install_dir_to_path "$_install_dir_expr" "$_env_script_path" "$_env_script_path_expr" "$_rcfiles" "$_shell"
fi
fi
}
write_env_script_sh() {
# write this env script to the given path (this cat/EOF stuff is a "heredoc" string)
local _install_dir_expr="$1"
local _env_script_path="$2"
ensure cat <<EOF > "$_env_script_path"
#!/bin/sh
# add binaries to PATH if they aren't added yet
# affix colons on either side of \$PATH to simplify matching
case ":\${PATH}:" in
*:"$_install_dir_expr":*)
;;
*)
# Prepending path in case a system-installed binary needs to be overridden
export PATH="$_install_dir_expr:\$PATH"
;;
esac
EOF
}
write_env_script_fish() {
# write this env script to the given path (this cat/EOF stuff is a "heredoc" string)
local _install_dir_expr="$1"
local _env_script_path="$2"
ensure cat <<EOF > "$_env_script_path"
if not contains "$_install_dir_expr" \$PATH
# Prepending path in case a system-installed binary needs to be overridden
set -x PATH "$_install_dir_expr" \$PATH
end
EOF
}
check_proc() {
# Check for /proc by looking for the /proc/self/exe link
# This is only run on Linux
if ! test -L /proc/self/exe ; then
err "fatal: Unable to find /proc/self/exe. Is /proc mounted? Installation cannot proceed without /proc."
fi
}
get_bitness() {
need_cmd head
# Architecture detection without dependencies beyond coreutils.
# ELF files start out "\x7fELF", and the following byte is
# 0x01 for 32-bit and
# 0x02 for 64-bit.
# The printf builtin on some shells like dash only supports octal
# escape sequences, so we use those.
local _current_exe_head
_current_exe_head=$(head -c 5 /proc/self/exe )
if [ "$_current_exe_head" = "$(printf '\177ELF\001')" ]; then
echo 32
elif [ "$_current_exe_head" = "$(printf '\177ELF\002')" ]; then
echo 64
else
err "unknown platform bitness"
fi
}
is_host_amd64_elf() {
need_cmd head
need_cmd tail
# ELF e_machine detection without dependencies beyond coreutils.
# Two-byte field at offset 0x12 indicates the CPU,
# but we're interested in it being 0x3E to indicate amd64, or not that.
local _current_exe_machine
_current_exe_machine=$(head -c 19 /proc/self/exe | tail -c 1)
[ "$_current_exe_machine" = "$(printf '\076')" ]
}
get_endianness() {
local cputype=$1
local suffix_eb=$2
local suffix_el=$3
# detect endianness without od/hexdump, like get_bitness() does.
need_cmd head
need_cmd tail
local _current_exe_endianness
_current_exe_endianness="$(head -c 6 /proc/self/exe | tail -c 1)"
if [ "$_current_exe_endianness" = "$(printf '\001')" ]; then
echo "${cputype}${suffix_el}"
elif [ "$_current_exe_endianness" = "$(printf '\002')" ]; then
echo "${cputype}${suffix_eb}"
else
err "unknown platform endianness"
fi
}
get_architecture() {
local _ostype
local _cputype
_ostype="$(uname -s)"
_cputype="$(uname -m)"
local _clibtype="gnu"
local _local_glibc
if [ "$_ostype" = Linux ]; then
if [ "$(uname -o)" = Android ]; then
_ostype=Android
fi
if ldd --version 2>&1 | grep -q 'musl'; then
_clibtype="musl-dynamic"
else
# Assume all other linuxes are glibc (even if wrong, static libc fallback will apply)
_clibtype="gnu"
fi
fi
if [ "$_ostype" = Darwin ] && [ "$_cputype" = i386 ]; then
# Darwin `uname -m` lies
if sysctl hw.optional.x86_64 | grep -q ': 1'; then
_cputype=x86_64
fi
fi
if [ "$_ostype" = Darwin ] && [ "$_cputype" = x86_64 ]; then
# Rosetta on aarch64
if [ "$(sysctl -n hw.optional.arm64 2>/dev/null)" = "1" ]; then
_cputype=aarch64
fi
fi
if [ "$_ostype" = SunOS ]; then
# Both Solaris and illumos presently announce as "SunOS" in "uname -s"
# so use "uname -o" to disambiguate. We use the full path to the
# system uname in case the user has coreutils uname first in PATH,
# which has historically sometimes printed the wrong value here.
if [ "$(/usr/bin/uname -o)" = illumos ]; then
_ostype=illumos
fi
# illumos systems have multi-arch userlands, and "uname -m" reports the
# machine hardware name; e.g., "i86pc" on both 32- and 64-bit x86
# systems. Check for the native (widest) instruction set on the
# running kernel:
if [ "$_cputype" = i86pc ]; then
_cputype="$(isainfo -n)"
fi
fi
case "$_ostype" in
Android)
_ostype=linux-android
;;
Linux)
check_proc
_ostype=unknown-linux-$_clibtype
_bitness=$(get_bitness)
;;
FreeBSD)
_ostype=unknown-freebsd
;;
NetBSD)
_ostype=unknown-netbsd
;;
DragonFly)
_ostype=unknown-dragonfly
;;
Darwin)
_ostype=apple-darwin
;;
illumos)
_ostype=unknown-illumos
;;
MINGW* | MSYS* | CYGWIN* | Windows_NT)
_ostype=pc-windows-gnu
;;
*)
err "unrecognized OS type: $_ostype"
;;
esac
case "$_cputype" in
i386 | i486 | i686 | i786 | x86)
_cputype=i686
;;
xscale | arm)
_cputype=arm
if [ "$_ostype" = "linux-android" ]; then
_ostype=linux-androideabi
fi
;;
armv6l)
_cputype=arm
if [ "$_ostype" = "linux-android" ]; then
_ostype=linux-androideabi
else
_ostype="${_ostype}eabihf"
fi
;;
armv7l | armv8l)
_cputype=armv7
if [ "$_ostype" = "linux-android" ]; then
_ostype=linux-androideabi
else
_ostype="${_ostype}eabihf"
fi
;;
aarch64 | arm64)
_cputype=aarch64
;;
x86_64 | x86-64 | x64 | amd64)
_cputype=x86_64
;;
mips)
_cputype=$(get_endianness mips '' el)
;;
mips64)
if [ "$_bitness" -eq 64 ]; then
# only n64 ABI is supported for now
_ostype="${_ostype}abi64"
_cputype=$(get_endianness mips64 '' el)
fi
;;
ppc)
_cputype=powerpc
;;
ppc64)
_cputype=powerpc64
;;
ppc64le)
_cputype=powerpc64le
;;
s390x)
_cputype=s390x
;;
riscv64)
_cputype=riscv64gc
;;
loongarch64)
_cputype=loongarch64
;;
*)
err "unknown CPU type: $_cputype"
esac
# Detect 64-bit linux with 32-bit userland
if [ "${_ostype}" = unknown-linux-gnu ] && [ "${_bitness}" -eq 32 ]; then
case $_cputype in
x86_64)
# 32-bit executable for amd64 = x32
if is_host_amd64_elf; then {
err "x32 linux unsupported"
}; else
_cputype=i686
fi
;;
mips64)
_cputype=$(get_endianness mips '' el)
;;
powerpc64)
_cputype=powerpc
;;
aarch64)
_cputype=armv7
if [ "$_ostype" = "linux-android" ]; then
_ostype=linux-androideabi
else
_ostype="${_ostype}eabihf"
fi
;;
riscv64gc)
err "riscv64 with 32-bit userland unsupported"
;;
esac
fi
# treat armv7 systems without neon as plain arm
if [ "$_ostype" = "unknown-linux-gnueabihf" ] && [ "$_cputype" = armv7 ]; then
if ensure grep '^Features' /proc/cpuinfo | grep -q -v neon; then
# At least one processor does not have NEON.
_cputype=arm
fi
fi
_arch="${_cputype}-${_ostype}"
RETVAL="$_arch"
}
say() {
if [ "0" = "$PRINT_QUIET" ]; then
echo "$1"
fi
}
say_verbose() {
if [ "1" = "$PRINT_VERBOSE" ]; then
echo "$1"
fi
}
err() {
if [ "0" = "$PRINT_QUIET" ]; then
local red
local reset
red=$(tput setaf 1 2>/dev/null || echo '')
reset=$(tput sgr0 2>/dev/null || echo '')
say "${red}ERROR${reset}: $1" >&2
fi
exit 1
}
need_cmd() {
if ! check_cmd "$1"
then err "need '$1' (command not found)"
fi
}
check_cmd() {
command -v "$1" > /dev/null 2>&1
return $?
}
assert_nz() {
if [ -z "$1" ]; then err "assert_nz $2"; fi
}
# Run a command that should never fail. If the command fails execution
# will immediately terminate with an error showing the failing
# command.
ensure() {
if ! "$@"; then err "command failed: $*"; fi
}
# This is just for indicating that commands' results are being
# intentionally ignored. Usually, because it's being executed
# as part of error handling.
ignore() {
"$@"
}
# This wraps curl or wget. Try curl first, if not installed,
# use wget instead.
downloader() {
if check_cmd curl
then _dld=curl
elif check_cmd wget
then _dld=wget
else _dld='curl or wget' # to be used in error message of need_cmd
fi
if [ "$1" = --check ]
then need_cmd "$_dld"
elif [ "$_dld" = curl ]
then curl -sSfL "$1" -o "$2"
elif [ "$_dld" = wget ]
then wget "$1" -O "$2"
else err "Unknown downloader" # should not reach here
fi
}
download_binary_and_run_installer "$@" || exit 1