From 0921ed1e6007493c886c87ee9a15f2cceecb1f9f Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Mon, 1 Jul 2019 02:32:19 -0600 Subject: [PATCH] separate ExecAndParse, bugfix source format --- gitver.go | 143 ++++------------------------------------------- gitver/gitver.go | 143 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 155 insertions(+), 131 deletions(-) create mode 100644 gitver/gitver.go diff --git a/gitver.go b/gitver.go index 574fffa..d3cf421 100644 --- a/gitver.go +++ b/gitver.go @@ -8,34 +8,16 @@ import ( "go/format" "log" "os" - "os/exec" - "regexp" - "strconv" - "strings" "text/template" "time" + + "git.rootprojects.org/root/go-gitver/gitver" ) +var GitRev, GitVersion, GitTimestamp string var exitCode int -var exactVer *regexp.Regexp -var gitVer *regexp.Regexp var verFile = "xversion.go" -var ( - GitRev = "0000000" - GitVersion = "v0.0.0-pre0+g0000000" - GitTimestamp = "0000-00-00T00:00:00+0000" -) - -func init() { - // exactly vX.Y.Z (go-compatible semver) - exactVer = regexp.MustCompile(`^v\d+\.\d+\.\d+$`) - - // vX.Y.Z-n-g0000000 git post-release, semver prerelease - // vX.Y.Z-dirty git post-release, semver prerelease - gitVer = regexp.MustCompile(`^(v\d+\.\d+)\.(\d+)(-(\d+))?(-(g[0-9a-f]+))?(-(dirty))?`) -} - func main() { pkg := "main" @@ -61,33 +43,25 @@ func main() { exitCode = 1 } - desc, err := gitDesc() + v, err := gitver.ExecAndParse() if nil != err { log.Fatalf("Failed to get git version: %s\n", err) os.Exit(exitCode) } - rev := gitRev() - ver := semVer(desc) - ts, err := gitTimestamp(desc) - if nil != err { - ts = time.Now() - } - v := struct { + // Create or overwrite the go file from template + var buf bytes.Buffer + if err := versionTpl.Execute(&buf, struct { Package string Timestamp string Version string GitRev string }{ Package: pkg, - Timestamp: ts.Format(time.RFC3339), - Version: ver, - GitRev: rev, - } - - // Create or overwrite the go file from template - var buf bytes.Buffer - if err := versionTpl.Execute(&buf, v); nil != err { + Timestamp: v.Timestamp.Format(time.RFC3339), + Version: v.Version, + GitRev: v.Rev, + }); nil != err { panic(err) } @@ -108,100 +82,7 @@ func main() { if err := f.Close(); nil != err { panic(err) } -} -func gitDesc() (string, error) { - args := strings.Split("git describe --tags --dirty --always", " ") - cmd := exec.Command(args[0], args[1:]...) - out, err := cmd.CombinedOutput() - if nil != err { - // Don't panic, just carry on - //out = []byte("v0.0.0-0-g0000000") - return "", err - } - return strings.TrimSpace(string(out)), nil -} - -func gitRev() string { - args := strings.Split("git rev-parse HEAD", " ") - cmd := exec.Command(args[0], args[1:]...) - out, err := cmd.CombinedOutput() - if nil != err { - fmt.Fprintf(os.Stderr, - "\nUnexpected Error\n\n"+ - "Please open an issue at https://git.rootprojects.org/root/go-gitver/issues/new \n"+ - "Please include the following:\n\n"+ - "Command: %s\n"+ - "Output: %s\n"+ - "Error: %s\n"+ - "\nPlease and Thank You.\n\n", strings.Join(args, " "), out, err) - os.Exit(exitCode) - } - return strings.TrimSpace(string(out)) -} - -func semVer(desc string) string { - if exactVer.MatchString(desc) { - // v1.0.0 - return desc - } - - if !gitVer.MatchString(desc) { - return "" - } - - // (v1.0).(0)(-(1))(-(g0000000))(-(dirty)) - vers := gitVer.FindStringSubmatch(desc) - patch, err := strconv.Atoi(vers[2]) - if nil != err { - fmt.Fprintf(os.Stderr, - "\nUnexpected Error\n\n"+ - "Please open an issue at https://git.rootprojects.org/root/go-gitver/issues/new \n"+ - "Please include the following:\n\n"+ - "git description: %s\n"+ - "RegExp: %#v\n"+ - "Error: %s\n"+ - "\nPlease and Thank You.\n\n", desc, gitVer, err) - os.Exit(exitCode) - } - - // v1.0.1-pre1 - // v1.0.1-pre1+g0000000 - // v1.0.1-pre0+dirty - // v1.0.1-pre0+g0000000-dirty - if "" == vers[4] { - vers[4] = "0" - } - ver := fmt.Sprintf("%s.%d-pre%s", vers[1], patch+1, vers[4]) - if "" != vers[6] || "dirty" == vers[8] { - ver += "+" - if "" != vers[6] { - ver += vers[6] - if "" != vers[8] { - ver += "-" - } - } - ver += vers[8] - } - - return ver -} - -func gitTimestamp(desc string) (time.Time, error) { - args := []string{ - "git", - "show", desc, - "--format=%cd", - "--date=format:%Y-%m-%dT%H:%M:%SZ%z", - "--no-patch", - } - cmd := exec.Command(args[0], args[1:]...) - out, err := cmd.CombinedOutput() - if nil != err { - // a dirty desc was probably used - return time.Time{}, err - } - return time.Parse(time.RFC3339, strings.TrimSpace(string(out))) } var versionTpl = template.Must(template.New("").Parse(`// Code generated by go generate; DO NOT EDIT. @@ -209,7 +90,7 @@ package {{ .Package }} func init() { GitRev = "{{ .GitRev }}" - {{- if .Version }} + {{ if .Version -}} GitVersion = "{{ .Version }}" {{ end -}} GitTimestamp = "{{ .Timestamp }}" diff --git a/gitver/gitver.go b/gitver/gitver.go new file mode 100644 index 0000000..fc04418 --- /dev/null +++ b/gitver/gitver.go @@ -0,0 +1,143 @@ +package gitver + +import ( + "fmt" + "os/exec" + "regexp" + "strconv" + "strings" + "time" +) + +var exactVer *regexp.Regexp +var gitVer *regexp.Regexp + +func init() { + // exactly vX.Y.Z (go-compatible semver) + exactVer = regexp.MustCompile(`^v\d+\.\d+\.\d+$`) + + // vX.Y.Z-n-g0000000 git post-release, semver prerelease + // vX.Y.Z-dirty git post-release, semver prerelease + gitVer = regexp.MustCompile(`^(v\d+\.\d+)\.(\d+)(-(\d+))?(-(g[0-9a-f]+))?(-(dirty))?`) +} + +type Versions struct { + Timestamp time.Time + Version string + Rev string +} + +func ExecAndParse() (*Versions, error) { + desc, err := gitDesc() + if nil != err { + return nil, err + } + rev, err := gitRev() + if nil != err { + return nil, err + } + ver, err := semVer(desc) + if nil != err { + return nil, err + } + ts, err := gitTimestamp(desc) + if nil != err { + ts = time.Now() + } + + return &Versions{ + Timestamp: ts, + Version: ver, + Rev: rev, + }, nil +} + +func gitDesc() (string, error) { + args := strings.Split("git describe --tags --dirty --always", " ") + cmd := exec.Command(args[0], args[1:]...) + out, err := cmd.CombinedOutput() + if nil != err { + // Don't panic, just carry on + //out = []byte("v0.0.0-0-g0000000") + return "", err + } + return strings.TrimSpace(string(out)), nil +} + +func gitRev() (string, error) { + args := strings.Split("git rev-parse HEAD", " ") + cmd := exec.Command(args[0], args[1:]...) + out, err := cmd.CombinedOutput() + if nil != err { + return "", fmt.Errorf("\nUnexpected Error\n\n"+ + "Please open an issue at https://git.rootprojects.org/root/go-gitver/issues/new \n"+ + "Please include the following:\n\n"+ + "Command: %s\n"+ + "Output: %s\n"+ + "Error: %s\n"+ + "\nPlease and Thank You.\n\n", strings.Join(args, " "), out, err) + } + return strings.TrimSpace(string(out)), nil +} + +func semVer(desc string) (string, error) { + if exactVer.MatchString(desc) { + // v1.0.0 + return desc, nil + } + + if !gitVer.MatchString(desc) { + return "", nil + } + + // (v1.0).(0)(-(1))(-(g0000000))(-(dirty)) + vers := gitVer.FindStringSubmatch(desc) + patch, err := strconv.Atoi(vers[2]) + if nil != err { + return "", fmt.Errorf("\nUnexpected Error\n\n"+ + "Please open an issue at https://git.rootprojects.org/root/go-gitver/issues/new \n"+ + "Please include the following:\n\n"+ + "git description: %s\n"+ + "RegExp: %#v\n"+ + "Error: %s\n"+ + "\nPlease and Thank You.\n\n", desc, gitVer, err) + } + + // v1.0.1-pre1 + // v1.0.1-pre1+g0000000 + // v1.0.1-pre0+dirty + // v1.0.1-pre0+g0000000-dirty + if "" == vers[4] { + vers[4] = "0" + } + ver := fmt.Sprintf("%s.%d-pre%s", vers[1], patch+1, vers[4]) + if "" != vers[6] || "dirty" == vers[8] { + ver += "+" + if "" != vers[6] { + ver += vers[6] + if "" != vers[8] { + ver += "-" + } + } + ver += vers[8] + } + + return ver, nil +} + +func gitTimestamp(desc string) (time.Time, error) { + args := []string{ + "git", + "show", desc, + "--format=%cd", + "--date=format:%Y-%m-%dT%H:%M:%SZ%z", + "--no-patch", + } + cmd := exec.Command(args[0], args[1:]...) + out, err := cmd.CombinedOutput() + if nil != err { + // a dirty desc was probably used + return time.Time{}, err + } + return time.Parse(time.RFC3339, strings.TrimSpace(string(out))) +}