[mike@mwxm4]

This commit is contained in:
2026-08-12 17:03:43 +02:00
parent 4ad3d2e13d
commit 94f5ec969d
11 changed files with 847 additions and 209 deletions
+4 -73
View File
@@ -5,7 +5,6 @@ import (
"crypto/rand"
"database/sql"
"encoding/base64"
"encoding/hex"
"flag"
"fmt"
"io"
@@ -15,96 +14,28 @@ import (
"os"
"path/filepath"
"regexp"
"runtime"
"strconv"
"strings"
"time"
"github.com/AlecAivazis/survey/v2"
"github.com/AlecAivazis/survey/v2/core"
"github.com/AlecAivazis/survey/v2/terminal"
"github.com/Masterminds/semver/v3"
"github.com/eknkc/basex"
"github.com/fatih/color"
"github.com/mgutz/ansi"
"github.com/minio/selfupdate"
"github.com/spf13/viper"
"github.com/tidwall/gjson"
)
var tbversion = "0.7.0"
var HTTPTIMEOUT = 3 * time.Second // version.txt / checksums.txt - must never stall a build
var DOWNLOADTIMEOUT = 10 * time.Minute // the binary itself, http.Client.Timeout covers the whole body
var CHRS = "VW9IdGJ6eXh1T25DRHdrc2M5MlhOQVNQcEJFWnJhWVY2ZEowaFJLdmoxNUdxVDRJZkZpTTdRZW0zTFc4Z2w="
var LR = []rune("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
func checkforupdate(URL string) { // ----------------------------------------------------- check for new version
prg := prgname()
client := &http.Client{Timeout: HTTPTIMEOUT}
body, err := fetch(client, URL+"/version.txt", 1<<20) // update server unreachable: never block the build
if err != nil { return }
lversion := strings.TrimSpace(string(body)) // exactly as published - it names the artifact
sv_version, err := semver.NewVersion(version)
if err != nil { return }
sv_lversion, err := semver.NewVersion(lversion)
if err != nil { return }
if !sv_lversion.GreaterThan(sv_version) { return }
if !Yesno(SF("new '%s' version found (%s -> %s), update now?",prg,sv_version,lversion),true,false) {
return
}
target := SF("%s_%s_%s_%s",prg,lversion,runtime.GOOS,runtime.GOARCH)
if runtime.GOOS == "windows" { target += ".exe" }
sum, err := getchecksum(client, URL+"/checksums.txt", target) // no checksum -> no update
if err != nil {
PE("update aborted", err.Error())
os.Exit(1)
}
if err := doupdate(&http.Client{Timeout: DOWNLOADTIMEOUT}, URL+"/"+target, sum); err != nil {
PE("update failed", err.Error())
os.Exit(1)
}
PO("update successful","please run your last command again")
os.Exit(0)
}
func doupdate(client *http.Client, url string, checksum []byte) error { // --------------------------- do update
resp, err := client.Get(url)
if err != nil { return err }
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK { return SE("server returned status: %v", resp.Status) }
return selfupdate.Apply(resp.Body, selfupdate.Options{Checksum: checksum})
}
func getchecksum(client *http.Client, url string, name string) ([]byte, error) { // -- sha256 of a published file
body, err := fetch(client, url, 1<<20)
if err != nil { return nil, SE("no checksums published (%v)", err) }
for _, line := range strings.Split(string(body), "\n") {
f := strings.Fields(line)
if len(f) == 2 && f[1] == name {
sum, err := hex.DecodeString(f[0])
if err != nil { return nil, SE("bad checksum for %s", name) }
return sum, nil
}
}
return nil, SE("no checksum for %s", name)
}
func fetch(client *http.Client, url string, max int64) ([]byte, error) { // ------------------- fetch a small file
resp, err := client.Get(url)
if err != nil { return nil, err }
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK { return nil, SE("server returned status: %v", resp.Status) }
return io.ReadAll(io.LimitReader(resp.Body, max))
}
// Updating oneself lives in selfupdate.go — one file per program, configured at
// its head, driven by the --update and --check-update options. It fetches from
// the releases of the gitea and weighs every download against the checksum
// published beside it.
func checkaccess(NETS []string) { // ------------------------------------------------- check ip net based access
match:=0;