Skip to content

Instantly share code, notes, and snippets.

@mark-kubacki
Last active June 14, 2023 14:56
Show Gist options
  • Save mark-kubacki/e1757a9c47c27897d0d9edcd62bf167d to your computer and use it in GitHub Desktop.
Save mark-kubacki/e1757a9c47c27897d0d9edcd62bf167d to your computer and use it in GitHub Desktop.
Updates your local Golang to the latest stable version
#!/bin/bash
# Will update your Golang.
# Needs: curl tar jq procps-ng/pgrep
set -eupo pipefail
if [[ -t 1 ]] && type -p 'tput' &>/dev/null && tput colors >&/dev/null; then
V_BOLD_RED=$(tput bold; tput setaf 1)
V_BOLD_GREEN=$(tput bold; tput setaf 2)
V_VIDOFF=$(tput sgr0)
else
V_BOLD_RED=''
V_BOLD_GREEN=''
V_VIDOFF=''
fi
info() {
printf "${V_BOLD_GREEN}${1}${V_VIDOFF}\n"
}
error() {
>&2 printf "${V_BOLD_RED}${1}${V_VIDOFF}\n"
}
: ${GOROOT:="/opt/go"}
if [[ -d "${GOROOT}.new" ]]; then
error "Artifacts of a previous unclean run detected: %s\n" "${GOROOT}.new"
exit 2
fi
# Returns a the version and a link to its archive for download,
# delimited by spaces.
# Variables read from environment are: os, arch
go::upstream::latest() {
local archive_term='[.[] | select(.stable==true).files[] | select(.os=="'${OSTYPE}'" and .arch=="'${arch}'").filename][0]'
local version_term='[.[] | select(.stable==true).version][0]'
curl --fail --location --silent --show-error --compressed \
'https://golang.org/dl/?mode=json' \
| jq -r "${version_term} + \" \" + ${archive_term}"
}
# Returns the download url for a version, provided as first argument.
# Usually used to get a particular version for patching it.
# Envvars read: os, arch
go::upstream::download_url() {
curl --fail --location --silent --show-error --compressed \
'https://golang.org/dl/?mode=json&include=all' \
| jq -r '[.[] | select(.version=="go'$1'").files[] | select(.os=="'${OSTYPE}'" and .arch=="'${arch}'").filename][0]'
}
if type -p 'dpkg' &>/dev/null; then
: ${arch:="$(dpkg --print-architecture)"}
else
: ${arch:="${HOSTTYPE}"}
arch="${arch//x86_64/amd64}"
fi
: ${UPSTREAM_PV:=""} ${UPSTREAM_SRC:=""}
if [[ -z "${UPSTREAM_PV}" ]]; then
read UPSTREAM_PV UPSTREAM_SRC < <(go::upstream::latest)
UPSTREAM_PV=${UPSTREAM_PV#go}
else
UPSTREAM_PV=${UPSTREAM_PV#go}
read UPSTREAM_SRC < <(go::upstream::download_url "${UPSTREAM_PV}")
fi
oldgolang="${GOROOT}/bin/go"
if [[ ! -x "${oldgolang}" ]] && command -v go &>/dev/null; then
oldgolang="$(command -v go)"
fi
if [[ -x "${oldgolang}" && "$("${oldgolang}" version)" == *"go${UPSTREAM_PV} ${OSTYPE}/${arch}"* ]]; then
error "Local version already is at '${UPSTREAM_PV}'. Exiting."
exit 0
fi
info "Starting upsert to: ${UPSTREAM_PV}"
: ${mirror:="https://dl.google.com"}
case "${UPSTREAM_SRC}" in
*gz) decoder='--gunzip' ;;
*xz) decoder='--xz' ;;
*zstd) decoder='--zstd' ;;
*) decoder='--no-auto-compress' ;;
esac
mkdir -p "${GOROOT}.new"
trap "rm -rf '${GOROOT}.new'" ERR
curl --fail --location --progress-bar \
"${mirror}/go/${UPSTREAM_SRC}" \
| tar --no-same-owner --strip-components=1 -x ${decoder} -C "${GOROOT}.new"/
# Apply any local patches.
pars=${UPSTREAM_PV//[^.]}
examine_P=()
if (( ${#pars} >= 2 )); then
# go-1.6.4 go-1.6
examine_P+=("go-${UPSTREAM_PV}" "go-${UPSTREAM_PV%.*}")
elif (( ${#pars} >= 1 )); then
examine_P+=("go-${UPSTREAM_PV}")
fi
unset pars
examine_P+=("go-${UPSTREAM_PV%%.*}" "go:${UPSTREAM_PV%%.*}" "go")
for P in "${examine_P[@]}"; do
if [[ -d /etc/portage/patches/"dev-lang/${P}" ]]; then
while read -r -u3 PATCH || [[ -n "${PATCH}" ]]; do
(cd "${GOROOT}.new"; patch -p1 --batch -i "${PATCH}")
done 3< <(find /etc/portage/patches/"dev-lang/${P}" -type f -name '*.patch' | sort -h)
fi
done
for pid in $(pgrep --full "${GOROOT}/bin/go"); do
info "Waiting on dangling process to conclude: ${pid}"
<&- tail --pid ${pid} -f /dev/null &
done
wait
[[ -d "${GOROOT}" ]] && mv "${GOROOT}"{,.old}
mv "${GOROOT}"{.new,}
rm -rf "${GOROOT}.old" &
info "Done: $(${GOROOT}/bin/go version)"
rm -rf "${GOROOT}.old" &
rm -rf /home/*/.cache/go-build &
# Compiled by any previous version of Go, can be removed.
rm -rf /usr/share/gocode/pkg &
wait
exit 0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment