package repostatus import ( "strconv" "strings" "go.wit.com/lib/gadgets" "go.wit.com/log" "go.wit.com/widget" ) // creates the actual widgets. // it's assumed you are always passing in a box func (rs *RepoStatus) draw(goSrcPath string, realPath string) { if !rs.Ready() { return } // display the status of the git repository rs.drawGitStatus(goSrcPath, realPath) // display the git branches and options rs.drawGitBranches() // show standard git commit and merge controls rs.drawGitCommands() } func (rs *RepoStatus) drawGitBranches() { rs.gitBranchesGroup = rs.window.Box().NewGroup("branches") newgrid := rs.gitBranchesGroup.NewGrid("gridnuts", 2, 2) rs.masterDrop = gadgets.NewBasicDropdown(newgrid, "main branch") rs.masterDrop.Custom = func() { log.Log(WARN, "Switching main branch to:", rs.masterDrop.String()) rs.masterBranchVersion.SetLabel(rs.masterDrop.String()) rs.mainWorkingName.SetValue(rs.masterDrop.String()) } rs.develDrop = gadgets.NewBasicDropdown(newgrid, "devel branch") rs.develDrop.Custom = func() { log.Log(WARN, "Switching devel branch to:", rs.develDrop.String()) rs.develBranchVersion.SetLabel(rs.develDrop.String()) rs.develWorkingName.SetValue(rs.develDrop.String()) } rs.userDrop = gadgets.NewBasicDropdown(newgrid, "user branch") rs.userDrop.Custom = func() { log.Log(WARN, "Switching user branch to:", rs.userDrop.String()) rs.userBranchVersion.SetLabel(rs.userDrop.String()) rs.userWorkingName.SetValue(rs.userDrop.String()) } rs.lasttag = gadgets.NewOneLiner(newgrid, "last tag") rs.masterBranchVersion = gadgets.NewOneLiner(newgrid, "master") rs.develBranchVersion = gadgets.NewOneLiner(newgrid, "devel") rs.userBranchVersion = gadgets.NewOneLiner(newgrid, "user") rs.currentBranch = gadgets.NewOneLiner(newgrid, "current branch") rs.currentVersion = gadgets.NewOneLiner(newgrid, "current version") /* var master = "" all := rs.getBranches() for _, branch := range all { log.Log(INFO, "getBranches()", branch) rs.masterDrop.AddText(branch) rs.develDrop.AddText(branch) rs.userDrop.AddText(branch) if branch == "master" { master = "master" } if branch == "main" { master = "main" } } */ // relabel the various gadgets with the right branch name // rs.masterBranchVersion.SetLabel(master) rs.showBranchesButton = newgrid.NewButton("getBranches()", func() { all := rs.getBranches() i := len(all) log.Log(WARN, "branch count =", i) }) rs.checkBranchesButton = newgrid.NewButton("CheckBranches()", func() { if rs.CheckBranches() { log.Log(WARN, "Branches are perfect") } else { log.Log(WARN, "Branches are not perfect") } }) newgrid.NewButton("show .git/config", func() { if rs.gitConfig == nil { log.Log(WARN, "Nonexistant or damaged .git/config", rs.String()) return } log.Log(WARN, ".git/config:", rs.realPath.String()) // The info: for name, remote := range rs.gitConfig.remotes { log.Log(WARN, " ", name, "url:", remote.url) } for name, branch := range rs.gitConfig.branches { log.Log(WARN, " ", name, "remote:", branch.remote, "merge", branch.merge) } }) newgrid.NewButton("check go.sum", func() { if rs.ReadGoMod() { log.Log(INFO, "parsed go.mod", rs.realPath.String()) } else { log.Log(WARN, "Something went wrong parsing go.mod", rs.realPath.String()) } log.Log(WARN, "go.sum:", rs.realPath.String()) for depname, version := range rs.goConfig { log.Log(WARN, " ", depname, version) } }) } func (rs *RepoStatus) drawGitStatus(goSrcPath string, realPath string) { rs.gitStatusGroup = rs.window.Box().NewGroup("What GO Knows It Has") newgrid := rs.gitStatusGroup.NewGrid("gridnuts", 2, 2) newgrid.Margin() newgrid.Pad() rs.path = gadgets.NewOneLiner(newgrid, "path") rs.goSrcPath = gadgets.NewOneLiner(newgrid, goSrcPath) rs.realPath = gadgets.NewOneLiner(newgrid, realPath) rs.realPath.Hide() rs.mainWorkingName = gadgets.NewOneLiner(newgrid, "main working branch") rs.mainWorkingName.SetValue("???") rs.develWorkingName = gadgets.NewOneLiner(newgrid, "devel working branch") rs.develWorkingName.SetValue("devel") rs.userWorkingName = gadgets.NewOneLiner(newgrid, "user working branch") rs.userWorkingName.SetValue("uid") rs.tagsDrop = gadgets.NewBasicDropdown(newgrid, "all releases") // git for-each-ref --sort=taggerdate --format '%(tag) ,,,_,,, %(subject)' refs/tags var cmd []string cmd = append(cmd, "git", "for-each-ref", "--sort=taggerdate", "--format", "%(tag) %(subject)", "refs/tags") _, _, output := RunCmd(rs.realPath.String(), cmd) log.Log(INFO, output) for _, line := range strings.Split(output, "\n") { rs.tagsDrop.AddText(line) } // rs.masterBranchVersion = gadgets.NewOneLiner(newgrid, "master") // rs.develBranchVersion = gadgets.NewOneLiner(newgrid, "devel") // rs.userBranchVersion = gadgets.NewOneLiner(newgrid, "user") rs.dirtyLabel = gadgets.NewOneLiner(newgrid, "dirty") rs.speed = gadgets.NewOneLiner(newgrid, "refresh speed =") rs.speedActual = gadgets.NewOneLiner(newgrid, "speed actual =") } func (rs *RepoStatus) drawGitCommands() { rs.gitCommandsGroup = rs.window.Box().NewGroup("git commands") newgrid := rs.gitCommandsGroup.NewGrid("gridnuts", 2, 2) newgrid.NewButton("update", func() { rs.Update() }) newgrid.NewButton("git pull", func() { var cmd []string cmd = append(cmd, "git", "pull") err, b, output := RunCmd(rs.realPath.String(), cmd) log.Warn("Did git pull here", err, b, output) }) rs.major = gadgets.NewBasicCombobox(newgrid, "major") rs.major.Custom = func() { rs.setTag() rs.generateCmd() } rs.minor = gadgets.NewBasicCombobox(newgrid, "minor") rs.minor.Custom = func() { rs.setTag() rs.generateCmd() } rs.revision = gadgets.NewBasicCombobox(newgrid, "revision") rs.revision.Custom = func() { rs.setTag() rs.generateCmd() } newgrid.NewLabel("new tag version") rs.newversion = newgrid.NewLabel("0.0.1") rs.versionMessage = gadgets.NewBasicEntry(newgrid, "tag message") rs.versionMessage.Custom = func() { rs.generateCmd() } rs.versionCmdOutput = gadgets.NewOneLiner(newgrid, "tag cmd") label := "merge " + rs.masterDrop.String() + " to devel" rs.develMerge = newgrid.NewButton(label, func() { rs.Disable() master := rs.masterDrop.String() rs.checkoutBranch("master", master) if rs.getCurrentBranchName() != master { log.Warn("something went wrong switching to the master branch. full stop!") return } if !rs.runGitCommands() { log.Warn("SOMETHING WENT WRONG") return } rs.Update() rs.Enable() log.Warn("THINGS SEEM OK") }) rs.releaseVersion = newgrid.NewButton("tag and release new version", func() { if !rs.generateCmd() { log.Warn("something is wrong. fix the errors first") return } rs.releaseVersion.Disable() log.Warn("COMMIT IT HERE") if !rs.runGitCommands() { log.Warn("SOMETHING WENT WRONG") } rs.Update() log.Warn("THINGS SEEM OK") }) newgrid.Margin() newgrid.Pad() } 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.newversion.SetLabel(newver) rs.minor.SetText("") rs.revision.SetText("") 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) rs.newversion.SetLabel(newver) rs.revision.SetText("") 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 } func (rs *RepoStatus) incrementVersion() { lasttag := rs.lasttag.String() var major, minor, revision string major, minor, revision = splitVersion(lasttag) 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(widget.GetString(c + 1)) rs.revision.AddText(widget.GetString(c + 2)) rs.revision.SetText(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.develMerge.SetLabel(label) return } log.Log(INFO, "Does master == devel? ", rs.masterBranchVersion.String(), rs.develBranchVersion.String()) if rs.masterBranchVersion.String() != rs.develBranchVersion.String() { log.Log(INFO, "master does not equal devel. merge devel into master") rs.EnableMergeDevel() rs.setMergeDevelCommands() label := "merge devel into " + rs.GetMasterBranchName() rs.develMerge.SetLabel(label) return } rs.getLastTagVersion() if rs.lasttag.String() != rs.masterBranchVersion.String() { log.Log(INFO, "master does not equal last tag") rs.incrementVersion() 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.Enable() return true } func (rs *RepoStatus) runGitCommands() bool { for _, line := range rs.versionCmds { s := strings.Join(line, " ") log.Log(INFO, "NEED TO RUN:", s) rs.develMerge.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.GetUserBranchName() 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")) }