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) }