Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions internal/cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@ var (
// Execute adds all child commands to the root command and sets flags appropriately.
// This is called by main.main(). It only needs to happen once to the rootCmd.
func Execute() {
// Cobra only registers the --version flag when Version is non-empty.
// Setting the template alone left --version and -v undefined, even though
// the man page and the shell completions both advertised them.
RootCmd.Version = version.GetVersion()
RootCmd.SetVersionTemplate("y509 version {{.Version}}\nBuild: " + version.GetFullVersion() + "\n")

if err := RootCmd.Execute(); err != nil {
Expand Down
36 changes: 36 additions & 0 deletions internal/version/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
package version

import (
"runtime/debug"
"strings"
)

Expand All @@ -14,6 +15,41 @@ var (
BuildDate = "unknown"
)

// Release builds get these values from -ldflags. A `go install` build gets no
// ldflags at all, so it reported itself as "dev" forever -- even though the
// toolchain had already stamped the module version and the VCS revision into
// the binary. Read them back out.
func init() {
info, ok := debug.ReadBuildInfo()
if !ok {
return
}

// Each value falls back on its own. A build that sets only Version through
// -ldflags should still pick up the commit and the build time the toolchain
// recorded, rather than being left reporting "unknown" for both.
if Version == "dev" {
// "(devel)" is what a build from a local working tree reports.
if info.Main.Version != "" && info.Main.Version != "(devel)" {
Version = info.Main.Version
}
}
for _, setting := range info.Settings {
switch setting.Key {
case "vcs.revision":
// An empty value must not overwrite "unknown" -- it would render as
// "y509 version dev ()".
if GitCommit == "unknown" && setting.Value != "" {
GitCommit = setting.Value
}
case "vcs.time":
if BuildDate == "unknown" && setting.Value != "" {
BuildDate = setting.Value
}
}
}
Comment thread
kanywst marked this conversation as resolved.
Comment thread
kanywst marked this conversation as resolved.
Comment thread
kanywst marked this conversation as resolved.
Comment thread
kanywst marked this conversation as resolved.
Comment on lines +37 to +50

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

When building with go install from a dirty working tree, the vcs.revision setting will return the clean commit hash, but the binary actually contains uncommitted changes. To accurately reflect this, we should also check the vcs.modified setting and append -dirty to the GitCommit if it is true and we are falling back to the VCS revision.

	var modified bool
	var commitUpdated bool
	for _, setting := range info.Settings {
		switch setting.Key {
		case "vcs.revision":
			// An empty value must not overwrite "unknown" -- it would render as
			// "y509 version dev ()".
			if GitCommit == "unknown" && setting.Value != "" {
				GitCommit = setting.Value
				commitUpdated = true
			}
		case "vcs.time":
			if BuildDate == "unknown" && setting.Value != "" {
				BuildDate = setting.Value
			}
		case "vcs.modified":
			modified = setting.Value == "true"
		}
	}
	if modified && commitUpdated && !strings.HasSuffix(GitCommit, "-dirty") {
		GitCommit += "-dirty"
	}

}
Comment thread
kanywst marked this conversation as resolved.

// GetVersion returns the version string
func GetVersion() string {
return Version
Expand Down