From 5a92412348ce2ca7d0fcefd935e27d2cff223aed Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Wed, 9 Aug 2023 23:03:30 +0000 Subject: [PATCH] ref: make 'go' canonical installer, not just alias --- go/README.md | 92 ++++++++++++++++++++++++++++++++++++++++++---- go/install.ps1 | 66 +++++++++++++++++++++++++++++++-- go/install.sh | 60 +++++++++++++++++++++++++++--- go/releases.js | 78 +++++++++++++++++++++++++++++++++++++++ golang/README.md | 8 +++- golang/install.sh | 1 - golang/releases.js | 77 +------------------------------------- 7 files changed, 287 insertions(+), 95 deletions(-) create mode 100644 go/releases.js diff --git a/go/README.md b/go/README.md index 984b607..f3a0a51 100644 --- a/go/README.md +++ b/go/README.md @@ -1,11 +1,89 @@ --- -title: Go (golang alias) -homepage: https://webinstall.dev/golang +title: Go +homepage: https://golang.org tagline: | - Alias for https://webinstall.dev/golang -alias: golang -description: | - See https://webinstall.dev/golang + Go makes it easy to build simple, reliable, and efficient software. --- -Alias for https://webinstall.dev/golang +To update or switch versions, run `webi go@stable` (or `@v1.21`, `@beta`, etc). + +### Files + +```text +~/.config/envman/PATH.env +~/.local/opt/go/ +~/go/ +``` + +## Cheat Sheet + +> Go is designed, through and through, to make Software Engineering easy. It's +> fast, efficient, reliable, and something you can learn in a weekend. +> +> If you subscribe to +> [_The Zen of Python_](https://www.python.org/dev/peps/pep-0020/), you'll +> [love](https://go-proverbs.github.io/) > +> [Go](https://www.youtube.com/watch?v=PAAkCSZUG1c). + +You may also want to install the Go IDE tooling: +[go-essentials](/go-essentials). + +### Hello World + +1. Make and enter your project directory + ```sh + mkdir -p ./hello/cmd/hello + pushd ./hello/ + ``` +2. Initialize your `go.mod` to your _git repository_ url: + ```sh + go mod init github.com/example/hello + ``` +3. Create a `hello.go` + + ```sh + cat << EOF >> ./cmd/hello/hello.go + package main + + import ( + "fmt" + ) + + func main () { + fmt.Println("Hello, World!") + } + EOF + ``` + +4. Format, build, and run your `./hello` + ```sh + go fmt ./... + go build -o hello ./cmd/hello/ + ./hello + ``` + You should see your output: + ```text + > Hello, World! + ``` + +### How to run a Go program as a service + +On Linux: + +```sh +# Install serviceman (compatible with systemd) +webi serviceman +``` + +```sh +# go into your programs 'opt' directory +pushd ./hello/ + +# swap 'hello' and './hello' for the name of your project and binary +sudo env PATH="$PATH" \ + serviceman add --system --username "$(whoami)" --name hello -- \ + ./hello + +# Restart the logging service +sudo systemctl restart systemd-journald +``` diff --git a/go/install.ps1 b/go/install.ps1 index 69046e9..0e3d1f2 100644 --- a/go/install.ps1 +++ b/go/install.ps1 @@ -1,5 +1,63 @@ -#!/bin/pwsh +#!/usr/bin/env pwsh -echo "'go@$Env:WEBI_TAG' is an alias for 'golang@$Env:WEBI_VERSION'" -IF ($Env:WEBI_HOST -eq $null -or $Env:WEBI_HOST -eq "") { $Env:WEBI_HOST = "https://webinstall.dev" } -curl.exe -fsSL "$Env:WEBI_HOST/golang@$Env:WEBI_VERSION" | powershell +$pkg_cmd_name = "go" +New-Item "$Env:USERPROFILE\Downloads\webi" -ItemType Directory -Force | out-null +$pkg_download = "$Env:USERPROFILE\Downloads\webi\$Env:WEBI_PKG_FILE" + +$pkg_src = "$Env:USERPROFILE\.local\opt\$pkg_cmd_name-v$Env:WEBI_VERSION" + +$pkg_dst = "$Env:USERPROFILE\.local\opt\$pkg_cmd_name" +$pkg_dst_cmd = "$pkg_dst\bin\$pkg_cmd_name" +$pkg_dst_bin = "$pkg_dst\bin" + +if (!(Get-Command "git.exe" -ErrorAction SilentlyContinue)) +{ + & "$Env:USERPROFILE\.local\bin\webi-pwsh.ps1" git + # because we need git.exe to be available to golang immediately + $Env:PATH = "$Env:USERPROFILE\.local\opt\git\cmd;$Env:PATH" +} + +# Fetch archive +IF (!(Test-Path -Path "$pkg_download")) +{ + echo "Downloading $Env:PKG_NAME from $Env:WEBI_PKG_URL to $pkg_download" + & curl.exe -A "$Env:WEBI_UA" -fsSL "$Env:WEBI_PKG_URL" -o "$pkg_download.part" + & move "$pkg_download.part" "$pkg_download" +} + +IF (!(Test-Path -Path "$pkg_src")) +{ + echo "Installing $pkg_cmd_name" + # TODO: temp directory + + # Enter opt + pushd .local\tmp + + # Remove any leftover tmp cruft + Remove-Item -Path "$pkg_cmd_name*" -Recurse -ErrorAction Ignore + + # Unpack archive + # Windows BSD-tar handles zip. Imagine that. + echo "Unpacking $pkg_download" + & tar xf "$pkg_download" + + # Settle unpacked archive into place + echo "New Name: $pkg_cmd_name-v$Env:WEBI_VERSION" + Get-ChildItem "$pkg_cmd_name*" | Select -f 1 | Rename-Item -NewName "$pkg_cmd_name-v$Env:WEBI_VERSION" + echo "New Location: $pkg_src" + Move-Item -Path "$pkg_cmd_name-v$Env:WEBI_VERSION" -Destination "$Env:USERPROFILE\.local\opt" + + # Exit tmp + popd +} + +echo "Copying into '$pkg_dst' from '$pkg_src'" +Remove-Item -Path "$pkg_dst" -Recurse -ErrorAction Ignore +Copy-Item -Path "$pkg_src" -Destination "$pkg_dst" -Recurse +IF (!(Test-Path -Path go\bin)) { New-Item -Path go\bin -ItemType Directory -Force | out-null } + +# Add to path +webi_path_add ~/.local/opt/go/bin + +# Special to go: add default GOBIN to PATH +webi_path_add ~/go/bin diff --git a/go/install.sh b/go/install.sh index 328b598..17186c2 100644 --- a/go/install.sh +++ b/go/install.sh @@ -2,10 +2,60 @@ set -e set -u -__redirect_alias_golang() { - echo "'go@${WEBI_TAG:-stable}' is an alias for 'golang@${WEBI_VERSION-}'" - WEBI_HOST=${WEBI_HOST:-"https://webinstall.dev"} - curl -fsSL "$WEBI_HOST/golang@${WEBI_VERSION-}" | sh +GOBIN="${HOME}/go" +GOBIN_REAL="${HOME}/.local/opt/go-bin-v${WEBI_VERSION}" + +pkg_cmd_name="go" + +# NOTE: pkg_* variables can be defined here +# pkg_cmd_name +# pkg_src, pkg_src_bin, pkg_src_cmd +# pkg_dst, pkg_dst_bin, pkg_dst_cmd +# +# Their defaults are defined in _webi/template.sh at https://github.com/webinstall/packages + +pkg_get_current_version() { + # 'go version' has output in this format: + # go version go1.14.2 darwin/amd64 + # This trims it down to just the version number: + # 1.14.2 + go version 2> /dev/null | + head -n 1 | + cut -d' ' -f3 | + sed 's:go::' } -__redirect_alias_golang +pkg_format_cmd_version() { + # 'go v1.14.0' will be 'go1.14' + my_version=$(echo "$1" | sed 's:\.0::g') + echo "${pkg_cmd_name}${my_version}" +} + +pkg_link() { + # 'pkg_dst' will default to $HOME/.local/opt/go + # 'pkg_src' will be the installed version, such as to $HOME/.local/opt/go-v1.14.2 + rm -rf "$pkg_dst" + ln -s "$pkg_src" "$pkg_dst" + + # Go has a special $GOBIN + + # 'GOBIN' is set above to "${HOME}/go" + # 'GOBIN_REAL' will be "${HOME}/.local/opt/go-bin-v${WEBI_VERSION}" + rm -rf "$GOBIN" + mkdir -p "$GOBIN_REAL/bin" + ln -s "$GOBIN_REAL" "$GOBIN" +} + +pkg_post_install() { + pkg_link + + # web_path_add is defined in _webi/template.sh at https://github.com/webinstall/packages + # Updates PATH with + # "$HOME/.local/opt/go" + webi_path_add "$pkg_dst_bin" + webi_path_add "$GOBIN/bin" +} + +pkg_done_message() { + echo "Installed 'go v$WEBI_VERSION' to ~/.local/opt/go" +} diff --git a/go/releases.js b/go/releases.js new file mode 100644 index 0000000..e49eb88 --- /dev/null +++ b/go/releases.js @@ -0,0 +1,78 @@ +'use strict'; + +var osMap = { + darwin: 'macos', +}; +var archMap = { + 386: 'x86', +}; + +function getAllReleases(request) { + /* + { + version: 'go1.13.8', + stable: true, + files: [ + { + filename: 'go1.13.8.src.tar.gz', + os: '', + arch: '', + version: 'go1.13.8', + sha256: + 'b13bf04633d4d8cf53226ebeaace8d4d2fd07ae6fa676d0844a688339debec34', + size: 21631178, + kind: 'source' + } + ] + }; + */ + return request({ + url: 'https://golang.org/dl/?mode=json&include=all', + json: true, + }).then((resp) => { + var goReleases = resp.body; + var all = { + releases: [], + download: 'https://dl.google.com/go/{{ download }}', + }; + + goReleases.forEach((release) => { + // strip 'go' prefix, standardize version + var parts = release.version.slice(2).split('.'); + while (parts.length < 3) { + parts.push('0'); + } + var version = parts.join('.'); + + release.files.forEach((asset) => { + var filename = asset.filename; + var os = osMap[asset.os] || asset.os || '-'; + var arch = archMap[asset.arch] || asset.arch || '-'; + all.releases.push({ + version: version, + // all go versions >= 1.0.0 are effectively LTS + lts: (parts[0] > 0 && release.stable) || false, + channel: (release.stable && 'stable') || 'beta', + date: '1970-01-01', // the world may never know + os: os, + arch: arch, + ext: '', // let normalize run the split/test/join + hash: '-', // not ready to standardize this yet + download: filename, + }); + }); + }); + + return all; + }); +} + +module.exports = getAllReleases; + +if (module === require.main) { + getAllReleases(require('@root/request')).then(function (all) { + all = require('../_webi/normalize.js')(all); + all.releases = all.releases.slice(0, 10); + console.info(JSON.stringify(all, null, 2)); + }); +} diff --git a/golang/README.md b/golang/README.md index 2065027..1bc0e09 100644 --- a/golang/README.md +++ b/golang/README.md @@ -3,10 +3,14 @@ title: Go homepage: https://golang.org tagline: | Go makes it easy to build simple, reliable, and efficient software. +alias: go +description: | + See https://webinstall.dev/go --- -To update or switch versions, run `webi golang@stable` (or `@v1.19`, `@beta`, -etc). +Alias for . + +To update or switch versions, run `webi go@stable` (or `@v1.21`, `@beta`, etc). ### Files diff --git a/golang/install.sh b/golang/install.sh index b797b2f..55fb005 100644 --- a/golang/install.sh +++ b/golang/install.sh @@ -5,7 +5,6 @@ set -u GOBIN="${HOME}/go" GOBIN_REAL="${HOME}/.local/opt/go-bin-v${WEBI_VERSION}" -# The package is 'golang', but the command is 'go' pkg_cmd_name="go" # NOTE: pkg_* variables can be defined here diff --git a/golang/releases.js b/golang/releases.js index e49eb88..36688b5 100644 --- a/golang/releases.js +++ b/golang/releases.js @@ -1,78 +1,3 @@ 'use strict'; -var osMap = { - darwin: 'macos', -}; -var archMap = { - 386: 'x86', -}; - -function getAllReleases(request) { - /* - { - version: 'go1.13.8', - stable: true, - files: [ - { - filename: 'go1.13.8.src.tar.gz', - os: '', - arch: '', - version: 'go1.13.8', - sha256: - 'b13bf04633d4d8cf53226ebeaace8d4d2fd07ae6fa676d0844a688339debec34', - size: 21631178, - kind: 'source' - } - ] - }; - */ - return request({ - url: 'https://golang.org/dl/?mode=json&include=all', - json: true, - }).then((resp) => { - var goReleases = resp.body; - var all = { - releases: [], - download: 'https://dl.google.com/go/{{ download }}', - }; - - goReleases.forEach((release) => { - // strip 'go' prefix, standardize version - var parts = release.version.slice(2).split('.'); - while (parts.length < 3) { - parts.push('0'); - } - var version = parts.join('.'); - - release.files.forEach((asset) => { - var filename = asset.filename; - var os = osMap[asset.os] || asset.os || '-'; - var arch = archMap[asset.arch] || asset.arch || '-'; - all.releases.push({ - version: version, - // all go versions >= 1.0.0 are effectively LTS - lts: (parts[0] > 0 && release.stable) || false, - channel: (release.stable && 'stable') || 'beta', - date: '1970-01-01', // the world may never know - os: os, - arch: arch, - ext: '', // let normalize run the split/test/join - hash: '-', // not ready to standardize this yet - download: filename, - }); - }); - }); - - return all; - }); -} - -module.exports = getAllReleases; - -if (module === require.main) { - getAllReleases(require('@root/request')).then(function (all) { - all = require('../_webi/normalize.js')(all); - all.releases = all.releases.slice(0, 10); - console.info(JSON.stringify(all, null, 2)); - }); -} +module.exports = require('../go/releases.js');