[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
+32 -78
View File
@@ -24,11 +24,12 @@ import (
"github.com/fsnotify/fsnotify"
)
var version = "1.21.0"
var UPDATEURL = "https://gozilla.fhi.mpg.de/gbld"
var UPLOADHOST = "root@gozilla"
var UPLOADPATH = "/db/www"
// version is a var, not a const, so build.sh can put the built number in via
// -ldflags "-X main.version=…". The value here only ever shows up in a bare
// `go build`; the version a release carries is the one in version.txt. Note
// that -a below names its artifacts from this line and not from version.txt —
// for gbld's own releases build.sh is the way, not -a.
var version = "1.22.0"
var oses = []string{"darwin", "linux", "windows"}
var arches = []string{"arm64", "amd64"}
@@ -49,7 +50,6 @@ var r3 = regexp.MustCompile(`\.go$`) // go sour
var r4 = regexp.MustCompile(`(?m)^(\s*var\s+build\s*=\s*")([^"]*)(")`) // build counter
var r5 = regexp.MustCompile(`(?im)^\s*var\s+version\s*=\s*"([^"]*)"`) // target version
var r6 = regexp.MustCompile(`(?s)import\s*\((.*?)\)`) // import block
var r7 = regexp.MustCompile(`^[A-Za-z0-9._-]+$`) // safe build name
type opts struct { // ------------------------------------------------------------------------- command line options
buildonly bool
@@ -80,7 +80,11 @@ func main() { // ===============================================================
opt_a := flag.Bool("a", false, "")
opt_v := flag.Bool("v", false, "")
opt_h := flag.Bool("h", false, "")
opt_u := flag.Bool("u", false, "")
opt_update := flag.Bool("update", false, "") // selfupdate.go
opt_checkupdate := flag.Bool("check-update", false, "")
opt_refresh := flag.Bool(strings.TrimPrefix(updateRefreshFlag, "--"), false, "") // background run, not in the
// help, name tied to the const
flag.Usage = func() {
P()
@@ -88,7 +92,7 @@ func main() { // ===============================================================
P()
P(Cw("Usage:"))
P(Cy(" gbld [-b] [-1] [-i] [-x] [-c <CMD>] [-o <OPTIONS>] [build name]"))
P(Cy(" gbld [-a] [-u]"))
P(Cy(" gbld [-a]"))
P(Cw(" -b build only"))
P(Cw(" -1 run only once, no watching (exit code: build error or exit code of the build)"))
P(Cw(" -i run goimports before build"))
@@ -98,7 +102,8 @@ func main() { // ===============================================================
P(Cw(" -v show version"))
P(Cw(" -h show help"))
P(Cw(" -a build for all platforms"))
P(Cw(" -u upload builds to " + UPLOADHOST))
P(Cw(" --check-update look for a newer release"))
P(Cw(" --update download and install the newest release"))
P()
P(Cw(" · if no build name is supplied the current directory name will be used"))
P()
@@ -120,18 +125,14 @@ func main() { // ===============================================================
o := opts{buildonly: *opt_b, once: *opt_1, imports: *opt_i, exitafter: *opt_x,
postcmd: *opt_c, runargs: *opt_o}
if *opt_v { // ·············································································· show version
info()
os.Exit(0)
}
if *opt_h { // ····················································································· show help
flag.Usage()
os.Exit(0)
}
if os.Getenv("GBLD_NO_UPDATE") == "" { // ······································· check for a newer gbld version
checkforupdate(UPDATEURL)
// These run before the toolchain is looked for: none of them needs 'go' or // no go,
// 'goimports', and selfupdate.go probes a fresh download with 'gbld -v', // no goimports
// which therefore has to work on a machine that has neither.
if (*opt_refresh) { selfUpdate.refresh(); return // update options
} else if (*opt_update) { runupdate(selfUpdate.install); return
} else if (*opt_checkupdate) { runupdate(selfUpdate.check); return
} else if (*opt_v) { info(); return
} else if (*opt_h) { flag.Usage(); return
}
GO = lookup("go") // ······················································· check for the required toolchain
@@ -157,14 +158,6 @@ func main() { // ===============================================================
if *opt_a { // ······························································· build for other platforms
info()
buildall(name)
}
if *opt_u { // ······································································ upload builds to gozilla
info()
uploadall(name)
}
if *opt_a || *opt_u {
os.Exit(0)
}
@@ -274,6 +267,14 @@ func buildAndRun(name, file string, o opts) bool { // -------------------------
PN("\033[2J\033[1;1H")
}
info()
// Costs nothing: the hint comes from the note in the cache, the asking
// happens once a day at most and in the background. It stands after the
// screen is cleared, or every rebuild would wipe it away again.
if hint := selfUpdate.daily(); hint != "" {
P(Cy(hint))
}
P(Cc("--- start compiling " + file + " ---"))
stopRunning()
@@ -478,58 +479,11 @@ func buildall(name string) { // ------------------------------------------------
PO("all builds done", targetversion)
}
func uploadall(name string) { // ------------------------------------------------------- upload builds to gozilla
if !r7.MatchString(name) { // the name ends up in a remote shell command
PE("invalid build name", name)
os.Exit(1)
}
targetversion, err := gettargetversion()
if err != nil {
func runupdate(task func(io.Writer) error) { // ----------------------------------- run a task from selfupdate.go
if err := task(os.Stdout); err != nil {
PE(err.Error())
os.Exit(1)
}
files := []string{}
for _, osys := range oses {
for _, arch := range arches {
ofile := filepath.Join("bin", artifact(name, targetversion, osys, arch))
if fileExists(ofile) {
files = append(files, ofile)
}
}
}
if len(files) == 0 {
PE("no builds found for version "+targetversion, "run 'gbld -a' first")
os.Exit(1)
}
for _, f := range []string{"bin/checksums.txt", "bin/version.txt"} {
if !fileExists(f) {
PE("missing "+f, "run 'gbld -a' first")
os.Exit(1)
}
files = append(files, f)
}
P(Ccb("upload builds to "+UPLOADHOST), Cwb(targetversion))
dst := UPLOADPATH + "/" + name
if err := run("ssh", UPLOADHOST, SF("mkdir -p '%s' && rm -f '%s'/*_*_*", dst, dst)); err != nil {
os.Exit(1)
}
if err := run(append([]string{"scp"}, append(files, UPLOADHOST+":"+dst)...)...); err != nil {
os.Exit(1)
}
PO("upload done", targetversion)
}
func run(args ...string) error { // ------------------------------------------------- run a command, report failure
P(Cy(strings.Join(args, " ")))
out, err := exec.Command(args[0], args[1:]...).CombinedOutput()
if err != nil {
PE(args[0]+" failed", strings.TrimSpace(string(out)))
}
return err
}
func artifact(name, version, osys, arch string) string { // ------------------------------ name of a build artifact