diff --git a/cmd/she/main.go b/cmd/she/main.go index daa7d72..6c5bd08 100644 --- a/cmd/she/main.go +++ b/cmd/she/main.go @@ -6,14 +6,31 @@ import ( "fmt" "io" "os" + "runtime/debug" "strings" "github.com/antonysastre/sheets/internal/sheet" ) // version is overridden at build time via -ldflags "-X main.version=...". +// When unset (e.g. `go install ...@latest`, which bypasses our Makefile), +// versionString falls back to the module version from runtime/debug. var version = "dev" +func versionString() string { + if version != "dev" { + return version + } + info, ok := debug.ReadBuildInfo() + if !ok { + return version + } + if v := info.Main.Version; v != "" && v != "(devel)" { + return v + } + return version +} + func main() { os.Exit(run(os.Args, os.Stdout, os.Stderr)) } @@ -69,7 +86,7 @@ func run(args []string, stdout, stderr io.Writer) int { printUsage(stdout) case "--version", "-V": - _, _ = fmt.Fprintf(stdout, "she %s\n", version) + _, _ = fmt.Fprintf(stdout, "she %s\n", versionString()) // "--" ends option parsing, so the next argument is taken literally — // the only way to view a sheet whose name begins with a dash. diff --git a/cmd/she/main_test.go b/cmd/she/main_test.go index 4e290c8..f5002dd 100644 --- a/cmd/she/main_test.go +++ b/cmd/she/main_test.go @@ -65,3 +65,26 @@ func checkStream(t *testing.T, name, got, want string) { t.Errorf("%s = %q, want it to contain %q", name, got, want) } } + +// versionString prefers the ldflags-injected value when present so `make +// build` carries `git describe`, but falls back to runtime/debug so a plain +// `go install ...@latest` (no ldflags) still reports the module version. +func TestVersionString(t *testing.T) { + orig := version + t.Cleanup(func() { version = orig }) + + version = "v1.2.3" + if got := versionString(); got != "v1.2.3" { + t.Errorf("ldflags-set: versionString() = %q, want %q", got, "v1.2.3") + } + + // "dev" sentinel — fall back to runtime/debug. Under `go test`, + // debug.ReadBuildInfo populates a synthetic Main.Version of "(devel)", + // which versionString rejects in favor of "dev". We can't easily + // exercise the happy fallback path (it needs a module-aware install), + // so verify the (devel)-or-empty path stays at "dev". + version = "dev" + if got := versionString(); got != "dev" { + t.Errorf("dev sentinel: versionString() = %q, want %q", got, "dev") + } +}