2# Install one of my Rust binaries from GitHub.
4# This was originally written to pull just my Rust binaries, but it
5# turns out it can work reasonably well for other projects. This allows
6# me to bypass Homebrew, which is generally nicer.
8# For my CLI tools written in Rust, I use a GitHub Action [1]
9# to compile binaries and add them to a release on GitHub.
11# These are the "canonical" versions, rather than recompiling on
12# each machine and having slightly different versions because I
13# was using different checkouts of the code.
15# This script gets the latest version of a binary from GitHub and
18# This script isn't meant to be run directly (hence the underscore) --
19# I have other scripts that invoke it (e.g. install-vfd), so I can find
20# those scripts with autocomplete in my shell, even on a new machine.
22# TODO: I publish macOS/Windows/Linux binaries, but this script only
23# fetches the macOS binary. In theory, it could detect which OS it's
24# running on and pick the right binary.
26# [1]: https://github.com/taiki-e/upload-rust-binary-action
33 echo "Usage: _install-rust-bin <REPO_NAME>"
38RELEASES_API_URL="https://api.github.com/repos/$REPO_NAME/releases/latest"
40# Fetch the asset URL using the GitHub Releases API [2].
42# For the purposes of this script, these are the interesting bits of the
43# API response that we want to pay attention to:
48# "name": "vfd-x86_64-apple-darwin.tar.gz",
49# "url": "https://api.github.com/repos/alexwlchan/books.alexwlchan.net/releases/assets/64229966",
53# "name": "vfd-x86_64-pc-windows-msvc.zip",
54# "url": "https://api.github.com/repos/alexwlchan/books.alexwlchan.net/releases/assets/64229889",
58# "name": "vfd-x86_64-unknown-linux-gnu.tar.gz",
59# "url": "https://api.github.com/repos/alexwlchan/books.alexwlchan.net/releases/assets/64229611",
65# [2]: https://docs.github.com/en/rest/releases/releases#get-the-latest-release
67# Note: this will filter out ARM binaries because I'm not running on
68# Apple Silicon yet; this will need updating eventually.
70ASSET_URL=$(curl --silent "$RELEASES_API_URL" \
71 | jq -r '.assets | .[] | select(.name | contains("darwin")) | select(.name | contains("arm") | not) | select(.name | contains("aarch64") | not) | .url' \
75if [[ "$ASSET_URL" == "" ]]
77 echo "No macOS download available for the latest version! Is it still building?" >&2
81# Download and unpack the asset using the GitHub Release Assets API [3].
83# We supply the headers required by the GitHub API, and the `--location`
84# flag caused curl to follow redirects.
86# Note: this assumes the binary is packaged as a tar.gz. The Windows
87# binaries are zipped instead of tar.gz-ed, so if you want to support
88# Windows, inspect the "content_type" field in the Releases API response.
90# [3]: https://docs.github.com/en/rest/releases/assets#get-a-release-asset
95 --header "Accept: application/octet-stream" \
98 "$ASSET_URL" > "asset.tar.gz"
100# Identify the name of the binary, which may be different from the repo name.
102# We list all the files in the asset package, which should contain a single
103# file, and assume that's the name of the binary.
104ASSET_FILES=$(tar --list --file "asset.tar.gz")
106if [[ "$REPO_NAME" == "BurntSushi/ripgrep" ]]
108 BINARY_PATH=$(echo "$ASSET_FILES" | grep "/rg$")
111 if (( $(echo "$ASSET_FILES" | wc -l) != 1 ))
113 echo "Release asset doesn't contain exactly 1 file; not sure what to do:" >&2
114 echo "$ASSET_FILES" >&2
118 BINARY_PATH="$(echo "$ASSET_FILES" | head -n 1)"
119 BINARY_NAME="$BINARY_PATH"
122# Now actually extract the binary, make it executable, and add it to the PATH.
123tar --extract --gunzip --file "asset.tar.gz"
125chmod +x "$BINARY_PATH"
126sudo mv "$BINARY_PATH" /usr/local/bin
129"$BINARY_NAME" --version