Last active
June 14, 2023 14:56
-
-
Save mark-kubacki/e1757a9c47c27897d0d9edcd62bf167d to your computer and use it in GitHub Desktop.
Updates your local Golang to the latest stable version
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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