@@ -1,12 +1,21 @@
11package version
22
3−import "runtime/debug"
3+import (
4+ "os"
5+ "runtime/debug"
6+ "strconv"
7+)
48
59// Build-time parameters set via -ldflags.
610
711var (
812 Version = "devel"
913 Commit = "unknown"
14+ // BuildID is a unique identifier for this build. For release builds it
15+ // equals Commit; for development builds (go run / go build without
16+ // ldflags) it is derived from the executable's modification time, which
17+ // changes on every recompilation.
18+ BuildID = ""
1019)
1120
1221// A user may install crush using `go install github.com/charmbracelet/crush@latest`.
@@ -15,11 +24,30 @@ var (
1524// is only set for `go install` and not for `go build`).
1625func init() {
1726 info, ok := debug.ReadBuildInfo()
18− if !ok {
19− return
27+ if ok {
28+ mainVersion := info.Main.Version
29+ if mainVersion != "" && mainVersion != "(devel)" {
30+ Version = mainVersion
31+ }
32+ }
33+
34+ // Derive BuildID when not set via ldflags.
35+ if BuildID == "" {
36+ BuildID = deriveBuildID()
37+ }
38+}
39+
40+// deriveBuildID uses the running executable's modification time as a unique
41+// build fingerprint. This changes on every recompilation (including `go run`),
42+// making it reliable for detecting stale servers during development.
43+func deriveBuildID() string {
44+ exe, err := os.Executable()
45+ if err != nil {
46+ return "unknown"
2047 }
21− mainVersion := info.Main.Version
22− if mainVersion != "" && mainVersion != "(devel)" {
23− Version = mainVersion
48+ fi, err := os.Stat(exe)
49+ if err != nil {
50+ return "unknown"
2451 }
52+ return strconv.FormatInt(fi.ModTime().UnixNano(), 36)
2553}