#!/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