#!/bin/sh # Install the vatan command, which installs and runs Vatan. # # curl -fsSL https://get.vatan.one | sh # # Downloads the vatan binary for this machine and its sha256 from Vatan, # checks one against the other, and puts the binary in /usr/local/bin (or # ~/.local/bin when that cannot be written and there is no sudo). Then # `vatan init` does the rest. Nothing else on this machine is changed. # # Settings, all optional: # VATAN_CLI_VERSION a release such as 1.4.0; the newest by default # VATAN_INSTALL_DIR where the binary goes # VATAN_RELEASES_URL where it is downloaded from; https://api.vatan.one # # POSIX sh, because this is piped into whatever `sh` the machine has. set -eu base="${VATAN_RELEASES_URL:-https://api.vatan.one}" version="${VATAN_CLI_VERSION:-latest}" say() { printf '%s\n' "$*"; } fail() { printf 'vatan install: %s\n' "$*" >&2; exit 1; } command -v curl >/dev/null 2>&1 || fail "curl is needed, and is not installed." os="$(uname -s)" arch="$(uname -m)" case "$os/$arch" in Linux/x86_64|Linux/amd64) target=linux-x64 ;; Linux/aarch64|Linux/arm64) target=linux-arm64 ;; Darwin/arm64) target=darwin-arm64 ;; *) fail "there is no vatan command for $os on $arch. It runs on Linux (x86-64 or ARM) and on Macs with Apple silicon." ;; esac if command -v sha256sum >/dev/null 2>&1; then digest() { sha256sum "$1" | cut -d ' ' -f 1; } elif command -v shasum >/dev/null 2>&1; then digest() { shasum -a 256 "$1" | cut -d ' ' -f 1; } else fail "neither sha256sum nor shasum is installed, and the download is not installed without a checksum." fi tmp="$(mktemp -d)" trap 'rm -rf "$tmp"' EXIT # `latest` is asked once and the version it names is used for both files. # Asked twice, a release published between the two requests would pair # one release's binary with the next one's checksum. if [ "$version" = latest ]; then link="$(curl -fsS -o /dev/null -w '%{redirect_url}' "$base/v1/cli/latest/$target.sha256")" \ || fail "Vatan did not answer. Try again, or set VATAN_CLI_VERSION to a release." version="$(printf '%s\n' "$link" | sed -n 's|.*/cli/\([0-9][0-9A-Za-z.-]*\)/.*|\1|p')" [ -n "$version" ] || fail "Vatan did not say which release is the newest." fi say "Downloading vatan $version for $target." curl -fL --progress-bar --retry 3 -o "$tmp/vatan" "$base/v1/cli/$version/$target" \ || fail "the download failed. Is $version a release?" curl -fsSL --retry 3 -o "$tmp/vatan.sha256" "$base/v1/cli/$version/$target.sha256" \ || fail "the checksum could not be downloaded, so the binary was not installed." want="$(cut -d ' ' -f 1 < "$tmp/vatan.sha256")" got="$(digest "$tmp/vatan")" [ -n "$want" ] && [ "$want" = "$got" ] \ || fail "the binary does not match its checksum, so it was not installed. Try again; if it happens twice, tell Vatan." chmod 755 "$tmp/vatan" # A Mac runs only signed code on Apple silicon. Signed for the machine # itself (ad hoc), which is what the compiler does when it builds there; # done again here in case this binary was built elsewhere. After the # checksum, so what was checked is what was downloaded. if [ "$os" = Darwin ] && command -v codesign >/dev/null 2>&1; then codesign --force --sign - "$tmp/vatan" >/dev/null 2>&1 || true fi dir="${VATAN_INSTALL_DIR:-/usr/local/bin}" if [ -w "$dir" ] || { [ ! -e "$dir" ] && mkdir -p "$dir" 2>/dev/null; }; then mv "$tmp/vatan" "$dir/vatan" elif [ -z "${VATAN_INSTALL_DIR:-}" ] && command -v sudo >/dev/null 2>&1; then say "Installing to $dir, which needs sudo." sudo mkdir -p "$dir" sudo mv "$tmp/vatan" "$dir/vatan" else dir="$HOME/.local/bin" mkdir -p "$dir" mv "$tmp/vatan" "$dir/vatan" case ":$PATH:" in *":$dir:"*) ;; *) say "Add $dir to your PATH to run vatan by name: export PATH=\"$dir:\$PATH\"" ;; esac fi say "" say "vatan $version is installed at $dir/vatan." say "Next:" say " vatan init"