#ft=sh bail () { >&2 echo "ERROR: $1" exit 1 } must_be_root () { if [ "$(id --user)" != 0 ]; then bail "must run as root" fi } 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;; *) >&2 echo "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;; *) >&2 echo "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}" } 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" }