#ft=bash bail() ( echo >&2 "ERROR: $1" exit 1 ) must_be_root() ( if [ "$(id --user)" != 0 ]; then bail "must run as root" fi ) set_link() ( TARGET=${1} APP_DIR=${2} APP_PATH=${3-} pushd "$(dirname "${TARGET}")" >/dev/null || exit 1 unlink_if_set "${TARGET}" REL_PATH=$(relative_path "$(dirname "${TARGET}")" "${APP_DIR}/current/${APP_PATH}") ln -s "${REL_PATH}" "$(basename "${TARGET}")" popd >/dev/null || exit 1 ) get_os() ( case $(uname -s) in Linux*) echo linux ;; Darwin*) echo darwin ;; Dragonfly*) echo dragonfly ;; FreeBSD*) echo freebsd ;; NetBSD*) echo netbsd ;; OpenBSD*) echo openbsd ;; SunOS*) echo solaris ;; Windows_NT*) echo windows ;; CYGWIN_NT*) echo windows ;; *) echo >&2 "unsupported os" return ;; esac ) get_arch() ( case $(uname -m) in x86_64*) echo amd64 ;; amd64*) echo amd64 ;; i386*) echo 386 ;; i686*) echo 386 ;; arm) echo arm ;; armv7*) echo arm ;; armv6*) echo arm ;; armv8*) echo arm ;; aarch64*) echo arm64 ;; *) echo >&2 "unsupported architecture: $(uname -m)" exit 1 ;; esac ) set_current_link() ( prefix=${1} version=${2} sudo=${3-} current="${prefix}/current" if [ -L "${current}" ]; then $sudo unlink "${current}" fi rel="$(relative_path "${prefix}" "${prefix}/${version}")" $sudo ln -s "$rel" "${current}" ) unlink_if_set() ( dir=$1 sudo=${2-} if [ -L "${dir}" ]; then # shellcheck disable=SC2086 ${sudo} unlink "${dir}" fi ) mkdir_if_missing() ( dir=${1} sudo=${2-} if [ ! -d "${dir}" ]; then # shellcheck disable=SC2086 $sudo mkdir -p "${dir}" fi ) extract_zip() ( url=${1} dest=${2} args=${3-} sudo=${4-} if [ -d "${dest}" ]; then return fi mkdir_if_missing "${dest}" "${sudo}" tmp_dir="$(mktemp -d)" zipfile=${tmp_dir}/release.zip curl --silent --location --output "${zipfile}" "${url}" # shellcheck disable=SC2086 $sudo unzip -o "${zipfile}" -d "${dest}" ${args} rm -rf "${tmp_dir}" ) extract_tarball() ( url=${1} dest=${2} args=${3-} sudo=${4-} if [ -d "${dest}" ]; then return fi mkdir_if_missing "${dest}" "${sudo}" tmp_dir="$(mktemp -d)" tarball=${tmp_dir}/release.tar.gz curl --silent --location --output "${tarball}" "${url}" # shellcheck disable=SC2086 $sudo tar xf "${tarball}" --directory "${dest}" ${args} rm -rf "${tmp_dir}" ) extract_binary() ( url=${1} dest=${2} sudo=${3-} if [ -f "${dest}" ]; then return fi mkdir_if_missing "$(dirname "${dest}")" "${sudo}" tmp_file="$(mktemp)" curl --silent --location --output "${tmp_file}" "${url}" $sudo chmod +x "${tmp_file}" $sudo mv "${tmp_file}" "${dest}" ) relative_path() ( # both $1 and $2 are absolute paths beginning with / # $1 must be a canonical path; that is none of its directory # components may be ".", ".." or a symbolic link # # returns relative path to $2/$target from $1/$src src=$1 target=$2 common_part=$src result= while [ "${target#"$common_part"}" = "$target" ]; do # no match, means that candidate common part is not correct # go up one level (reduce common part) common_part=$(dirname "$common_part") # and record that we went back, with correct / handling if [ -z "$result" ]; then result=.. else result=../$result fi done if [ "$common_part" = / ]; then # special case for root (no common path) result=$result/ fi # since we now have identified the common part, # compute the non-common part forward_part=${target#"$common_part"} # and now stick all parts together if [ -n "$result" ] && [ -n "$forward_part" ]; then result=$result$forward_part elif [ -n "$forward_part" ]; then # extra slash removal result=${forward_part#?} fi printf '%s' "$result" )