#!/bin/sh # # This script acts like the "go" command, but uses Tailscale's # currently-desired version from https://github.com/tailscale/go, # downloading it first if necessary. set -eu log() { echo "$@" >&2 } DEFAULT_TOOLCHAIN_DIR="${HOME}/.cache/tailscale-go" TOOLCHAIN="${TOOLCHAIN-${DEFAULT_TOOLCHAIN_DIR}}" TOOLCHAIN_GO="${TOOLCHAIN}/bin/go" read -r REV < "$(dirname "$0")/../go.toolchain.rev" # Fast, quiet path, when Tailscale is already current. if [ -e "${TOOLCHAIN_GO}" ]; then short_hash=$("${TOOLCHAIN_GO}" version | sed 's/.*-ts//; s/ .*//') case $REV in "$short_hash"*) unset GOROOT exec "${TOOLCHAIN_GO}" "$@" esac fi # This works for linux and darwin, which is sufficient # (we do not build tailscale-go for other targets). host_os=$(uname -s | tr A-Z a-z) host_arch="$(uname -m)" if [ "$host_arch" = "aarch64" ]; then # Go uses the name "arm64". host_arch="arm64" elif [ "$host_arch" = "x86_64" ]; then # Go uses the name "amd64". host_arch="amd64" fi get_cached() { if [ ! -d "$TOOLCHAIN" ]; then mkdir -p "$TOOLCHAIN" fi archive="$TOOLCHAIN-$REV.tar.gz" mark="$TOOLCHAIN.extracted" extracted= # Ignore the error from read, which may error if the mark file does not contain a line end. read -r extracted < "$mark" || true if [ "$extracted" = "$REV" ] && [ -e "${TOOLCHAIN_GO}" ]; then # already ok log "Go toolchain '$REV' already extracted." return 0 fi rm -f "$archive.new" "$TOOLCHAIN.extracted" if [ ! -e "$archive" ]; then log "Need to download go '$REV'." curl -f -L -o "$archive.new" "https://github.com/tailscale/go/releases/download/build-${REV}/${host_os}-${host_arch}.tar.gz" rm -f "$archive" mv "$archive.new" "$archive" fi log "Extracting tailscale/go rev '$REV'" >&2 log " into '$TOOLCHAIN'." >&2 rm -rf "$TOOLCHAIN" mkdir -p "$TOOLCHAIN" (cd "$TOOLCHAIN" && tar --strip-components=1 -xf "$archive") echo "$REV" >$mark } if [ "${REV}" = "SKIP" ] || [ "${host_os}" != "darwin" -a "${host_os}" != "linux" ] || [ "${host_arch}" != "amd64" -a "${host_arch}" != "arm64" ]; then # Use whichever go is available exec go "$@" else get_cached fi unset GOROOT exec "${TOOLCHAIN_GO}" "$@"