Skip to content

Instantly share code, notes, and snippets.

@TaQuanMinhLong
Last active June 8, 2024 10:08
Show Gist options
  • Select an option

  • Save TaQuanMinhLong/a893cce49a865b40d30eaf244587aed0 to your computer and use it in GitHub Desktop.

Select an option

Save TaQuanMinhLong/a893cce49a865b40d30eaf244587aed0 to your computer and use it in GitHub Desktop.
Update golang version using Nushell script
# Config
const INSTALL_DIR = "/usr/local"
const DL_URL = "https://go.dev/dl/"
let num_threads = sys | get cpu | length
let GO_ROOT = $INSTALL_DIR | path join go
let GO_BIN = $GO_ROOT | path join bin
let TMP_DIR = $env.PWD | path join go_dl_tmp
let ADD_TO_PATH = $"add_to_path ($GO_BIN)"
# let ADD_TO_PATH = $"$env.PATH = \(if ($GO_BIN) in $env.PATH { $env.PATH } else { \($env.PATH | split row \(char esep) | append ($GO_BIN)) })"
def get_os [] {
uname | get kernel-name | str downcase | str trim
}
def get_arch [] {
let arch = arch | to text
match $arch {
"x86" => "386",
"x86_64" => "amd64",
"arm" => "armv6l",
"aarch64" => "arm64",
"loongarch64" => "loong64",
"m68k" => "mips",
"csky" => "mips",
"mips" => "mips",
"mips64" => "mips64",
"powerpc" => "ppc64",
"powerpc64" => "ppc64",
"riscv64" => "riscv64",
"s390x" => "s390x",
"sparc64" => "amd64",
_ => "",
}
}
def get_version [] {
if (which go | is-empty) {
return "null"
}
return (go version | parse "go version go{major}.{minor}.{patch} {os}/{arch}")
}
def is_up_to_date [current, latest] {
if ($current.major != $latest.major) {
return false
}
if ($current.minor != $latest.minor) {
return false
}
if ($current.patch != $latest.patch) {
return false
}
return true
}
def check_update [] {
print "Checking for updates... 🚧"
let query = {mode: "json"} | url build-query
let url = [$DL_URL ? $query] | str join
let data = http get $url | first 1
let version = $data | get version | parse "go{major}.{minor}.{patch}"
let os = get_os
let arch = get_arch
let file = $data.files.0 | where os == $os and arch == $arch
if ($file | is-empty) {
print $"🚨 Error: No download target found for OS = ($os) and ARCH = ($arch)"
exit 1
}
let filename = $file.0.filename
return {version: $version, filename: $filename}
}
def download [file_name: string, file_size: int ] {
rm -rf $TMP_DIR
mkdir $TMP_DIR
cd $TMP_DIR
let per_thread = $file_size // $num_threads
let remain = $file_size mod $num_threads
let timer_start = date now
0..($num_threads - 1) | par-each {|i|
let start = $i * $per_thread
mut end = if $i == ($num_threads - 1) {$file_size - 1} else {($i + 1) * $per_thread - 1}
let bytes_header = [range $"bytes=($start)-($end)"]
let url = $"($DL_URL)($file_name)"
let tmp_file = $"($i | fill -a right -c 0 -w 3)_tmp_($start)_($end)"
http get -H $bytes_header $url | save $tmp_file
}
let file_path = $TMP_DIR | path join $file_name
ls -s | sort-by name | each {|f| open $f.name | into binary } | bytes collect | save -frap $file_path
let duration = (date now) - $timer_start | format duration ms
print $"Download finished in ($duration) βœ…"
return $file_path
}
let update_info = check_update
let latest = $update_info.version
let current = get_version
if ($current != "null") and (is_up_to_date $current $latest) {
print "Go is up to date πŸš€"
print $"(go version) βœ…"
exit 0
}
print "Removing old version... 🚧"
sudo rm -rf $GO_ROOT
let file_name = $update_info.filename | to text
let file_size = http head ($DL_URL | path join $file_name) | where name == "content-length" | get value | to text | into int
print $"Downloading new version: ($file_name) \(($file_size) bytes)... ⏳"
let file_path = download $file_name $file_size
open $file_path | bytes length | print
sudo tar -xzvf $file_path -C $INSTALL_DIR
print "Cleaning up temporary files... 🧹"
rm -rf $TMP_DIR
let added_to_path = $GO_BIN in $env.PATH
if not $added_to_path {
print "Adding Go binary dir to $PATH"
open ($nu.env-path) | append $ADD_TO_PATH | save -f $nu.env-path
}
print $"Update successfully: (go version) βœ…"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment