consolidate version package

This commit is contained in:
Mike Bloy 2019-08-25 09:53:50 -05:00
parent 10a5bd4cc4
commit 9d4fe2a78d
5 changed files with 64 additions and 76 deletions

View File

@ -8,7 +8,8 @@ import (
func main() { func main() {
fmt.Println(sayHi("Mike")) fmt.Println(sayHi("Mike"))
fmt.Printf("This is %s\n", version.VersionStr) fmt.Printf("This is %s\n", version.Version)
fmt.Printf("version data: %#v\n", version.Version)
} }
func sayHi(name string) string { func sayHi(name string) string {

View File

@ -1,21 +0,0 @@
package version
import (
"fmt"
"runtime"
)
// 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)
// VersionData : The Info struct of the version specification
var VersionData = parseGitDescribe(gitDescribe)
// VersionStr : The string representation of the version
var VersionStr = VersionData.String()

View File

@ -1,22 +0,0 @@
package version
import (
"runtime"
"testing"
)
func TestGoVersion(t *testing.T) {
got := GoVersion
expected := runtime.Version()
if got != expected {
t.Errorf("Expected: %s ; Got: %s", got, expected)
}
}
func TestOsArch(t *testing.T) {
got := OsArch
expected := runtime.GOOS + " (" + runtime.GOARCH + ")"
if got != expected {
t.Errorf("Expected: %s ; Got: %s", got, expected)
}
}

View File

@ -3,25 +3,38 @@ package version
import ( import (
"fmt" "fmt"
"regexp" "regexp"
"runtime"
"strconv" "strconv"
"strings" "strings"
) )
// Info : data structure for program version information // Info : data structure for program version information
type Info struct { type info struct {
Major int Major int
Minor int Minor int
Patch int Patch int
Prerelease []string Prerelease []string
BuildInfo []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 // Equal compares two Info structs for equality
func (i Info) Equal(o Info) bool { func (i info) Equal(o info) bool {
if i.Major != o.Major || i.Minor != o.Minor || i.Patch != o.Patch { if i.Major != o.Major || i.Minor != o.Minor || i.Patch != o.Patch {
return false return false
} }
if len(i.Prerelease) != len(o.Prerelease) || len(i.BuildInfo) != len(o.BuildInfo) { if len(i.Prerelease) != len(o.Prerelease) || len(i.BuildMeta) != len(o.BuildMeta) {
return false return false
} }
for j := 0; j < len(i.Prerelease); j++ { for j := 0; j < len(i.Prerelease); j++ {
@ -29,8 +42,8 @@ func (i Info) Equal(o Info) bool {
return false return false
} }
} }
for j := 0; j < len(i.BuildInfo); j++ { for j := 0; j < len(i.BuildMeta); j++ {
if i.BuildInfo[j] != o.BuildInfo[j] { if i.BuildMeta[j] != o.BuildMeta[j] {
return false return false
} }
} }
@ -38,14 +51,14 @@ func (i Info) Equal(o Info) bool {
} }
// String returns a human friendly version string // String returns a human friendly version string
func (i Info) String() string { func (i info) String() string {
var b strings.Builder var b strings.Builder
fmt.Fprintf(&b, "v%d.%d.%d", i.Major, i.Minor, i.Patch) fmt.Fprintf(&b, "v%d.%d.%d", i.Major, i.Minor, i.Patch)
if len(i.Prerelease) > 0 { if len(i.Prerelease) > 0 {
fmt.Fprintf(&b, "-%s", strings.Join(i.Prerelease, ".")) fmt.Fprintf(&b, "-%s", strings.Join(i.Prerelease, "."))
} }
if len(i.BuildInfo) > 0 { if len(i.BuildMeta) > 0 {
fmt.Fprintf(&b, "+%s", strings.Join(i.BuildInfo, ".")) fmt.Fprintf(&b, "+%s", strings.Join(i.BuildMeta, "."))
} }
return b.String() return b.String()
} }
@ -66,13 +79,13 @@ const reStr = `^(?:v(([0-9]+)(?:\.([0-9]+)(?:\.([0-9]+))?)?))?(?:-((?:alpha|beta
var re = regexp.MustCompile(reStr) var re = regexp.MustCompile(reStr)
func parseGitDescribe(input string) Info { func parseGitDescribe(input string) info {
matches := re.FindStringSubmatch(input) matches := re.FindStringSubmatch(input)
if matches == nil || matches[0] == "" { if matches == nil || matches[0] == "" {
return Info{0, 0, 0, []string{"dev"}, []string{"unknown"}} return info{0, 0, 0, []string{"dev"}, []string{"unknown"}}
} }
info := Info{} info := info{}
if matches[2] != "" { if matches[2] != "" {
num, _ := strconv.Atoi(matches[2]) num, _ := strconv.Atoi(matches[2])
info.Major = num info.Major = num
@ -89,15 +102,15 @@ func parseGitDescribe(input string) Info {
info.Prerelease = strings.Split(matches[5], ".") info.Prerelease = strings.Split(matches[5], ".")
} }
if matches[6] != "" || matches[7] != "" || matches[8] != "" { if matches[6] != "" || matches[7] != "" || matches[8] != "" {
info.BuildInfo = append(info.BuildInfo, "git") info.BuildMeta = append(info.BuildMeta, "git")
if matches[6] != "" { if matches[6] != "" {
info.BuildInfo = append(info.BuildInfo, matches[6]) info.BuildMeta = append(info.BuildMeta, matches[6])
} }
if matches[7] != "" { if matches[7] != "" {
info.BuildInfo = append(info.BuildInfo, matches[7]) info.BuildMeta = append(info.BuildMeta, matches[7])
} }
if matches[8] != "" { if matches[8] != "" {
info.BuildInfo = append(info.BuildInfo, "dirty") info.BuildMeta = append(info.BuildMeta, "dirty")
} }
} }

View File

@ -2,18 +2,35 @@ package version
import ( import (
"fmt" "fmt"
"runtime"
"testing" "testing"
) )
func TestGoVersion(t *testing.T) {
got := GoVersion
expected := runtime.Version()
if got != expected {
t.Errorf("Expected: %s ; Got: %s", got, expected)
}
}
func TestOsArch(t *testing.T) {
got := OsArch
expected := runtime.GOOS + " (" + runtime.GOARCH + ")"
if got != expected {
t.Errorf("Expected: %s ; Got: %s", got, expected)
}
}
func TestParseGitDescribe(t *testing.T) { func TestParseGitDescribe(t *testing.T) {
expected := []Info{ expected := []info{
Info{0, 0, 0, []string{"dev"}, []string{"unknown"}}, info{0, 0, 0, []string{"dev"}, []string{"unknown"}},
Info{0, 0, 0, []string{}, []string{"git", "feedbeef"}}, info{0, 0, 0, []string{}, []string{"git", "feedbeef"}},
Info{1, 2, 0, []string{"dev", "1"}, []string{"git", "83", "feedbeef"}}, info{1, 2, 0, []string{"dev", "1"}, []string{"git", "83", "feedbeef"}},
Info{1, 2, 3, []string{"dev", "1"}, []string{"git", "83", "feedbeef", "dirty"}}, info{1, 2, 3, []string{"dev", "1"}, []string{"git", "83", "feedbeef", "dirty"}},
Info{1, 2, 3, []string{}, []string{"git", "dirty"}}, info{1, 2, 3, []string{}, []string{"git", "dirty"}},
Info{1, 2, 3, []string{"beta"}, []string{"git", "dirty"}}, info{1, 2, 3, []string{"beta"}, []string{"git", "dirty"}},
Info{1, 2, 3, []string{"rc"}, []string{}}, info{1, 2, 3, []string{"rc"}, []string{}},
} }
inputs := []string{ inputs := []string{
"", "",
@ -33,14 +50,14 @@ func TestParseGitDescribe(t *testing.T) {
} }
func TestInfoStringer(t *testing.T) { func TestInfoStringer(t *testing.T) {
inputs := []Info{ inputs := []info{
Info{0, 0, 0, []string{"dev"}, []string{"unknown"}}, info{0, 0, 0, []string{"dev"}, []string{"unknown"}},
Info{0, 0, 0, []string{}, []string{"git", "feedbeef"}}, info{0, 0, 0, []string{}, []string{"git", "feedbeef"}},
Info{1, 2, 0, []string{"dev", "1"}, []string{"git", "83", "feedbeef"}}, info{1, 2, 0, []string{"dev", "1"}, []string{"git", "83", "feedbeef"}},
Info{1, 2, 3, []string{"dev", "1"}, []string{"git", "83", "feedbeef", "dirty"}}, info{1, 2, 3, []string{"dev", "1"}, []string{"git", "83", "feedbeef", "dirty"}},
Info{1, 2, 3, []string{}, []string{"git", "dirty"}}, info{1, 2, 3, []string{}, []string{"git", "dirty"}},
Info{1, 2, 3, []string{"beta"}, []string{"git", "dirty"}}, info{1, 2, 3, []string{"beta"}, []string{"git", "dirty"}},
Info{1, 2, 3, []string{"rc"}, []string{}}, info{1, 2, 3, []string{"rc"}, []string{}},
} }
expected := []string{ expected := []string{
"v0.0.0-dev+unknown", "v0.0.0-dev+unknown",