119 lines
2.8 KiB
Go
119 lines
2.8 KiB
Go
package version
|
|
|
|
import (
|
|
"fmt"
|
|
"regexp"
|
|
"runtime"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
// Info : data structure for program version information
|
|
type info struct {
|
|
Major int
|
|
Minor int
|
|
Patch int
|
|
Prerelease []string
|
|
BuildMeta []string
|
|
}
|
|
|
|
// gitDescribe : Git's "git describe --always --dirty" output
|
|
var gitDescribe = ""
|
|
|
|
// GoVersion : The go version used to compile this binary
|
|
var GoVersion = runtime.Version()
|
|
|
|
// OsArch : The OS and archetcture used for this binary
|
|
var OsArch = fmt.Sprintf("%s (%s)", runtime.GOOS, runtime.GOARCH)
|
|
|
|
// Version : the complete version data
|
|
var Version = parseGitDescribe(gitDescribe)
|
|
|
|
// Equal compares two Info structs for equality
|
|
func (i info) Equal(o info) bool {
|
|
if i.Major != o.Major || i.Minor != o.Minor || i.Patch != o.Patch {
|
|
return false
|
|
}
|
|
if len(i.Prerelease) != len(o.Prerelease) || len(i.BuildMeta) != len(o.BuildMeta) {
|
|
return false
|
|
}
|
|
for j := 0; j < len(i.Prerelease); j++ {
|
|
if i.Prerelease[j] != o.Prerelease[j] {
|
|
return false
|
|
}
|
|
}
|
|
for j := 0; j < len(i.BuildMeta); j++ {
|
|
if i.BuildMeta[j] != o.BuildMeta[j] {
|
|
return false
|
|
}
|
|
}
|
|
return true
|
|
}
|
|
|
|
// String returns a human friendly version string
|
|
func (i info) String() string {
|
|
var b strings.Builder
|
|
fmt.Fprintf(&b, "v%d.%d.%d", i.Major, i.Minor, i.Patch)
|
|
if len(i.Prerelease) > 0 {
|
|
fmt.Fprintf(&b, "-%s", strings.Join(i.Prerelease, "."))
|
|
}
|
|
if len(i.BuildMeta) > 0 {
|
|
fmt.Fprintf(&b, "+%s", strings.Join(i.BuildMeta, "."))
|
|
}
|
|
return b.String()
|
|
}
|
|
|
|
/* reStr is a regular expression string to parse the output of git describe
|
|
Match groups:
|
|
|
|
1. version number (without "v")
|
|
2. major version
|
|
3. minor version
|
|
4. patch version
|
|
5. prerelease identifier
|
|
6. commit count
|
|
7. git short hash
|
|
8. "-dirty" if dirty, else ""
|
|
*/
|
|
const reStr = `^(?:v(([0-9]+)(?:\.([0-9]+)(?:\.([0-9]+))?)?))?(?:-((?:alpha|beta|rc|dev)(?:\.[a-zA-Z0-9]+)*))?(?:-([0-9]+)-g)?([a-f0-9A-F]+)?(?:(-dirty))?$`
|
|
|
|
var re = regexp.MustCompile(reStr)
|
|
|
|
func parseGitDescribe(input string) info {
|
|
matches := re.FindStringSubmatch(input)
|
|
if matches == nil || matches[0] == "" {
|
|
return info{0, 0, 0, []string{"dev"}, []string{"unknown"}}
|
|
}
|
|
|
|
info := info{}
|
|
if matches[2] != "" {
|
|
num, _ := strconv.Atoi(matches[2])
|
|
info.Major = num
|
|
}
|
|
if matches[3] != "" {
|
|
num, _ := strconv.Atoi(matches[3])
|
|
info.Minor = num
|
|
}
|
|
if matches[4] != "" {
|
|
num, _ := strconv.Atoi(matches[4])
|
|
info.Patch = num
|
|
}
|
|
if matches[5] != "" {
|
|
info.Prerelease = strings.Split(matches[5], ".")
|
|
}
|
|
if matches[6] != "" || matches[7] != "" || matches[8] != "" {
|
|
info.BuildMeta = append(info.BuildMeta, "git")
|
|
if matches[6] != "" {
|
|
info.BuildMeta = append(info.BuildMeta, matches[6])
|
|
}
|
|
if matches[7] != "" {
|
|
info.BuildMeta = append(info.BuildMeta, matches[7])
|
|
}
|
|
if matches[8] != "" {
|
|
info.BuildMeta = append(info.BuildMeta, "dirty")
|
|
}
|
|
}
|
|
|
|
return info
|
|
}
|