98 lines
2.5 KiB
Go
98 lines
2.5 KiB
Go
// Package buildinfo reports the version, commit and build date of the running
|
|
// binary.
|
|
//
|
|
// Release builds have these stamped in by goreleaser through -ldflags. When
|
|
// that has not happened, as with `go build` or `go install`, the values are
|
|
// recovered from the module metadata the toolchain embeds. Anything that
|
|
// cannot be established as a real release is reported as a development build,
|
|
// which is what disables the update machinery.
|
|
package buildinfo
|
|
|
|
import (
|
|
"fmt"
|
|
"runtime"
|
|
"runtime/debug"
|
|
"strings"
|
|
|
|
"golang.org/x/mod/module"
|
|
"golang.org/x/mod/semver"
|
|
)
|
|
|
|
// devVersion is the version reported by builds that were not produced by a
|
|
// release. Both the update check and `godeez update` refuse to run on them.
|
|
const devVersion = "dev"
|
|
|
|
// Injected at link time by goreleaser. They are unexported and read through
|
|
// the accessors below so nothing can depend on their zero values directly.
|
|
var (
|
|
version = devVersion
|
|
commit = ""
|
|
date = ""
|
|
)
|
|
|
|
// Version returns the release version without a leading "v", or devVersion
|
|
// for anything that is not a release build. Binaries built with `go install`
|
|
// carry no ldflags but do record the module version, so that is consulted
|
|
// before giving up.
|
|
func Version() string {
|
|
if version != devVersion {
|
|
return version
|
|
}
|
|
|
|
if info, ok := debug.ReadBuildInfo(); ok {
|
|
if v := releaseVersion(info.Main.Version); v != "" {
|
|
return v
|
|
}
|
|
}
|
|
|
|
return devVersion
|
|
}
|
|
|
|
// releaseVersion accepts v only if it names a published release, returning ""
|
|
// otherwise.
|
|
//
|
|
// Pseudo-versions describe a commit that was never tagged, and a build suffix
|
|
// marks a local or modified build. Treating either as a release would offer
|
|
// the user an update path from a version that does not exist.
|
|
func releaseVersion(v string) string {
|
|
if !semver.IsValid(v) {
|
|
return ""
|
|
}
|
|
if semver.Build(v) != "" || module.IsPseudoVersion(v) {
|
|
return ""
|
|
}
|
|
|
|
return strings.TrimPrefix(v, "v")
|
|
}
|
|
|
|
func IsDev() bool {
|
|
return Version() == devVersion
|
|
}
|
|
|
|
// Commit returns the revision the binary was built from, falling back to the
|
|
// VCS stamp the Go toolchain records when building inside a repository. It
|
|
// returns "" when neither is available.
|
|
func Commit() string {
|
|
if commit != "" {
|
|
return commit
|
|
}
|
|
|
|
if info, ok := debug.ReadBuildInfo(); ok {
|
|
for _, s := range info.Settings {
|
|
if s.Key == "vcs.revision" {
|
|
return s.Value
|
|
}
|
|
}
|
|
}
|
|
|
|
return ""
|
|
}
|
|
|
|
func Date() string {
|
|
return date
|
|
}
|
|
|
|
func UserAgent() string {
|
|
return fmt.Sprintf("godeez/%s (%s/%s)", Version(), runtime.GOOS, runtime.GOARCH)
|
|
}
|