113 lines
3.0 KiB
Bash
Executable File
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" "$@"
|