set -eu
REPO="@REPO@"
BASE_URL="@BASE_URL@"
BINARIES="@BINARIES@"
INSTALL_DIR="${INSTALL_DIR:-@INSTALL_DIR@}"
VERIFY_CHECKSUM="@VERIFY_CHECKSUM@"
VERSION="${VERSION:-}"
info() { printf '%s\n' "@NAME@-install: $*" >&2; }
die() { printf '%s\n' "@NAME@-install: error: $*" >&2; exit 1; }
have() { command -v "$1" >/dev/null 2>&1; }
fetch() {
if have curl; then
curl -fsSL "$1" -o "$2"
elif have wget; then
wget -qO "$2" "$1"
else
die "need curl or wget to download files"
fi
}
fetch_stdout() {
if have curl; then
curl -fsSL "$1"
elif have wget; then
wget -qO- "$1"
else
die "need curl or wget to download files"
fi
}
detect_os() {
case "$(uname -s)" in
@DETECT_OS_CASES@
*) echo "unsupported" ;;
esac
}
detect_arch() {
case "$(uname -m)" in
@DETECT_ARCH_CASES@
*) echo "unsupported" ;;
esac
}
install_binary() {
_src="$1"
_name="$2"
dir="$INSTALL_DIR"
if [ -w "$dir" ]; then
install -m 0755 "$_src" "$dir/$_name"
elif have sudo; then
info "installing to $dir (requires sudo)"
sudo install -m 0755 "$_src" "$dir/$_name"
else
dir="$HOME/.local/bin"
info "no write access to $INSTALL_DIR and no sudo; installing to $dir"
mkdir -p "$dir"
install -m 0755 "$_src" "$dir/$_name"
case ":$PATH:" in
*":$dir:"*) ;;
*) info "note: $dir is not in your PATH; add it to run $_name" ;;
esac
fi
info "installed $_name $version to $dir/$_name"
}
if [ "$BASE_URL" = "https://github.com" ]; then
API_BASE="https://api.github.com"
else
API_BASE="$BASE_URL/api/v3"
fi
if [ -z "$VERSION" ]; then
info "resolving latest release of $REPO"
body=$(fetch_stdout "$API_BASE/repos/$REPO/releases/latest") \
|| die "failed to query the latest release of $REPO"
VERSION=$(printf '%s\n' "$body" |
grep -m1 '"tag_name"' |
sed -e 's/.*"tag_name"[[:space:]]*:[[:space:]]*"//' -e 's/".*//')
[ -n "$VERSION" ] || die "could not determine the latest release of $REPO"
fi
version="${VERSION#@TAG_PREFIX@}"
tag="@TAG_PREFIX@${version}"
CHECKSUMS="@CHECKSUMS@"
OS="$(detect_os)"
ARCH="$(detect_arch)"
ARCHIVE=""
case "${OS}-${ARCH}" in
@ASSET_CASES@
*) die "no prebuilt binary for ${OS}-${ARCH} (supported: @SUPPORTED_PLATFORMS@)" ;;
esac
tmp=$(mktemp -d)
trap 'rm -rf "$tmp"' EXIT INT TERM
base="$BASE_URL/$REPO/releases/download/$tag"
info "downloading $ARCHIVE"
fetch "$base/$ARCHIVE" "$tmp/$ARCHIVE" || die "failed to download $ARCHIVE"
if [ "$VERIFY_CHECKSUM" = "true" ]; then
expected=""
if fetch "$base/$CHECKSUMS" "$tmp/$CHECKSUMS" 2>/dev/null; then
expected=$(awk -v f="$ARCHIVE" '$2 == f { print $1 }' "$tmp/$CHECKSUMS" | head -n1)
fi
if [ -z "$expected" ] && fetch "$base/$ARCHIVE.sha256" "$tmp/$ARCHIVE.sha256" 2>/dev/null; then
expected=$(awk '{ print $1 }' "$tmp/$ARCHIVE.sha256" | head -n1)
fi
[ -n "$expected" ] || die "no checksum published for $ARCHIVE"
if have sha256sum; then
actual=$(sha256sum "$tmp/$ARCHIVE" | awk '{ print $1 }')
elif have shasum; then
actual=$(shasum -a 256 "$tmp/$ARCHIVE" | awk '{ print $1 }')
else
die "need sha256sum or shasum to verify the download"
fi
[ "$expected" = "$actual" ] ||
die "checksum mismatch for $ARCHIVE (expected $expected, got $actual)"
info "checksum verified"
fi
info "extracting $ARCHIVE"
case "$ARCHIVE" in
*.tar.gz | *.tgz) tar -xzf "$tmp/$ARCHIVE" -C "$tmp" ;;
*.zip)
have unzip || die "need unzip to extract $ARCHIVE"
unzip -q "$tmp/$ARCHIVE" -d "$tmp"
;;
*) die "unknown archive format: $ARCHIVE" ;;
esac
for BINARY in $BINARIES; do
bin=$(find "$tmp" -type f -name "$BINARY" | head -n1)
[ -n "$bin" ] || die "binary $BINARY not found inside $ARCHIVE"
chmod +x "$bin"
install_binary "$bin" "$BINARY"
done