124 lines
2.5 KiB
Go
124 lines
2.5 KiB
Go
// +build tools
|
|
|
|
package main
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"go/format"
|
|
"os"
|
|
"os/exec"
|
|
"regexp"
|
|
"strconv"
|
|
"strings"
|
|
"text/template"
|
|
"time"
|
|
)
|
|
|
|
var exactVer *regexp.Regexp
|
|
var gitVer *regexp.Regexp
|
|
var verFile = "generated-version.go"
|
|
|
|
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
|
|
gitVer = regexp.MustCompile(`^(v\d+\.\d+)\.(\d+)-(\d+)-g`)
|
|
}
|
|
|
|
// Goal: Either use an exact version like v1.0.0
|
|
// or translate the git version like v1.0.0-4-g0000000
|
|
// to a semver like v1.0.1-pre4+g0000000
|
|
// Don't fail when git repo isn't available.
|
|
func main() {
|
|
desc := gitDesc()
|
|
rev := gitRev()
|
|
ver := semVer(desc)
|
|
ts := time.Now().Format(time.RFC3339)
|
|
|
|
v := struct {
|
|
Timestamp string
|
|
Version string
|
|
GitRev string
|
|
}{
|
|
Timestamp: ts,
|
|
Version: ver,
|
|
GitRev: rev,
|
|
}
|
|
|
|
// Create or overwrite the go file from template
|
|
var buf bytes.Buffer
|
|
if err := versionTpl.Execute(&buf, v); nil != err {
|
|
panic(err)
|
|
}
|
|
|
|
// Format
|
|
src, err := format.Source(buf.Bytes())
|
|
if nil != err {
|
|
panic(err)
|
|
}
|
|
|
|
// Write to disk (in the Current Working Directory)
|
|
f, err := os.Create(verFile)
|
|
if nil != err {
|
|
panic(err)
|
|
}
|
|
if _, err := f.Write(src); nil != err {
|
|
panic(err)
|
|
}
|
|
if err := f.Close(); nil != err {
|
|
panic(err)
|
|
}
|
|
}
|
|
|
|
func gitDesc() string {
|
|
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 strings.TrimSpace(string(out))
|
|
}
|
|
|
|
func gitRev() string {
|
|
args := strings.Split("git rev-parse HEAD", " ")
|
|
cmd := exec.Command(args[0], args[1:]...)
|
|
out, err := cmd.CombinedOutput()
|
|
if nil != err {
|
|
// Don't panic, just carry on
|
|
out = []byte("00000000000000000")
|
|
}
|
|
return strings.TrimSpace(string(out))
|
|
}
|
|
|
|
func semVer(desc string) string {
|
|
var ver string
|
|
if exactVer.MatchString(desc) {
|
|
// v1.0.0
|
|
ver = desc
|
|
} else if gitVer.MatchString(desc) {
|
|
// ((v1.0).(0)-(1))
|
|
vers := gitVer.FindStringSubmatch(desc)
|
|
patch, err := strconv.Atoi(vers[2])
|
|
if nil != err {
|
|
panic(err)
|
|
}
|
|
// v1.0.1-pre1
|
|
ver = fmt.Sprintf("%s.%d-pre%s", vers[1], patch+1, vers[3])
|
|
}
|
|
return ver
|
|
}
|
|
|
|
var versionTpl = template.Must(template.New("").Parse(`// Code generated by go generate; DO NOT EDIT.
|
|
package main
|
|
|
|
func init() {
|
|
Timestamp = "{{ .Timestamp }}"
|
|
Version = "{{ .Version }}"
|
|
GitRev = "{{ .GitRev }}"
|
|
}
|
|
`))
|