gitpb/currentVersions.go

301 lines
7.6 KiB
Go

package gitpb
// runs git, parses output
// types faster than you can
import (
"errors"
"path/filepath"
"regexp"
"strconv"
"strings"
"unicode"
"go.wit.com/log"
)
func (repo *Repo) reloadVersions() {
repo.setMasterVersion()
repo.setDevelVersion()
repo.setUserVersion()
repo.setLastTag()
repo.setCurrentBranchName()
repo.setCurrentBranchVersion()
}
func (repo *Repo) setMasterVersion() {
bname := repo.GetMasterBranchName()
v, err := repo.gitVersionByName(bname)
/*
count := repo.LenGitTags()
log.Info(repo.GetGoPath(), "tag count", count)
repo.UpdateGitTags()
count = repo.LenGitTags()
log.Info(repo.GetGoPath(), "tag count", count)
*/
if err == nil {
repo.MasterVersion = v
} else {
log.Log(GITPBWARN, "gitpb.GitMasterVersion() error:", err)
repo.MasterVersion = "giterr"
}
}
func (repo *Repo) setDevelVersion() {
bname := repo.GetDevelBranchName()
v, err := repo.gitVersionByName(bname)
if err == nil {
repo.DevelVersion = v
} else {
log.Log(GITPBWARN, "gitpb.GitDevelVersion() error:", err)
repo.DevelVersion = "deverr"
}
}
func (repo *Repo) setUserVersion() {
bname := repo.GetUserBranchName()
v, err := repo.gitVersionByName(bname)
if err == nil {
repo.UserVersion = v
} else {
log.Log(GITPBWARN, "gitpb.GitUserVersion() error:", err)
repo.UserVersion = "uerr"
}
}
/*
now tracked in repo.Reload()
func (repo *Repo) GetCurrentBranchName() string {
r := repo.RunQuiet([]string{"git", "branch", "--show-current"})
output := strings.Join(r.Stdout, "\n")
if r.Error != nil {
log.Log(GITPBWARN, "GetCurrentBranchName() not in a git repo?", r.Error, repo.GetGoPath())
log.Log(GITPBWARN, "GetCurrentBranchName() output might have worked anyway:", output)
}
return strings.TrimSpace(output)
}
*/
// this is used often. probably move everything to this
// returns things like
// v0.2.2
// v0.22.39-1-g2141737
// v0.23-dirty
// mystuff
func (repo *Repo) GetCurrentVersion() string {
if repo == nil {
return ""
}
bver := repo.GetCurrentBranchVersion()
if repo.CheckDirty() {
bver = bver + "-dirty"
}
return bver
}
func (repo *Repo) gitDescribeByHash(hash string) (string, error) {
if hash == "" {
return "", errors.New("hash was blank")
}
r := repo.RunQuiet([]string{"git", "describe", "--tags", "--always", hash})
out := strings.Join(r.Stdout, "\n")
if r.Error != nil {
log.Warn("not in a git repo or bad hash?", r.Error, repo.GetGoPath())
return out, r.Error
}
return out, r.Error
}
// this should get the most recent tag
func (repo *Repo) GetLastTagVersion() string {
return repo.LastTag
}
func (repo *Repo) DebianReleaseVersion() string {
lasttag := repo.GetLastTagVersion()
newv := trimNonNumericFromStart(lasttag)
if newv == "" {
newv = "0.0"
if lasttag != "" {
newv += "-" + lasttag
}
}
return newv
}
func (repo *Repo) DebianCurrentVersion() string {
cbversion := repo.GetCurrentBranchVersion()
newv := trimNonNumericFromStart(cbversion)
if newv == "" {
newv = "0.0"
}
if repo.CheckDirty() {
newv += "-dirty"
}
return newv
}
func (repo *Repo) gitVersionByName(name string) (string, error) {
name = strings.TrimSpace(name)
if name == "" {
// git will return the current tag
r := repo.RunQuiet([]string{"git", "describe", "--tags", "--always"})
output := strings.Join(r.Stdout, "\n")
if r.Error != nil {
log.Log(GITPBWARN, "gitDescribeByName() output might have worked anyway:", output)
log.Log(GITPBWARN, "gitDescribeByName() not in a git repo?", r.Error, repo.GetGoPath())
return "", r.Error
}
return strings.TrimSpace(output), nil
}
if !repo.IsBranch(name) {
// tag does not exist
log.Log(GITPBWARN, "LocalTagExists()", name, "did not exist")
return "", errors.New("gitDescribeByName() git fatal: Not a valid object name: " + name)
}
cmd := []string{"git", "describe", "--tags", "--always", name}
result := repo.RunQuiet(cmd)
output := strings.Join(result.Stdout, "\n")
if result.Error != nil {
log.Log(GITPBWARN, "cmd =", cmd)
log.Log(GITPBWARN, "err =", result.Error)
log.Log(GITPBWARN, "output (might have worked with error?) =", output)
log.Log(GITPBWARN, "not in a git repo or bad tag?", repo.GetGoPath())
return "", result.Error
}
return strings.TrimSpace(output), nil
}
// find a branch name
// will find "master" or "devel"
// will also find "v0.1.1"
// or will find "patches-from-foo"
// will return *any* match on any git branch because it doesn't
// matter much here yet
// eventually this will be worked out by forge in some future code that hasn't been made yet
func (repo *Repo) IsBranch(findname string) bool {
loop := repo.Tags.All()
for loop.Scan() {
t := loop.Next()
// log.Info("LocalTagExists() tag:", t.Refname)
tagname := t.Refname
if strings.HasPrefix(tagname, "refs/remotes") {
continue
}
path, filename := filepath.Split(tagname)
log.Log(GITPB, "gitpb.IsBranch() tag:", path, filename, "from", repo.GetGoPath())
if filename == findname {
log.Log(GITPB, "gitpb.IsBranch() found tag:", path, filename, "from", repo.GetGoPath())
return true
}
}
log.Log(GITPB, "did not find tag:", findname, "in", repo.GetGoPath())
return false
}
// todo: redo this and above. both are messed up. ignore for now until things are stable
func (repo *Repo) IsLocalBranch(findname string) bool {
loop := repo.Tags.All()
for loop.Scan() {
t := loop.Next()
// log.Info("LocalTagExists() tag:", t.Refname)
tagname := t.Refname
if strings.HasPrefix(tagname, "refs/heads") {
continue
}
path, filename := filepath.Split(tagname)
log.Log(GITPB, "gitpb.IsBranch() tag:", path, filename, "from", repo.GetGoPath())
if filename == findname {
log.Log(GITPB, "gitpb.IsBranch() found tag:", path, filename, "from", repo.GetGoPath())
return true
}
}
log.Log(GITPB, "did not find tag:", findname, "in", repo.GetGoPath())
return false
}
func trimNonNumericFromStart(s string) string {
for i, r := range s {
if unicode.IsDigit(r) {
return s[i:]
}
}
return ""
}
func normalizeVersion(s string) string {
// reg, err := regexp.Compile("[^a-zA-Z0-9]+")
parts := strings.Split(s, "-")
if len(parts) == 0 {
return ""
}
reg, err := regexp.Compile("[^0-9.]+")
if err != nil {
log.Log(GITPBWARN, "normalizeVersion() regexp.Compile() ERROR =", err)
return parts[0]
}
clean := reg.ReplaceAllString(parts[0], "")
log.Log(GITPB, "normalizeVersion() s =", clean)
return clean
}
// golang doesn't seem to really support v0.1 and seems to want v0.1.0
// todo: confirm this
func splitVersion(version string) (a, b, c string) {
tmp := normalizeVersion(version)
parts := strings.Split(tmp, ".")
switch len(parts) {
case 1:
return parts[0], "", ""
case 2:
return parts[0], parts[1], ""
default:
return parts[0], parts[1], parts[2]
}
}
// changes the target minor. v0.1.3 becomes v0.2.0
func (repo *Repo) IncrementTargetMinor() {
lasttag := repo.GetLastTag()
var major, minor, revision string
major, minor, revision = splitVersion(lasttag)
olda, _ := strconv.Atoi(major)
oldb, _ := strconv.Atoi(minor)
oldc, _ := strconv.Atoi(revision)
oldb += 1
oldc = 0
newa := strconv.Itoa(olda)
newb := strconv.Itoa(oldb)
newc := strconv.Itoa(oldc)
repo.SetTargetVersion("v" + newa + "." + newb + "." + newc)
}
// changes the target revision. v0.1.3 becomes v0.1.4
func (repo *Repo) IncrementTargetRevision() {
lasttag := repo.GetLastTag()
var major, minor, revision string
major, minor, revision = splitVersion(lasttag)
olda, _ := strconv.Atoi(major)
oldb, _ := strconv.Atoi(minor)
oldc, _ := strconv.Atoi(revision)
oldc += 1
newa := strconv.Itoa(olda)
newb := strconv.Itoa(oldb)
newc := strconv.Itoa(oldc)
repo.SetTargetVersion("v" + newa + "." + newb + "." + newc)
}