safing-portbase/info/version.go
2024-04-11 14:59:01 +02:00

150 lines
3.2 KiB
Go

package info
import (
"errors"
"fmt"
"os"
"runtime"
"runtime/debug"
"strings"
"sync"
)
var (
name string
license string
version = "dev build"
buildSource = "unknown"
buildTime = "unknown"
info *Info
loadInfo sync.Once
)
func init() {
// Convert version string space placeholders.
version = strings.ReplaceAll(version, "_", " ")
buildSource = strings.ReplaceAll(buildSource, "_", " ")
buildTime = strings.ReplaceAll(buildTime, "_", " ")
}
// Info holds the programs meta information.
type Info struct { //nolint:maligned
Name string
Version string
License string
Source string
BuildTime string
CGO bool
Commit string
CommitTime string
Dirty bool
debug.BuildInfo
}
// Set sets meta information via the main routine. This should be the first thing your program calls.
func Set(setName string, setVersion string, setLicenseName string) {
name = setName
license = setLicenseName
if setVersion != "" {
version = setVersion
}
}
// GetInfo returns all the meta information about the program.
func GetInfo() *Info {
loadInfo.Do(func() {
buildInfo, _ := debug.ReadBuildInfo()
buildSettings := make(map[string]string)
for _, setting := range buildInfo.Settings {
buildSettings[setting.Key] = setting.Value
}
fmt.Println(buildSettings)
info = &Info{
Name: name,
Version: version,
License: license,
Source: buildSource,
BuildTime: buildTime,
CGO: buildSettings["CGO_ENABLED"] == "1",
Commit: buildSettings["vcs.revision"],
CommitTime: buildSettings["vcs.time"],
Dirty: buildSettings["vcs.modified"] == "true",
BuildInfo: *buildInfo,
}
if info.Commit == "" {
info.Commit = "unknown"
}
if info.CommitTime == "" {
info.CommitTime = "unknown"
}
})
return info
}
// Version returns the short version string.
func Version() string {
info := GetInfo()
if info.Dirty {
return version + "*"
}
return version
}
// FullVersion returns the full and detailed version string.
func FullVersion() string {
info := GetInfo()
builder := new(strings.Builder)
// Name and version.
builder.WriteString(fmt.Sprintf("%s %s\n", info.Name, Version()))
// Build info.
cgoInfo := "-cgo"
if info.CGO {
cgoInfo = "+cgo"
}
builder.WriteString(fmt.Sprintf("\nbuilt with %s (%s %s) for %s/%s\n", runtime.Version(), runtime.Compiler, cgoInfo, runtime.GOOS, runtime.GOARCH))
builder.WriteString(fmt.Sprintf(" at %s\n", info.BuildTime))
// Commit info.
dirtyInfo := "clean"
if info.Dirty {
dirtyInfo = "dirty"
}
builder.WriteString(fmt.Sprintf("\ncommit %s (%s)\n", info.Commit, dirtyInfo))
builder.WriteString(fmt.Sprintf(" at %s\n", info.CommitTime))
builder.WriteString(fmt.Sprintf(" from %s\n", info.Source))
builder.WriteString(fmt.Sprintf("\nLicensed under the %s license.", license))
return builder.String()
}
// CheckVersion checks if the metadata is ok.
func CheckVersion() error {
switch {
case strings.HasSuffix(os.Args[0], ".test"):
return nil // testing on linux/darwin
case strings.HasSuffix(os.Args[0], ".test.exe"):
return nil // testing on windows
default:
// check version information
if name == "" || license == "" {
return errors.New("must call SetInfo() before calling CheckVersion()")
}
}
return nil
}