github.com/hairyhenderson/gomplate/v4@v4.0.0-pre-2.0.20240520121557-362f058f0c93/version/gen/vgen.go (about) 1 // run as 'go run ./version/gen/vgen.go' 2 3 package main 4 5 import ( 6 "fmt" 7 "log" 8 "os/exec" 9 "strings" 10 11 "github.com/Masterminds/semver/v3" 12 ) 13 14 func main() { 15 descVer, err := describedVersion() 16 if err != nil { 17 log.Fatal(err) 18 } 19 20 latest, err := latestTag() 21 if err != nil { 22 log.Fatal(err) 23 } 24 25 ver := version(descVer, latest) 26 27 fmt.Println(ver.String()) 28 } 29 30 func describedVersion() (*semver.Version, error) { 31 desc, err := runCmd("git describe --always") 32 if err != nil { 33 return nil, fmt.Errorf("git describe failed: %w", err) 34 } 35 36 ver, err := semver.NewVersion(desc) 37 if err != nil { 38 return nil, err 39 } 40 41 return ver, nil 42 } 43 44 func version(descVer, latest *semver.Version) *semver.Version { 45 ver := *descVer 46 if ver.Prerelease() != "" { 47 ver = ver.IncPatch().IncPatch() 48 ver, _ = ver.SetPrerelease(descVer.Prerelease()) 49 ver, _ = ver.SetMetadata(descVer.Metadata()) 50 } else if ver.Metadata() != "" { 51 ver = ver.IncPatch() 52 ver, _ = ver.SetMetadata(descVer.Metadata()) 53 } 54 55 // if we're on a release tag already, we're done 56 if descVer.Equal(&ver) { 57 return descVer 58 } 59 60 // If 'latest' is greater than 'ver', we need to skip to the next patch. 61 // If 'latest' is already a prerelease (i.e. if v5.0.0-pre was tagged), 62 // we should use 63 // If 'latest' is a prerelease, it's the same logic, except that we don't 64 // want to increment the patch version. 65 if latest.GreaterThan(&ver) || latest.Prerelease() != "" { 66 v := *latest 67 if v.Prerelease() == "" { 68 v = v.IncPatch() 69 } 70 v, _ = v.SetPrerelease(ver.Prerelease()) 71 v, _ = v.SetMetadata(ver.Metadata()) 72 73 ver = v 74 } 75 76 return &ver 77 } 78 79 func latestTag() (*semver.Version, error) { 80 // get the latest tag 81 tags, err := runCmd("git tag --list v*") 82 if err != nil { 83 return nil, fmt.Errorf("git tag failed: %w", err) 84 } 85 86 // find the latest tag 87 var latest *semver.Version 88 for _, tag := range strings.Split(tags, "\n") { 89 ver, err := semver.NewVersion(tag) 90 if err != nil { 91 return nil, fmt.Errorf("parsing tag %q failed: %w", tag, err) 92 } 93 94 if latest == nil || ver.GreaterThan(latest) { 95 latest = ver 96 } 97 } 98 99 if latest == nil { 100 return nil, fmt.Errorf("no tags found") 101 } 102 103 return latest, nil 104 } 105 106 func runCmd(c string) (string, error) { 107 parts := strings.Split(c, " ") 108 //nolint:gosec 109 cmd := exec.Command(parts[0], parts[1:]...) 110 out, err := cmd.CombinedOutput() 111 return strings.TrimSpace(string(out)), err 112 }