dl/cmd/godl/main.go

161 lines
3.7 KiB
Go

package main
import (
"context"
"flag"
"fmt"
"io"
"net/http"
"os"
"os/exec"
"path/filepath"
"runtime"
"strings"
"git.jojodev.com/golang/dl"
"github.com/schollz/progressbar/v3"
)
var f = false
func main() {
downloadFlag := flag.Bool("download", false, "Download latest Go")
installFlag := &f
if runtime.GOOS == "linux" {
installFlag = flag.Bool("install", false, "Install/Update Go")
}
outFlag := flag.String("out", ".", "Where to put the downloaded file")
flag.Parse()
latest, err := latestVersion()
if err != nil {
fmt.Println(err)
return
}
if !*downloadFlag && !*installFlag {
ver, err := goVersion()
if err != nil {
fmt.Println(err)
return
}
fmt.Printf("Current: %sLatest: %s\n", ver, latest.Version)
return
}
outPath := filepath.Join(*outFlag, latest.Filename)
if *downloadFlag {
if err := download(latest.Filename, outPath); err != nil {
fmt.Println(err)
return
}
fmt.Println(outPath)
}
if *installFlag {
if err := install(outPath); err != nil {
fmt.Println(err)
return
}
ver, err := goVersion()
if err != nil {
fmt.Println(err)
return
}
fmt.Printf("Successfully installed: %s\n", ver)
}
}
func goVersion() (string, error) {
goVersion := exec.Command("/usr/local/go/bin/go", "version")
out, err := goVersion.Output()
if err != nil {
return "", fmt.Errorf("could not check go version: %v", err)
}
return string(out), nil
}
func latestVersion() (*dl.File, error) {
versions, err := dl.Versions(context.Background())
if err != nil {
return nil, fmt.Errorf("could not get latest Go version(s): %v", err)
}
if len(versions) < 1 {
return nil, fmt.Errorf("no latest Go version(s) found: %v", err)
}
var version dl.File
for _, file := range versions[0].Files {
if strings.EqualFold(file.OS, runtime.GOOS) && strings.EqualFold(file.Arch, runtime.GOARCH) {
version = file
break
}
}
if version.Filename == "" {
return nil, fmt.Errorf("could not find a download for OS = %s | Arch = %s", runtime.GOOS, runtime.GOARCH)
}
return &version, nil
}
func download(filename, outPath string) error {
outFile, err := os.Create(outPath)
if err != nil {
return fmt.Errorf("could not create file for download: %v", err)
}
defer outFile.Close()
req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("https://golang.org/dl/%s", filename), nil)
if err != nil {
return fmt.Errorf("could not create request: %v", err)
}
req.Header.Set("User-Agent", "git.jojodev.com/golang/dl/cmd/godl")
res, err := http.DefaultClient.Do(req)
if err != nil {
return fmt.Errorf("could not download file: %v", err)
}
defer res.Body.Close()
bar := progressbar.DefaultBytes(
res.ContentLength,
fmt.Sprintf("downloading %s", filename),
)
if _, err := io.Copy(io.MultiWriter(outFile, bar), res.Body); err != nil {
return err
}
return nil
}
func install(outPath string) error {
if os.Geteuid() != 0 {
return fmt.Errorf(`This command must be run as root to perform the install.
Alternatively, you can run the following command manually, which is taken from https://golang.org/doc/install#install
rm -rf /usr/local/go && tar -C /usr/local -xzf ` + outPath)
}
fmt.Println("removing local installation")
rm := exec.Command("rm", "-rf", "/usr/local/go")
if err := rm.Run(); err != nil {
return fmt.Errorf("could not remove local go installation: %v", err)
}
fmt.Println("extracting new installation")
tar := exec.Command("tar", "-C", "/usr/local", "-xzf", outPath)
if err := tar.Run(); err != nil {
return fmt.Errorf("could not extract new installation: %v", err)
}
rmDl := exec.Command("rm", outPath)
if err := rmDl.Run(); err != nil {
return fmt.Errorf("could not remove downloaded file: %v", err)
}
return nil
}