Files
goca/update.go
2026-07-27 16:14:41 +02:00

128 lines
3.3 KiB
Go

package main
import (
"bufio"
"fmt"
"net/http"
"os"
"path/filepath"
"runtime"
"strings"
"github.com/AlecAivazis/survey/v2"
"github.com/AlecAivazis/survey/v2/terminal"
"github.com/Masterminds/semver/v3"
"github.com/fatih/color"
"github.com/minio/selfupdate"
)
var UPDATEURL = "http://gozilla.fhi.mpg.de/goca"
// Color function variables matching tools.go in dns
var Crb func(...interface{}) string = color.New(color.Bold, color.FgRed).SprintFunc()
var Cgb func(...interface{}) string = color.New(color.Bold, color.FgGreen).SprintFunc()
var Cwb func(...interface{}) string = color.New(color.Bold, color.FgWhite).SprintFunc()
func SF(format string, a ...any) string {
return fmt.Sprintf(format, a...)
}
func PE(msg ...string) (n int, err error) {
if len(msg) == 2 {
return fmt.Fprintf(os.Stdout, "%s: %s (%s)\n", Crb("ERROR"), Cwb(msg[0]), msg[1])
}
return fmt.Fprintf(os.Stdout, "%s: %s\n", Crb("ERROR"), Cwb(msg[0]))
}
func PO(msg ...string) (n int, err error) {
if len(msg) == 2 {
return fmt.Fprintf(os.Stdout, "%s: %s (%s)\n", Cgb("OK"), Cwb(msg[0]), msg[1])
}
return fmt.Fprintf(os.Stdout, "%s: %s\n", Cgb("OK"), Cwb(msg[0]))
}
func checkforupdate(URL string) { // ----------------------------------------------------- check for new version
prg := prgname()
resp, err := http.Get(URL + "/version.txt")
if err == nil {
scanner := bufio.NewScanner(resp.Body)
if scanner.Scan() {
lversion := strings.TrimSpace(scanner.Text())
sv_version, err := semver.NewVersion(Version)
if err == nil {
sv_lversion, err := semver.NewVersion(lversion)
if err == nil {
if sv_lversion.GreaterThan(sv_version) {
ans := Yesno(SF("new '%s' version found (%s -> %s), update now?",
prg, sv_version, sv_lversion), true, false)
if ans {
updateurl := SF("%s/%s_%s_%s_%s", URL, prg, lversion, runtime.GOOS, runtime.GOARCH)
if err := doupdate(updateurl); err != nil {
PE(SF("Update failed: %v\n", err))
os.Exit(1)
}
PO("Update successful!", "please run your last command again")
os.Exit(0)
}
}
}
}
}
resp.Body.Close()
}
}
func doupdate(url string) error { // ----------------------------------------------------------------- do update
resp, err := http.Get(url)
if err != nil {
return err
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return fmt.Errorf("server returned status: %v", resp.Status)
}
err = selfupdate.Apply(resp.Body, selfupdate.Options{})
if err != nil {
return err
}
return nil
}
func Yesno(msg string, def bool, overwrite bool) bool { // -------------------------- AlecAivazis/survey: yes/no
if overwrite {
return true
}
var err error
tmp := ""
if def {
err = survey.AskOne(&survey.Select{Message: msg, Options: []string{"Yes", "No"}}, &tmp)
} else {
err = survey.AskOne(&survey.Select{Message: msg, Options: []string{"No", "Yes"}}, &tmp)
}
if err != nil {
if err == terminal.InterruptErr {
fmt.Fprintln(os.Stdout, Crb("Interrupted."))
os.Exit(0)
}
}
if tmp == "Yes" {
return true
} else {
return false
}
}
func prgname() string { // ---------------------------------------------------------------- program name
exepath, err := os.Executable()
if err != nil {
PE(SF("Error getting executable path: %s", err))
return ""
}
exename := filepath.Base(exepath)
return exename
}