#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;; *) bail "unsupported os: $(uname -s)" ;; esac } get_arch () { case $(uname -m) in x86_64*) echo amd64;; amd64*) echo amd64;; *) bail "unsupported architecture: $(uname -m)" ;; esac } set_current_link () { prefix="${1}" version="${2}" sudo="${3}" current="${prefix}/current" if [ -s "${current}" ] ; then $sudo unlink "${current}" fi $sudo ln --symbolic --relative "${prefix}/${version}" "${current}" } extract_tarball () { url="${1}" dest="${2}" args="${3}" sudo="${4}" if [ -d "${dest}" ]; then return fi $sudo mkdir -p "${dest}" tmp_dir="$(mktemp --directory)" 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" }