MCPcopy Create free account
hub / github.com/codehamr/codehamr / maybeSelfUpdate

Function maybeSelfUpdate

cmd/codehamr/main.go:163–200  ·  view source on GitHub ↗

maybeSelfUpdate runs the pre-launch auto-update. No-op for local builds, an already-current hash, an unsupported platform (see update.assetName), or any network/filesystem refusal. On success it swaps the binary and re-execs via reExec (which only returns on failure). Any failure past "update availa

()

Source from the content-addressed store, hash-verified

161// re-execs via reExec (which only returns on failure). Any failure past
162// "update available" prints one stderr line and proceeds with the old binary.
163func maybeSelfUpdate() {
164 // Skip local builds: hashing a `go run` temp binary against the
165 // published checksum would otherwise swap in the last release and hide
166 // unreleased work behind an "update applied" banner.
167 if isLocalBuild(version) {
168 return
169 }
170 exe, err := os.Executable()
171 if err != nil {
172 return
173 }
174 ctx, cancel := context.WithTimeout(context.Background(), updateBudget)
175 defer cancel()
176 if !update.Check(ctx, exe) {
177 return
178 }
179 fmt.Fprintln(os.Stderr, "◉ applying codehamr update...")
180 if err := update.Apply(ctx, exe); err != nil {
181 fmt.Fprintf(os.Stderr, "⚠ update failed: %v\n", err)
182 if os.IsPermission(err) {
183 fmt.Fprintln(os.Stderr, " tip: rerun with sudo, or reinstall with PREFIX=$HOME/.local")
184 }
185 return
186 }
187 // Re-launch the new binary. reExec is platform-split: unix execve (same
188 // PID) vs. Windows spawn-and-wait. CODEHAMR_NO_UPDATE_CHECK=1 stops the
189 // replacement run from re-checking its own freshly-written hash. On
190 // reExec failure we fall through to the old in-memory binary.
191 if err := reExec(exe, os.Args, reexecEnv()); err != nil {
192 fmt.Fprintf(os.Stderr, "⚠ re-exec failed: %v (continuing with previous version)\n", err)
193 }
194}
195
196// reexecEnv arms the update-loop guard and returns the environment for the
197// re-exec'd child. os.Setenv overwrites in place so os.Environ() carries
198// exactly one entry; append(os.Environ(), …) would leave a pre-existing
199// user-set value first, and Unix execve resolves os.Getenv to the FIRST
200// match, silently defeating the guard if someone exported
201// CODEHAMR_NO_UPDATE_CHECK to a non-"1" value.
202func reexecEnv() []string {
203 os.Setenv("CODEHAMR_NO_UPDATE_CHECK", "1")

Callers 1

mainFunction · 0.85

Calls 4

CheckFunction · 0.92
ApplyFunction · 0.92
isLocalBuildFunction · 0.85
reExecFunction · 0.70

Tested by

no test coverage detected