#!/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)"fiif [ "$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
#!/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-install
fi