go-setversion/go-setversion

113 lines
3.0 KiB
Bash
Executable File

#!/usr/bin/env bash
set -Eeuo pipefail
declare -r \
config_file="${XDG_CONFIG_HOME:-${HOME}/.config}/go-setversion/paths.conf" \
log_level="${GOSETVERSION_LOGLEVEL:-}"
# Default to the system-wide installed Go.
declare go='/usr/bin/go'
# Helper scripts. Useful if you have this script as `go-setversion` somewhere,
# and `$GOBIN/go` is a symlink to it.
if [ "$(basename "$0")" == 'go-setversion' ]; then
case "${1:-}" in
''|'install')
ln -s "$(realpath "$0")" "${GOBIN}/go"
>&2 echo "go-setversion installed to '$GOBIN'. Run "go setversion 1.18" to set the go version for the current path."
;;
'reset')
rm "$config_file"
>&2 echo 'config file deleted. go-setversion has been reset.'
;;
'uninstall')
rm "${GOBIN}/go"
>&2 echo "'$GOBIN/go' deleted."
;;
*)
>&2 echo "unknown command: ${1}"
exit 1
;;
esac
exit 0
fi
# Only print logs if `GOSETVERSION_LOGLEVEL` is set to `info` in the
# environment.
print_info() {
declare -r message="$*"
if [ "$log_level" == 'info' ]; then
>&2 echo "GOUP [INFO]: ${message}"
fi
}
# If this script is called with `$0 setversion`, then this function is executed
# and the actual Go binary will not be called. This function saves `$PWD` to
# the config file, and sets it to `$2`. If the Go version is not passed in
# `$2`, then this function deletes this `$PWD` entry from the configuration.
if [ "${1:-}" == 'setversion' ]; then
mkdir -p "$(dirname "$config_file")"
touch "$config_file"
declare -r go_version="${2:-}"
sed -i "\|${PWD} |d" "$config_file"
if [ -n "$go_version" ]; then
echo "${PWD} go${go_version#go}" >> "$config_file"
fi
print_info "set path '${PWD} to '${go_version}'"
# Calling `go version` here will ensure that the requested Go version
# is immediately prepared (see below).
exec go version
fi
# Fetches the configured Go version from the config file. If no match is found,
# looks in parent directories until `/`.
#
# The `while` loop will first look for a match with the full `$PWD`. Then it
# will strip path elements one by one, virtually descending the filesystem tree
# until it finds a match. If no match is found, it doesn't return anything.
go_from_config() {
if ! [ -f "$config_file" ]; then
return
fi
declare target='' version=''
target="$(realpath "$PWD")/x" \
while [ "$target" != '/' ]; do
target="$(dirname "$target")"
version="$(sed -n "0,\|${target} |s|${target} ||p" "$config_file")"
if [ -n "$version" ]; then
printf "%s" "$version"
return
fi
done
}
candidate_go="$(go_from_config)"
if [ -z "$candidate_go" ]; then
print_info "no config match: using '$go'"
else
print_info "config match: '$candidate_go'"
# If there is a match in the configuration, then make sure that the
# corresponding Go version is installed and downloaded.
if ! [ -x "${GOBIN}/${candidate_go}" ]; then
"$go" install "golang.org/dl/${candidate_go}@latest"
"$candidate_go" download
fi
go="$candidate_go"
fi
# Finally, execute the actual Go binary with all the original arguments.
exec "$go" "$@"