From 0eaafb64b4042c8028098ed5133061fb7dc37cdf Mon Sep 17 00:00:00 2001 From: Jimmy Zelinskie Date: Thu, 21 Apr 2022 16:06:23 -0400 Subject: [PATCH] version: use buildinfo vcs revision --- version.go | 42 +++++++++++++++++++++++++++++++++++------- 1 file changed, 35 insertions(+), 7 deletions(-) diff --git a/version.go b/version.go index 98f24dd..4ac473a 100644 --- a/version.go +++ b/version.go @@ -6,15 +6,47 @@ import ( "runtime/debug" "strings" + "github.com/jzelinskie/stringz" "github.com/spf13/cobra" "github.com/spf13/pflag" ) +func findBuildSetting(bi *debug.BuildInfo, key string) string { + for _, setting := range bi.Settings { + if setting.Key == key { + return setting.Value + } + } + return "" +} + +func vcsRevision(bi *debug.BuildInfo) string { + revision := findBuildSetting(bi, "vcs.revision") + if revision == "" { + return "" + } + + revision = revision[:12] // Short SHA + + if findBuildSetting(bi, "vcs.modified") == "true" { + revision = revision + "-dirty" + } + + return revision +} + // Version is variable that holds program's version string. // This should be set with the follow flags to the `go build` command: // -ldflags '-X github.com/jzelinskie/cobrautil.Version=$YOUR_VERSION_HERE' var Version string +// VersionWithFallbacks returns a string of the program version. +// If the version wasn't set by ldflags, falls back to the VCS revision, and +// finally Go module version. +func VersionWithFallbacks(bi *debug.BuildInfo) string { + return stringz.DefaultEmpty(stringz.DefaultEmpty(Version, vcsRevision(bi)), bi.Main.Version) +} + // UsageVersion introspects the process debug data for Go modules to return a // version string. func UsageVersion(programName string, includeDeps bool) string { @@ -23,21 +55,17 @@ func UsageVersion(programName string, includeDeps bool) string { panic("failed to read BuildInfo because the program was compiled with Go " + runtime.Version()) } - if Version == "" { - // The version wasn't set by ldflags, so fallback to the Go module version. - // Although, this value is pretty much guaranteed to just be "(devel)". - Version = bi.Main.Version - } + version := VersionWithFallbacks(bi) if !includeDeps { if Version == "(devel)" { return fmt.Sprintf("%s development build (unknown exact version)", programName) } - return fmt.Sprintf("%s %s", programName, Version) + return fmt.Sprintf("%s %s", programName, version) } var b strings.Builder - fmt.Fprintf(&b, "%s %s", bi.Path, Version) + fmt.Fprintf(&b, "%s %s", bi.Path, version) for _, dep := range bi.Deps { fmt.Fprintf(&b, "\n\t%s %s", dep.Path, dep.Version) }