#!/bin/sh
# Bootstrap the cacher binary in one line, for CI manifests and dev boxes:
#
# curl -sSL https://bigbes.pages.srht.bigb.es/ci-cacher/install.sh | sh
#
# Detects the platform, verifies the download against the published
# checksums.txt, installs into ~/.local/bin (override with CACHER_BINDIR or
# a single positional argument), and — on builds.sr.ht, where ~/.buildenv is
# sourced before every task — appends the PATH export so later tasks find
# the binary without repeating it.
#
# Env:
# CACHER_BASE_URL where to fetch from (default: the pages.sr.ht release)
# CACHER_BINDIR install directory (default: $HOME/.local/bin)
set -eu
BASE_URL="${CACHER_BASE_URL:-https://bigbes.pages.srht.bigb.es/ci-cacher}"
BINDIR="${1:-${CACHER_BINDIR:-$HOME/.local/bin}}"
os=$(uname -s | tr '[:upper:]' '[:lower:]')
case "$os" in
linux | darwin) ;;
*) echo "install.sh: unsupported OS '$os'; build from source: go install go.bigb.es/cacher@latest" >&2; exit 1 ;;
esac
case "$(uname -m)" in
x86_64 | amd64) arch=amd64 ;;
aarch64 | arm64) arch=arm64 ;;
*) echo "install.sh: unsupported architecture '$(uname -m)'" >&2; exit 1 ;;
esac
asset="cacher-${os}-${arch}"
# curl on most CI images, wget on the minimal ones. Fail loudly on HTTP
# errors so a 404 can't be installed as an executable.
if command -v curl >/dev/null 2>&1; then
fetch() { curl -fsSL "$1" -o "$2"; }
elif command -v wget >/dev/null 2>&1; then
fetch() { wget -q "$1" -O "$2"; }
else
echo "install.sh: neither curl nor wget is available" >&2
exit 1
fi
tmp=$(mktemp -d)
trap 'rm -rf "$tmp"' EXIT
echo "install.sh: fetching ${BASE_URL}/${asset}"
fetch "${BASE_URL}/${asset}" "${tmp}/cacher"
# checksums.txt lists every published asset; pull out the line for the
# one we downloaded and compare hashes as plain strings. Deliberately not
# `sha256sum -c --ignore-missing`: --ignore-missing is a coreutils
# extension, and Alpine ships busybox sha256sum, which rejects it.
# A host with no sha256 tool at all warns and installs anyway.
if command -v sha256sum >/dev/null 2>&1; then
hash_of() { sha256sum "$1" | cut -d' ' -f1; }
elif command -v shasum >/dev/null 2>&1; then
hash_of() { shasum -a 256 "$1" | cut -d' ' -f1; }
else
hash_of() { echo ""; }
echo "install.sh: no sha256sum/shasum — skipping checksum verification" >&2
fi
if fetch "${BASE_URL}/checksums.txt" "${tmp}/checksums.txt"; then
want=$(awk -v a="$asset" '$2 == a { print $1 }' "${tmp}/checksums.txt")
got=$(hash_of "${tmp}/cacher")
if [ -z "$want" ]; then
echo "install.sh: ${asset} is not listed in checksums.txt — skipping verification" >&2
elif [ -n "$got" ] && [ "$want" != "$got" ]; then
echo "install.sh: checksum mismatch for ${asset}" >&2
echo " want ${want}" >&2
echo " got ${got}" >&2
exit 1
elif [ -n "$got" ]; then
echo "install.sh: checksum ok"
fi
else
echo "install.sh: checksums.txt unavailable — skipping verification" >&2
fi
# Land it via a staging file inside $BINDIR, so the final step is a
# rename on one filesystem: writing over a binary in place fails with
# ETXTBSY while something is running it.
mkdir -p "$BINDIR"
staged="${BINDIR}/.cacher.new.$$"
trap 'rm -rf "$tmp" "$staged"' EXIT
cp "${tmp}/cacher" "$staged"
chmod 0755 "$staged"
mv -f "$staged" "${BINDIR}/cacher"
# builds.sr.ht sources ~/.buildenv before every task; adding the export
# here saves each manifest a PATH line of its own.
if [ -f "$HOME/.buildenv" ] && ! grep -q "$BINDIR" "$HOME/.buildenv" 2>/dev/null; then
echo "export PATH=\"${BINDIR}:\$PATH\"" >> "$HOME/.buildenv"
echo "install.sh: added ${BINDIR} to ~/.buildenv PATH"
fi
echo "install.sh: installed → ${BINDIR}/cacher"
"${BINDIR}/cacher" version
case ":${PATH}:" in
*":${BINDIR}:"*) ;;
*) echo "install.sh: note — ${BINDIR} is not on your PATH" >&2 ;;
esac