package repostatus import ( "errors" "strconv" "strings" "go.wit.com/log" "go.wit.com/widget" ) // used to block commits on non-user branches func (rs *RepoStatus) IsUserBranch() bool { if rs.GetCurrentBranchName() == rs.GetUserBranchName() { return true } return false } func (rs *RepoStatus) DeleteUserBranch(force bool) bool { log.Log(REPOWARN, "figure out what to do here") return false } func (rs *RepoStatus) ResetBranches() bool { log.Log(REPOWARN, "figure out what to do here") return false } func (rs *RepoStatus) FetchMaster() (error, string) { // log.Log(REPOWARN, "FetchMaster() start", rs.Name()) master := rs.GetMasterBranchName() return rs.fetchBranch(master) } func (rs *RepoStatus) FetchDevel() (error, string) { devel := rs.GetDevelBranchName() return rs.fetchBranch(devel) } // fetch the branch 'apple' func (rs *RepoStatus) fetchBranch(apple string) (error, string) { if rs.GetCurrentBranchName() != rs.GetUserBranchName() { return errors.New("not in user branch"), "" } if rs.gitConfig == nil { return errors.New("missing .git/config"), "" } log.Log(REPOWARN, rs.Name(), "looking for branch:", apple) for name, branch := range rs.gitConfig.branches { if name == apple { // found the branch! log.Log(REPOWARN, " ", name, "remote:", branch.remote, "merge", branch.merge) cmd := []string{"git", "fetch", branch.remote, apple + ":" + apple} log.Log(REPOWARN, "running:", rs.Name(), cmd) err, out := rs.RunCmd(cmd) return err, out } } return errors.New("branch " + apple + " not found"), "" } func (rs *RepoStatus) MergeUserToDevel() bool { startbranch := rs.GetCurrentBranchName() devel := rs.GetDevelBranchName() user := rs.GetUserBranchName() log.Info("MergeUserToDevel() checking out", devel, "started on", startbranch, "merge", user) var all [][]string all = append(all, []string{"git", "checkout", devel}) all = append(all, []string{"git", "merge", user}) all = append(all, []string{"git", "push"}) if rs.DoAll(all) { log.Log(WARN, "MergeUserToDevel() failed", rs.Path()) rs.updateNew() return true } // DoAll failed rs.updateNew() return false } func (rs *RepoStatus) MergeDevelToMaster() bool { startbranch := rs.GetCurrentBranchName() devel := rs.GetDevelBranchName() main := rs.GetMasterBranchName() log.Info("MergeDevelToMaster() checking out", main, "started on", startbranch, "merge", devel) var all [][]string all = append(all, []string{"git", "checkout", main}) all = append(all, []string{"git", "merge", devel}) all = append(all, []string{"git", "push"}) if rs.DoAll(all) { log.Log(WARN, "MergeDevelToMaster() failed", rs.Path()) rs.updateNew() return true } // DoAll failed rs.updateNew() return false } /* func (rs *RepoStatus) runReleaseVersionB() bool { if !rs.generateCmd() { log.Warn("something is wrong. fix the errors first") return false } rs.releaseVersion.Disable() log.Warn("MAKING A RELEASE AND VERSION") if !rs.runGitCommands(true) { log.Warn("SOMETHING WENT WRONG") rs.UpdateNew() rs.Enable() return false } log.Warn("THINGS SEEM OK. runReleaseVersionB worked. Release is finished. restart autotypist()") rs.Hide() return true } */ func (rs *RepoStatus) runFullAutomation() bool { if !rs.MergeUserToDevel() { log.Warn("THINGS FAILED returned false") return false } log.Warn("THINGS SEEM OK returned true. can run this again?") /* log.Warn("develMerge =", rs.develMergeB.String()) label := "merge devel into " + rs.GetMasterBranchName() if label == rs.develMergeB.String() { log.Warn("LABELS MATCH", label, rs.develMergeB.String()) if !rs.RunDevelMergeB() { log.Warn("THINGS FAILED returned false") return false } } if rs.develMergeB.String() == "ready to release" { log.Warn("THINGS SEEM OK ready to release") if rs.releaseVersion.String() == "Release!" { log.Warn("releaseVersion == 'Release!'. safe to do release version HERE?") log.Warn("rs.newversion =", rs.newversion.String()) log.Warn("rs.targetReleaseVersion =", rs.targetReleaseVersion.String()) log.Warn("Are these equal?") if rs.newversion.String() == rs.targetReleaseVersion.String() { log.Warn("THEY ARE EQUAL!") rs.runReleaseVersionB() } else { log.Warn("THEY ARE NOT EQUAL") } } } */ return true } var releaseRevision string = "" // over ride the computation of this if a release is being created func (rs *RepoStatus) setRevision(c string) { if releaseRevision == "" { rs.revision.SetText(c) } rs.revision.SetText(releaseRevision) } func (rs *RepoStatus) SetVersion(a, b, c string, reason string) { rs.major.SetText(a) rs.minor.SetText(b) releaseRevision = c rs.setRevision(c) rs.targetReleaseVersion.SetText("v" + a + "." + b + "." + c) rs.versionMessage.SetLabel(reason) rs.versionMessage.SetText(reason) // rs.versionMessage.SetValue(reason) } func (rs *RepoStatus) setTag() bool { lasttag := rs.lasttag.String() var major, minor, revision string major, minor, revision = splitVersion(lasttag) olda, _ := strconv.Atoi(major) oldb, _ := strconv.Atoi(minor) oldc, _ := strconv.Atoi(revision) log.Log(INFO, "current version here", lasttag) log.Log(INFO, "current release a,b,c =", major, minor, revision) newa, _ := strconv.Atoi(rs.major.String()) newver := strconv.Itoa(newa) if newa < olda { log.Warn("new version bad", newver, "vs old version", lasttag, "newa =", newa, "olda =", olda) rs.newversion.SetLabel("bad") return false } if newa > olda { log.Log(INFO, "new version ok", newver, "vs old version", lasttag) rs.minor.SetText("0") rs.setRevision("0") newver := strconv.Itoa(newa) + ".0.0" rs.newversion.SetLabel(newver) return true } newb, _ := strconv.Atoi(rs.minor.String()) newver = strconv.Itoa(newa) + "." + strconv.Itoa(newb) if newb < oldb { log.Warn("new version bad", newver, "vs old version", lasttag, "newb =", newb, "oldb =", oldb) rs.newversion.SetLabel("bad") return false } if newb > oldb { log.Log(INFO, "new version ok", newver, "vs old version", lasttag) newver = strconv.Itoa(newa) + "." + strconv.Itoa(newb) + ".0" rs.newversion.SetLabel(newver) rs.setRevision("0") return true } newc, _ := strconv.Atoi(rs.revision.String()) newver = strconv.Itoa(newa) + "." + strconv.Itoa(newb) + "." + strconv.Itoa(newc) if newc <= oldc { log.Warn("new version bad", newver, "vs old version", lasttag) rs.newversion.SetLabel("bad") return false } log.Log(INFO, "new version ok", newver, "vs old version", lasttag) rs.newversion.SetLabel(newver) return true } // the newversion field goes through some sanity checking // to make sure it's greater than the existing tag and // valid according to golang -- it must be format 'v1.2.3' func (rs *RepoStatus) GetNewVersionTag() string { return rs.newversion.String() } func (rs *RepoStatus) incrementRevision() { lasttag := rs.lasttag.String() var major, minor, revision string if rs.targetReleaseVersion.String() == "" { major, minor, revision = splitVersion(lasttag) log.Warn("Should release version here", lasttag) log.Log(INFO, "Should release a,b,c", major, minor, revision) } else { // this means there is a specific release version trying to be done // use the target release version instead major, minor, revision = splitVersion(rs.targetReleaseVersion.String()) log.Warn("Should release version here", lasttag) log.Log(INFO, "Should release a,b,c", major, minor, revision) } a, _ := strconv.Atoi(major) b, _ := strconv.Atoi(minor) c, _ := strconv.Atoi(revision) rs.major.AddText(widget.GetString(a)) rs.major.AddText(widget.GetString(a + 1)) rs.major.SetText(widget.GetString(a)) rs.minor.AddText(widget.GetString(b)) rs.minor.AddText(widget.GetString(b + 1)) rs.minor.SetText(widget.GetString(b)) // rs.c := strconv.Atoi(revision) rs.revision.AddText(strconv.Itoa(c + 1)) rs.revision.AddText(strconv.Itoa(c + 2)) rs.revision.SetText(strconv.Itoa(c + 1)) // rs.setRevision(widget.GetString(c + 1)) } func (rs *RepoStatus) recommend() { log.Log(INFO, "Is repo dirty?", rs.dirtyLabel.String()) log.Log(INFO, "list the known tags") rs.DisableEverything() rs.populateTags() log.Log(INFO, "Does devel == user?", rs.develBranchVersion.String(), rs.userBranchVersion.String()) if rs.develBranchVersion.String() != rs.userBranchVersion.String() { log.Log(INFO, "devel does not equal user") log.Log(INFO, "merge or squash?") rs.EnableMergeDevel() rs.setMergeUserCommands() label := "merge user into " + rs.GetDevelBranchName() rs.develMergeB.SetLabel(label) return } log.Log(INFO, "Does master == devel? ", rs.GetMasterVersion(), rs.GetDevelVersion()) if rs.GetMasterVersion() != rs.GetDevelVersion() { log.Log(INFO, "master does not equal devel. merge devel into master") rs.EnableMergeDevel() rs.setMergeDevelCommands() label := "merge devel into " + rs.GetMasterBranchName() rs.develMergeB.SetLabel(label) return } if rs.lasttag.String() != rs.GetMasterVersion() { log.Log(INFO, "master does not equal last tag") rs.incrementRevision() rs.EnableSelectTag() rs.setTag() return } log.Log(INFO, "Is repo pushed upstream? git.wit.org or github?") } func (rs *RepoStatus) generateCmd() bool { // the length of 24 is arbitrary, but should be short // they should be things like perhaps, major release names // or something the users might see. // aka: "Topsy", "Picasso", "Buzz", etc if !rs.setTag() { log.Log(INFO, "tag sucked. fix your tag version") rs.versionMessage.SetLabel("tag message (bad version)") rs.releaseVersion.Disable() return false } log.Log(INFO, "tag is valid!!!!") rs.setGitCommands() if rs.versionMessage.String() == "" { log.Log(INFO, "tag message is empty!!!!") rs.releaseVersion.Disable() return false } if len(rs.versionMessage.String()) > 24 { rs.versionMessage.SetLabel("tag message (too long)") } else { rs.versionMessage.SetLabel("tag message") } rs.releaseVersion.SetLabel("Release Tag!") rs.releaseVersion.Enable() return true } func (rs *RepoStatus) runGitCommands(verbose bool) bool { for _, line := range rs.versionCmds { s := strings.Join(line, " ") if verbose { log.Log(WARN, "RUNNING:", s) } rs.develMergeB.SetText(s) err, b, output := runCmd(rs.realPath.String(), line) if err != nil { log.Warn("ABEND EXECUTION") log.Warn("error =", err) log.Warn("output =", output) return false } log.Log(INFO, "Returned with b =", b) log.Log(INFO, "output was =", output) log.Log(INFO, "RUN DONE") } return true } func (rs *RepoStatus) setGitCommands() { var line1, line2, line3 []string var all [][]string newTag := rs.newversion.String() line1 = append(line1, "git", "tag", "v"+newTag, "-m", rs.versionMessage.String()) all = append(all, line1) line2 = append(line2, "git", "push", "--tags") all = append(all, line2) line3 = append(line3, "git", "push", "--prune", "--tags") all = append(all, line3) rs.versionCmds = all var tmp []string // convert to displayable to the user text for _, line := range all { s := strings.Join(line, " ") log.Log(INFO, "s =", s) tmp = append(tmp, s) } rs.versionCmdOutput.SetValue(strings.Join(tmp, "\n")) } func (rs *RepoStatus) setMergeDevelCommands() { var line1, line2, line3 []string var all [][]string master := rs.GetMasterBranchName() devel := rs.GetDevelBranchName() line1 = append(line1, "git", "checkout", master) all = append(all, line1) line2 = append(line2, "git", "merge", devel) all = append(all, line2) line3 = append(line3, "git", "push") all = append(all, line3) rs.versionCmds = all var tmp []string // convert to displayable to the user text for _, line := range all { s := strings.Join(line, " ") log.Log(INFO, "s =", s) tmp = append(tmp, s) } rs.versionCmdOutput.SetValue(strings.Join(tmp, "\n")) } func (rs *RepoStatus) setMergeUserCommands() { var line1, line2, line3 []string var all [][]string devel := rs.GetDevelBranchName() user := rs.userWorkingName.String() line1 = append(line1, "git", "checkout", devel) all = append(all, line1) line2 = append(line2, "git", "merge", user) all = append(all, line2) line3 = append(line3, "git", "push") all = append(all, line3) rs.versionCmds = all var tmp []string // convert to displayable to the user text for _, line := range all { s := strings.Join(line, " ") log.Log(INFO, "s =", s) tmp = append(tmp, s) } rs.versionCmdOutput.SetValue(strings.Join(tmp, "\n")) }