--force-update reports from/to versions; elevated parent no longer claims "update applied" when nothing changed
This commit is contained in:
+40
-11
@@ -39,6 +39,11 @@ var version = "dev"
|
||||
// process: a signed update has been staged and the GPU lock is idle.
|
||||
const exitCodeUpdate = 3
|
||||
|
||||
// exitCodeStaged is returned by an elevated --force-update child when it
|
||||
// staged a new binary, so the non-elevated parent can tell "updated" from
|
||||
// "up to date" (it cannot see the child's console).
|
||||
const exitCodeStaged = 4
|
||||
|
||||
// stdoutIsTerminal reports whether stdout is a console (char device), as
|
||||
// opposed to a pipe or file — which is what Docker containers and services
|
||||
// see.
|
||||
@@ -348,11 +353,12 @@ func forceUpdateCommand(configPath string, elevatedChild bool) int {
|
||||
// instead of hanging in a TCP connect for minutes.
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
|
||||
defer cancel()
|
||||
staged, err := u.Check(ctx, exePath)
|
||||
staged, to, err := u.Check(ctx, exePath)
|
||||
if err != nil && isPermission(err) && !service.Elevated() {
|
||||
code, _ := elevateAndMirror("--force-update")
|
||||
if code == 0 {
|
||||
fmt.Println("update applied (elevated)")
|
||||
reportElevatedUpdate(code, to)
|
||||
if code == 0 || code == exitCodeStaged {
|
||||
return 0
|
||||
}
|
||||
return code
|
||||
}
|
||||
@@ -364,12 +370,13 @@ func forceUpdateCommand(configPath string, elevatedChild bool) int {
|
||||
fmt.Printf("%s is up to date\n", versionLine())
|
||||
return 0
|
||||
}
|
||||
fmt.Printf("%s: update staged\n", versionLine())
|
||||
fmt.Printf("gpu-turnstile: updated from %s to %s\n", version, to)
|
||||
restarted, err := service.RestartIfRunning()
|
||||
if err != nil && isPermission(err) && !service.Elevated() {
|
||||
code, _ := elevateAndMirror("--force-update")
|
||||
if code == 0 {
|
||||
fmt.Println("update applied (elevated)")
|
||||
reportElevatedUpdate(code, to)
|
||||
if code == 0 || code == exitCodeStaged {
|
||||
return 0
|
||||
}
|
||||
return code
|
||||
}
|
||||
@@ -378,13 +385,35 @@ func forceUpdateCommand(configPath string, elevatedChild bool) int {
|
||||
return 1
|
||||
}
|
||||
if restarted {
|
||||
fmt.Println("service restarted on the new version")
|
||||
fmt.Println("service restarted on " + to)
|
||||
} else {
|
||||
fmt.Println("no running service; the new version applies on next start")
|
||||
fmt.Println("no running service; " + to + " applies on the next start")
|
||||
}
|
||||
if elevatedChild {
|
||||
// Tell the non-elevated parent (which cannot see this console)
|
||||
// whether anything was staged, so its mirror message is honest.
|
||||
return exitCodeStaged
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// reportElevatedUpdate prints the parent's summary of an elevated
|
||||
// --force-update child: exitCodeStaged means the child staged a new binary,
|
||||
// 0 means it found nothing to do. to is the tag the parent's own check
|
||||
// resolved before it hit the permission wall ("" when it never got that
|
||||
// far).
|
||||
func reportElevatedUpdate(code int, to string) {
|
||||
switch {
|
||||
case code == exitCodeStaged && to != "":
|
||||
fmt.Printf("gpu-turnstile: updated from %s to %s (elevated)\n", version, to)
|
||||
case code == exitCodeStaged:
|
||||
fmt.Println("update applied (elevated)")
|
||||
case code == 0:
|
||||
fmt.Printf("%s is up to date\n", versionLine())
|
||||
}
|
||||
// Non-zero, non-staged codes: elevateAndMirror already printed the failure.
|
||||
}
|
||||
|
||||
// serviceCommand installs (copyBin = register the canonical-layout copy)
|
||||
// or removes the service and reports the result. On Windows, when the
|
||||
// shell is not elevated, the command relaunches itself through a UAC
|
||||
@@ -813,16 +842,16 @@ func updateLoop(ctx context.Context, cfg config.Config, log *slog.Logger, lk *lo
|
||||
}
|
||||
u := &update.Updater{Repo: cfg.UpdateRepo, Asset: cfg.UpdateAsset, Version: version, Desired: cfg.AppVersion, Log: log}
|
||||
for {
|
||||
staged, err := u.Check(ctx, exePath)
|
||||
staged, to, err := u.Check(ctx, exePath)
|
||||
if err != nil && ctx.Err() == nil {
|
||||
log.Warn("auto-update check failed", "err", err)
|
||||
}
|
||||
if staged {
|
||||
if !isService {
|
||||
log.Warn("auto-update: new binary staged; restart gpu-turnstile to apply")
|
||||
log.Warn("auto-update: new binary staged; restart gpu-turnstile to apply", "version", to)
|
||||
return
|
||||
}
|
||||
log.Warn("auto-update: staged; restarting once the GPU is idle")
|
||||
log.Warn("auto-update: staged; restarting once the GPU is idle", "version", to)
|
||||
if waitForIdle(ctx, lk, 24*time.Hour) {
|
||||
log.Warn("auto-update: restarting to apply update")
|
||||
os.Exit(exitCodeUpdate)
|
||||
|
||||
Reference in New Issue
Block a user