148 lines · 5.7 KB · Text
RawDownload
#!/usr/bin/env bash## Installs cargo-binstall at the pinned version if it isn't already present. # This script should be platform-agnostic (eg. no unix-only references like /dev/null). set -eo pipefail # Local bootstraps and CI both install binstall through this script, so this is# the single pinned version everywhere.BINSTALL_VERSION="1.18.1" # Every archive this script may run, keyed by asset name, with the SHA-256 that# GitHub publishes for it. The download URL and the release it points at are both# mutable, so the digest — reviewed here, in the repo — is what authenticates the# binary before it executes. A mismatch aborts the install.## Regenerate when bumping BINSTALL_VERSION:##   curl -sSfL https://api.github.com/repos/cargo-bins/cargo-binstall/releases/tags/v<version> \#     | jq -r '.assets[] | "\(.name) \(.digest)"'archive_sha256() {    case "$1" in        cargo-binstall-universal-apple-darwin.zip)            echo "5cc5d6d502924623a491c4ed77fb925193f05106252cffd3be979cbb94a0cd01" ;;        cargo-binstall-x86_64-unknown-linux-musl.tgz)            echo "cf2a4b54494ea8555d6349685e9a301efc1051d9fba6308c76914b2486f8700f" ;;        cargo-binstall-aarch64-unknown-linux-musl.tgz)            echo "c55962a0115f9716b709216de7f8bdd59d6ba8738779e60b051b4593f677717a" ;;        cargo-binstall-x86_64-pc-windows-msvc.zip)            echo "89706aa5215c164d8d091597a470fee72308ac87e8553af395ea77db844a888c" ;;        cargo-binstall-aarch64-pc-windows-msvc.zip)            echo "c6873e81457d9e44973a8e9a849795f2c83765fce0af8ad68b597b5b40dec418" ;;    esac} # The macOS archive is a universal binary, so it serves both darwin architectures.archive_for_platform() {    case "$(uname -s)" in        Darwin)            echo "cargo-binstall-universal-apple-darwin.zip" ;;        Linux)            echo "cargo-binstall-$(uname -m)-unknown-linux-musl.tgz" ;;        *)            if [ "${OS-}" = "Windows_NT" ]; then                # uname -m is unreliable here: Git for Windows' MSYS runtime reports the                # emulated x86_64 host under WOW64, or "unknown" on a native arm64 host,                # rather than the real machine architecture. PROCESSOR_ARCHITEW6432 (set                # only under emulation, to the true native architecture) falling back to                # PROCESSOR_ARCHITECTURE reports it correctly in both cases.                case "${PROCESSOR_ARCHITEW6432:-${PROCESSOR_ARCHITECTURE-}}" in                    ARM64)                        echo "cargo-binstall-aarch64-pc-windows-msvc.zip" ;;                    AMD64)                        echo "cargo-binstall-x86_64-pc-windows-msvc.zip" ;;                esac            fi            ;;    esac} sha256_of() {    if [ -n "$(command -v sha256sum || true)" ]; then        sha256sum "$1" | cut -d ' ' -f 1    elif [ -n "$(command -v shasum || true)" ]; then        shasum -a 256 "$1" | cut -d ' ' -f 1    else        openssl dgst -sha256 "$1" | awk '{print $NF}'    fi} # bsdtar reads zip archives, which is what keeps unzip optional on macOS and# Windows. GNU tar cannot, but Linux downloads a .tgz.extract() {    case "$1" in        *.zip)            if [ -n "$(command -v unzip || true)" ]; then                unzip -o "$1"            else                tar -xf "$1"            fi            ;;        *)            tar -xzf "$1" ;;    esac} # cargo-binstall is installed from its own prebuilt release rather than with# `cargo install`, which compiles it and its whole dependency tree from source and# dominates the runtime of a fresh bootstrap.INSTALLED_VERSION=""if command -v cargo-binstall; then    INSTALLED_VERSION="$(cargo-binstall -V)"fi if [ "$INSTALLED_VERSION" != "$BINSTALL_VERSION" ]; then    echo "Installing cargo-binstall v${BINSTALL_VERSION} from its prebuilt release..."     ARCHIVE="$(archive_for_platform)"    EXPECTED_SHA256="$(archive_sha256 "$ARCHIVE")"    if [ -z "$EXPECTED_SHA256" ]; then        echo "error: no pinned cargo-binstall release for $(uname -s) $(uname -m)." >&2        echo "Add its archive and SHA-256 to script/install_cargo_binstall to support this platform." >&2        exit 1    fi     WORKDIR="$(mktemp -d)"    # shellcheck disable=SC2064 # Expand WORKDIR now so the trap still resolves it later.    trap "rm -rf \"$WORKDIR\"" EXIT     # GitHub's release-asset CDN intermittently fails with errors curl's --retry    # won't retry, and its brownouts can last minutes, so retry at the shell level    # with exponential backoff.    DOWNLOAD_ATTEMPTS=5    RETRY_DELAY=10    for attempt in $(seq 1 "$DOWNLOAD_ATTEMPTS"); do        if curl -L --proto '=https' --tlsv1.2 -sSf \            --retry 5 --retry-delay 2 \            "https://github.com/cargo-bins/cargo-binstall/releases/download/v${BINSTALL_VERSION}/${ARCHIVE}" \            --output "$WORKDIR/$ARCHIVE"; then            break        fi        if [ "$attempt" -eq "$DOWNLOAD_ATTEMPTS" ]; then            echo "error: failed to download $ARCHIVE after $DOWNLOAD_ATTEMPTS attempts." >&2            exit 1        fi        echo "Download failed; retrying in ${RETRY_DELAY}s..." >&2        sleep "$RETRY_DELAY"        RETRY_DELAY=$((RETRY_DELAY * 2))    done     ACTUAL_SHA256="$(sha256_of "$WORKDIR/$ARCHIVE")"    if [ "$ACTUAL_SHA256" != "$EXPECTED_SHA256" ]; then        echo "error: $ARCHIVE failed verification, refusing to run it." >&2        echo "  expected SHA-256 $EXPECTED_SHA256" >&2        echo "  actual SHA-256   $ACTUAL_SHA256" >&2        exit 1    fi     (cd "$WORKDIR" && extract "$ARCHIVE")     BINSTALL="$WORKDIR/cargo-binstall"    if [ -f "${BINSTALL}.exe" ]; then        BINSTALL="${BINSTALL}.exe"    fi    chmod +x "$BINSTALL"    "$BINSTALL" --self-installfi