Compare commits

...

65 Commits

Author SHA1 Message Date
Jeff Carr cfc91c8ba6 rm GOSRC 2025-09-11 23:10:38 -05:00
Jeff Carr 1c8f502c1b rm old code 2025-09-11 06:31:38 -05:00
Jeff Carr a72e9ce5f4 NEVER LEAVE JUNK IN GO REPOS EVER 2025-02-22 19:11:51 -06:00
Jeff Carr 3ab156a9c4 gitpb code is changing 2025-02-21 09:33:58 -06:00
Jeff Carr fa5c6572ff should help race conditions 2025-01-30 18:00:03 -06:00
Jeff Carr d568d5dbe4 make the buttons work 2025-01-30 13:44:22 -06:00
Jeff Carr 4484b0b84d new window for merge on a single repo 2025-01-30 13:35:22 -06:00
Jeff Carr c079039ffe func name change 2025-01-30 11:50:23 -06:00
Jeff Carr ff91deee63 func name change 2025-01-30 11:27:37 -06:00
Jeff Carr 2395a4466e delete old code. start refactor to protobuf 2025-01-29 16:18:32 -06:00
Jeff Carr 2b2de94eff old code 2025-01-29 12:26:00 -06:00
Jeff Carr 750ceaf8a1 old status vestages of the past are gone 2025-01-19 07:06:03 -06:00
Jeff Carr ac2958e559 code now moved to gitpb 2025-01-18 15:48:52 -06:00
Jeff Carr a15d447fbd more removal of old code 2025-01-07 22:28:50 -06:00
Jeff Carr fcb74ce2e8 attempt to set pb.State 2025-01-07 20:39:30 -06:00
Jeff Carr 648d3ac6b6 blah 2025-01-07 19:43:01 -06:00
Jeff Carr f53f1256f1 more rm old code 2025-01-07 19:29:46 -06:00
Jeff Carr 4efbead37c last of the easy rm old code 2025-01-07 19:09:25 -06:00
Jeff Carr 4dcd9a1164 mv code. eventually move to shell 2025-01-07 18:53:58 -06:00
Jeff Carr d9a54a6c31 still rm old code 2025-01-07 18:45:34 -06:00
Jeff Carr 9221f83aaf rm old code 2025-01-07 18:29:31 -06:00
Jeff Carr e323d5920c rm old code 2025-01-07 18:24:17 -06:00
Jeff Carr 07e0fdc437 rm old code 2025-01-07 18:18:38 -06:00
Jeff Carr 669c4e082c try to debug gui stuff 2025-01-07 05:59:12 -06:00
Jeff Carr 904a5e8568 remove lots of old stuff! 2025-01-07 04:58:05 -06:00
Jeff Carr 2ea1113c72 ignore 'gui' in .git/config 2025-01-07 03:24:05 -06:00
Jeff Carr 05d827868e move merge code to gitpb 2025-01-05 12:01:39 -06:00
Jeff Carr 3a53e0bd9b more things moved to gitpb 2024-12-17 18:49:24 -06:00
Jeff Carr 93e9e4e43b changes in gitpb 2024-12-17 06:36:45 -06:00
Jeff Carr 54cdb3fbec rm old code 2024-12-03 18:03:29 -06:00
Jeff Carr 283bd90e91 lots more moved to using the protobuf 2024-12-03 00:34:55 -06:00
Jeff Carr d5c394d3c3 moving things to protobuf 2024-11-30 02:03:17 -06:00
Jeff Carr b52c3c426a start moving things to gitpb 2024-11-29 23:18:46 -06:00
Jeff Carr c25e4dd406 hardcode go1.20 and above for testing mac builds 2024-11-29 22:46:02 -06:00
Jeff Carr e43863e8e7 start refactor to protobuf 2024-11-28 18:36:29 -06:00
Jeff Carr 9d13c972e4 always use https for git clone 2024-11-24 23:35:36 -06:00
Jeff Carr 2866815e3c work towards a global override file 2024-11-22 22:30:08 -06:00
Jeff Carr 4c46927bc7 todo: get this from 'go list' somehow? 2024-11-22 20:48:02 -06:00
Jeff Carr a1ce58e9d0 git clone needs to enforce downloading into godir/ 2024-11-17 17:19:09 -06:00
Jeff Carr 94e98f2145 fix clone logic 2024-11-17 16:07:39 -06:00
Jeff Carr 9358005c9d rework Clone() 2024-11-17 14:42:49 -06:00
Jeff Carr 2e8a1d4793 use more realtime output for git clone 2024-11-15 09:12:47 -06:00
Jeff Carr 4ab00cce02 minor rm 2024-11-14 21:48:21 -06:00
Jeff Carr a7c5499221 quiet some output 2024-11-13 11:56:02 -06:00
Jeff Carr 009d8f3b9d improve output handling via go-cmd
Signed-off-by: Jeff Carr <jcarr@wit.com>
2024-11-13 10:33:25 -06:00
Jeff Carr 55acea0bd7 use go-cmd/cmd 2024-11-08 06:43:33 -06:00
Jeff Carr 29545d3f04 clearer debugging 2024-11-07 07:04:39 -06:00
Jeff Carr 5be028858c start moving mappings to a config file 2024-11-07 05:08:17 -06:00
Jeff Carr 6b1330d7f3 remove old stdout junk 2024-11-07 02:25:31 -06:00
Jeff Carr 3ce9f5f773 find .proto and .pb.go files
Signed-off-by: Jeff Carr <jcarr@wit.com>
2024-11-06 20:30:00 -06:00
Jeff Carr 44ab5deb3f more work on protobuf files
Signed-off-by: Jeff Carr <jcarr@wit.com>
2024-11-06 19:23:05 -06:00
Jeff Carr 31355467a5 dumb nil panic
Signed-off-by: Jeff Carr <jcarr@wit.com>
2024-11-06 15:51:29 -06:00
Jeff Carr e6f883a9b5 final commits before release
Signed-off-by: Jeff Carr <jcarr@wit.com>
2024-11-05 05:58:54 -06:00
Jeff Carr 8eb7501855 add repo.Whitelist bool
Signed-off-by: Jeff Carr <jcarr@wit.com>
2024-11-05 03:14:46 -06:00
Jeff Carr 8786690d46 init flag for new repos
Signed-off-by: Jeff Carr <jcarr@wit.com>
2024-11-04 02:16:19 -06:00
Jeff Carr b451591006 DirtyList()
Signed-off-by: Jeff Carr <jcarr@wit.com>
2024-11-01 21:41:16 -05:00
Jeff Carr bf2a42ec64 hack to override golang.org/x URL's
Signed-off-by: Jeff Carr <jcarr@wit.com>
2024-10-11 21:14:46 -05:00
Jeff Carr 5bc1a24a69 use 'go list' to get the URL 2024-03-21 19:43:52 -05:00
Jeff Carr 2ce9051921 exec things to STDOUT
Signed-off-by: Jeff Carr <jcarr@wit.com>
2024-03-21 16:16:35 -05:00
Jeff Carr 804acc169a fix logic for go.work setups 2024-03-09 22:03:18 -06:00
Jeff Carr 2622e90b1f one must pass the go path to go mod init 2024-03-09 18:30:04 -06:00
Jeff Carr 7d3e4ce84e add submodules section of the .git/config 2024-03-09 16:50:18 -06:00
Jeff Carr 546ad6a842 look for go-import in the HTML 2024-03-08 15:09:46 -06:00
Jeff Carr 54367ddc72 initial clone works 2024-03-07 22:08:32 -06:00
Jeff Carr 2cdf2c3cda working on go-clone 2024-03-07 19:31:52 -06:00
22 changed files with 682 additions and 2698 deletions

View File

@ -1,4 +1,4 @@
all:
all: goimports
GO111MODULE=off go vet
goimports:
@ -10,3 +10,6 @@ redomod:
GO111MODULE= go mod init
GO111MODULE= go mod tidy
clean:
rm -f go.*
go-mod-clean --purge

1
README.md Normal file
View File

@ -0,0 +1 @@
This code is really hacky still

View File

@ -2,74 +2,36 @@ package repostatus
import (
"go.wit.com/gui"
"go.wit.com/lib/gadgets"
"go.wit.com/log"
)
func (rs *RepoStatus) makeBranchesBox(parent *gui.Node) {
repo := rs.pb
rs.gitBranchesGroup = parent.NewGroup("branches") // `progname:"BRANCHES"` // can the toolkits use these for i18n support?
newgrid := rs.gitBranchesGroup.NewGrid("gridnuts", 0, 0)
grid := rs.gitBranchesGroup.RawGrid()
rs.lasttag = gadgets.NewOneLiner(newgrid, "last tag") // `progname:"LASTTAG"`
newgrid.NextRow()
rs.mainBranchVersion = gadgets.NewOneLiner(newgrid, "master") // `progname:"MASTERBRANCH"`
newgrid.NextRow()
rs.develBranchVersion = gadgets.NewOneLiner(newgrid, "devel") // `progname:"DEVELBRANCH"`
newgrid.NextRow()
rs.userBranchVersion = gadgets.NewOneLiner(newgrid, "user") // `progname:"USERBRANCH"`
newgrid.NextRow()
rs.currentBranch = gadgets.NewOneLiner(newgrid, "current branch") // `progname:"CURRENTBRANCH"`
newgrid.NextRow()
rs.currentVersion = gadgets.NewOneLiner(newgrid, "current version") // `progname:"CURRENTVERSION"`
newgrid.NextRow()
rs.switchBranchB = newgrid.NewButton("Switch Branch", func() { // `progname:"SWITCH"`
bname := rs.targetBranch.String()
log.Info("Should switch to branch", bname, "here")
var all [][]string
all = append(all, []string{"git", "checkout", bname})
if rs.DoAll(all) {
log.Info("branch switched to", bname)
} else {
log.Info("branch switched to", bname, "failed")
var win *repoBranchesWindow
grid.NewButton("Branches Window", func() {
if win != nil {
win.Toggle()
return
}
rs.updateNew()
log.Info("redo this")
win = MakeRepoBranchesWindow(repo)
win.Show()
})
grid.NextRow()
rs.targetBranch = newgrid.NewDropdown() // `progname:"TARGET"`
// rs.targetBranch.AddText("master")
newgrid.NextRow()
// runs "git branch --all"
// rs.gitBranchAll()
rs.showBranchesButton = newgrid.NewButton("find jcarr and devel", func() {
if rs.TagExists("jcarr") {
log.Log(WARN, "tag jcarr exists")
} else {
log.Log(WARN, "tag jcarr does not exist")
}
if rs.TagExists("devel") {
log.Log(WARN, "tag devel exists")
} else {
log.Log(WARN, "tag devel does not exist")
var mergeWin *repoMergeWindow
grid.NewButton("Merge Window", func() {
if mergeWin != nil {
mergeWin.Toggle()
return
}
log.Info("redo this")
mergeWin = rs.MakeRepoMergeWindow(repo)
mergeWin.Show()
})
newgrid.NextRow()
grid.NextRow()
rs.checkBranchesButton = newgrid.NewButton("CheckBranches()", func() {
if rs.CheckBranches() {
log.Log(WARN, "Branches are perfect")
} else {
log.Log(WARN, "Branches are not perfect")
}
})
newgrid.NextRow()
newgrid.NewButton("Revert master to devel", func() {
rs.RevertMasterToDevel()
})
}

204
common.go
View File

@ -1,11 +1,7 @@
package repostatus
import (
"strings"
"unicode"
"go.wit.com/log"
// "go.wit.com/gui/gui"
)
// reports externally if something has changed
@ -25,44 +21,10 @@ func (rs *RepoStatus) getChanges() string {
}
func (rs *RepoStatus) NoteChange(s string) {
log.Log(REPOWARN, "NoteChange() got", rs.String(), s)
rs.changed = true
rs.changes += s + "\n"
}
// deprecate this. returns the gopath right now
func (rs *RepoStatus) String() string {
// log.Warn("RepoStatus.String() is to be deprecated")
return rs.path.String()
}
// returns the go path for the repo. "go.wit.com/apps/autotypist"
func (rs *RepoStatus) GoName() string {
return rs.GoPath()
}
// not sure which name is easier to remember. probably this one
func (rs *RepoStatus) GoPath() string {
return rs.goPath.String()
}
// full path
func (rs *RepoStatus) FullPath() string {
return rs.realPath.String()
}
func (rs *RepoStatus) IsPrimitive() bool {
if rs.primitive.String() == "true" {
return true
}
return false
}
// returns the filesystem path to the repo
func (rs *RepoStatus) Path() string {
return rs.realPath.String()
}
func (rs *RepoStatus) Show() {
if !rs.Ready() {
return
@ -101,143 +63,59 @@ func (rs *RepoStatus) Ready() bool {
return rs.ready
}
func (rs *RepoStatus) IsGoLang() bool {
if !rs.Ready() {
return false
}
if rs.isGoLang.String() == "true" {
return true
}
return false
// disable all things besides Update() button
func (rs *RepoStatus) DisableEverything() {
log.Log(INFO, "DisableEverything()")
// choosing a major, minor or revision
rs.major.Disable()
rs.minor.Disable()
rs.revision.Disable()
// disable adding a tag message
rs.versionMessage.Disable()
// disable the merge devel to master button
rs.develMergeB.Disable()
// disable the tag a new version button
rs.releaseVersion.Disable()
}
func (rs *RepoStatus) RepoType() string {
if !rs.IsGoLang() {
return ""
}
err, output := rs.RunCmd([]string{"go", "list", "-f", "'{{if eq .Name \"main\"}}binary{{else}}library{{end}}'"})
if err == nil {
output = strings.Trim(output, "'")
// log.Info("go package is:", output)
return output
}
// log.Info("package is: unknown", err)
return ""
// this means devel needs to be merged to master
func (rs *RepoStatus) EnableMergeDevel() {
rs.DisableEverything()
rs.develMergeB.Enable()
}
func (rs *RepoStatus) BinaryName() string {
// get the package name from the repo name
path := rs.String()
parts := strings.Split(path, "/")
name := parts[len(parts)-1]
return name
func (rs *RepoStatus) Disable() {
rs.window.Disable()
}
func (rs *RepoStatus) Build() bool {
if !rs.IsGoLang() {
return false
}
name := rs.BinaryName()
// removes the binary if it already exists
rs.RunCmd([]string{"rm", "-f", name})
if rs.Exists(name) {
log.Warn("file could not be removed filename =", name)
return false
}
log.Info("need to build here", rs.String())
// rs.RunCmd([]string{"go", "build", "-v", "-x"})
rs.XtermBash([]string{"go", "build", "-v", "-x"})
if rs.Exists(name) {
log.Warn("build worked", name)
return true
}
log.Warn("build failed", name)
return false
func (rs *RepoStatus) Enable() {
rs.window.Enable()
}
func (rs *RepoStatus) GetTargetVersion() string {
return rs.targetReleaseVersion.String()
}
// this means you need to release a new version of the master repository
func (rs *RepoStatus) EnableSelectTag() {
rs.DisableEverything()
func (rs *RepoStatus) GetCurrentVersion() string {
return rs.currentVersion.String()
}
// choosing a major, minor or revision
rs.major.Enable()
rs.minor.Enable()
rs.revision.Enable()
func (rs *RepoStatus) LastTag() string {
return rs.lasttag.String()
}
// disable adding a tag message
rs.versionMessage.Enable()
func (rs *RepoStatus) IncrementVersion() bool {
rs.incrementRevision()
rs.EnableSelectTag()
rs.setTag()
newtag := "v" + rs.newversion.String()
log.Log(REPOWARN, rs.GoPath(), "old version:", rs.LastTag(), "new version:", newtag)
rs.targetReleaseVersion.SetText(newtag)
return true
}
rs.develMergeB.SetLabel("ready to release")
// TODO: run this through the sanity check!
func (rs *RepoStatus) SetTargetVersion(s string) {
// todo: redo setTag to do increment logic
// func (rs *RepoStatus) setTag() bool {
rs.targetReleaseVersion.SetText(s)
}
func (rs *RepoStatus) IsPrivate() bool {
if rs.private.String() == "true" {
return true
}
return false
}
func (rs *RepoStatus) SetPrivate(b bool) {
if b {
rs.private.SetText("true")
if len(rs.versionMessage.String()) == 0 {
// force there to be a commit message
rs.releaseVersion.Disable()
} else {
rs.private.SetText("false")
// rs.generateCmd()
rs.releaseVersion.Enable()
}
}
// returns a name for human consuption only
// todo: implement nicknames
func (rs *RepoStatus) Name() string {
if rs.IsGoLang() {
return rs.GoPath()
}
return rs.Path()
}
func trimNonNumericFromStart(s string) string {
for i, r := range s {
if unicode.IsDigit(r) {
return s[i:]
}
}
return ""
}
func (rs *RepoStatus) DebianReleaseVersion() string {
lasttag := rs.GetLastTagVersion()
newv := trimNonNumericFromStart(lasttag)
if newv == "" {
newv = "0.0"
if lasttag != "" {
newv += "-" + lasttag
}
}
return newv
}
func (rs *RepoStatus) DebianCurrentVersion() string {
cbversion := rs.GetCurrentBranchVersion()
newv := trimNonNumericFromStart(cbversion)
if newv == "" {
newv = "0.0"
}
if rs.CheckDirty() {
newv += "-dirty"
}
return newv
}

57
deps.go
View File

@ -1,57 +0,0 @@
package repostatus
import (
"bufio"
"os"
"path/filepath"
"strings"
"go.wit.com/log"
)
func (rs *RepoStatus) GetGoDeps() GoConfig {
tmp := filepath.Join(rs.realPath.String(), "go.sum")
gosum, err := os.Open(tmp)
if err != nil {
log.Log(WARN, "\tmissing go.sum", rs.realPath.String())
return nil
}
defer gosum.Close()
var deps GoConfig
deps = make(GoConfig)
scanner := bufio.NewScanner(gosum)
log.Info("\tgosum:", tmp)
for scanner.Scan() {
line := strings.TrimSpace(scanner.Text())
parts := strings.Split(line, " ")
if len(parts) == 3 {
godep := strings.TrimSpace(parts[0])
version := strings.TrimSpace(parts[1])
if strings.HasSuffix(version, "/go.mod") {
version = strings.TrimSuffix(version, "/go.mod")
}
currentversion, ok := deps[godep]
if ok {
if currentversion != version {
log.Info("\tREPO:", rs.String(), rs.realPath.String())
log.Info("\t version mismatch:", godep, version, currentversion)
}
} else {
deps[godep] = version
log.Info("\t", godep, "=", version)
}
} else {
log.Info("\t INVALID:", parts)
return nil
}
}
if err := scanner.Err(); err != nil {
return nil
}
return deps
}

547
git.go
View File

@ -1,83 +1,34 @@
package repostatus
import (
"errors"
"fmt"
"os/user"
"strings"
"time"
"unicode/utf8"
"io/ioutil"
"go.wit.com/log"
)
func (rs *RepoStatus) GetCurrentBranchName() string {
return rs.currentBranch.String()
}
func (rs *RepoStatus) GetCurrentBranchVersion() string {
return rs.currentVersion.String()
}
func (rs *RepoStatus) LastGitPull() (time.Time, error) {
return rs.mtime(".git/FETCH_HEAD")
}
func (rs *RepoStatus) Age() time.Duration {
var t *Tag
t = rs.NewestTag()
if t != nil {
log.Log(REPO, "newest tag:", t.date.String(), t.tag.String(), t.Name())
return t.Age()
}
const gitLayout = "Mon Jan 2 15:04:05 2006 -0700"
const madeuptime = "Mon Jun 3 15:04:05 2013 -0700"
tagTime, _ := time.Parse(gitLayout, madeuptime)
return time.Since(tagTime)
}
var ErrorMissingGitConfig error = errors.New("missing .git/config")
var ErrorGitPullOnLocal error = errors.New("git pull on local only branch")
func (rs *RepoStatus) GitPull() (string, error) {
currentName := rs.GetCurrentBranchName()
if rs.IsOnlyLocalTag(currentName) {
return "", ErrorGitPullOnLocal
}
var cmd []string
cmd = append(cmd, "git", "pull")
err, output := rs.RunCmd(cmd)
if err != nil {
output = "git error_,,,_a_,,,_b_,,,c"
}
if err == nil {
log.Log(REPOWARN, "git pull ran", rs.Path())
log.Log(REPOWARN, "git pull output", output)
} else {
log.Log(REPOWARN, "git pull error", rs.Path(), err)
}
return output, err
// most everything here needs to be deprecated now
func (rs *RepoStatus) Path() string {
return rs.realPath.String()
}
/*
// this isn't right
func (rs *RepoStatus) LastTagAge() (time.Time, string) {
return time.Now(), rs.lasttag.String()
func (rs *RepoStatus) GitState() string {
return rs.gitState.String()
}
*/
func (rs *RepoStatus) GetStatus() string {
return rs.gitState.String()
}
func (rs *RepoStatus) GetLastTagVersion() string {
return rs.lasttag.String()
}
func (rs *RepoStatus) displayCurrentBranchName() string {
out := rs.pb.GetCurrentBranchName()
rs.currentBranch.SetValue(out)
return out
}
// stores the current branch name
func (rs *RepoStatus) checkCurrentBranchName() string {
currentname := rs.currentBranch.String()
out := run(rs.realPath.String(), "git", "branch --show-current")
out := rs.pb.GetCurrentBranchName()
if currentname == out {
// nothing changed
return currentname
@ -89,469 +40,3 @@ func (rs *RepoStatus) checkCurrentBranchName() string {
rs.NoteChange("current branch has changed from " + currentname + " to " + out)
return out
}
func (rs *RepoStatus) gitDescribeByHash(hash string) (string, error) {
if hash == "" {
return "", errors.New("hash was blank")
}
err, out := rs.RunCmd([]string{"git", "describe", "--tags", "--always", hash})
if err != nil {
log.Warn("not in a git repo or bad hash?", err, rs.Path())
return "", err
}
out = strings.TrimSpace(out)
return out, err
}
func (rs *RepoStatus) gitDescribeByName(name string) (string, error) {
name = strings.TrimSpace(name)
if name == "" {
// git will return the current tag
err, out := rs.RunCmd([]string{"git", "describe", "--tags", "--always"})
if err != nil {
log.Warn("not in a git repo?", err, rs.Path())
return "", err
}
out = strings.TrimSpace(out)
return out, err
}
if !rs.LocalTagExists(name) {
// tag does not exist
return "", errors.New("git fatal: Not a valid object name")
}
cmd := []string{"git", "describe", "--tags", "--always", name}
err, out := rs.RunCmd(cmd)
if err != nil {
log.Warn("cmd =", cmd)
log.Warn("err =", err)
log.Warn("not in a git repo or bad tag?", rs.Path())
return "", err
}
out = strings.TrimSpace(out)
return out, err
}
// todo: don't run git every time?
func (rs *RepoStatus) checkCurrentBranchVersion() string {
out, _ := rs.gitDescribeByName("")
log.Log(REPO, "checkCurrentBranchVersion()", out)
rs.currentVersion.SetValue(out)
return out
}
// this should get the most recent tag
func (rs *RepoStatus) setLastTagVersion() {
hash := run(rs.realPath.String(), "git", "rev-list --tags --max-count=1")
log.Log(REPO, "getLastTagVersion()", hash)
name, _ := rs.gitDescribeByHash(hash)
rs.lasttag.SetText(name)
return
}
func (rs *RepoStatus) populateTags() {
tmp := rs.realPath.String() + "/.git/refs/tags"
log.Log(REPO, "populateTags() path =", tmp)
for _, tag := range listFiles(tmp) {
if rs.tags[tag] == "" {
log.Log(REPO, "populateTags() Adding new tag", tag)
// rs.tagsDrop.AddText(tag)
rs.tags[tag] = "origin"
}
}
// rs.tagsDrop.SetText(rs.lasttagrev)
}
func (rs *RepoStatus) getBranches() []string {
var all []string
var heads []string
var remotes []string
heads = listFiles(rs.realPath.String() + "/.git/refs/heads")
remotes = listFiles(rs.realPath.String() + "/.git/refs/remotes")
all = heads
all = append(all, remotes...)
for _, branch := range all {
log.Log(REPO, "getBranches()", branch)
}
return all
}
// returns quickly based on the last time it was checked
func (rs *RepoStatus) IsDirty() bool {
if rs.dirtyLabel.String() == "no" {
return false
}
return true
}
func (rs *RepoStatus) CheckDirty() bool {
var start string = rs.dirtyLabel.String()
cmd := []string{"git", "status"}
err, out := rs.RunCmd(cmd)
if err != nil {
log.Warn("CheckDirty() status cmd =", cmd)
log.Warn("CheckDirty() status out =", out)
log.Warn("CheckDirty() status err =", err)
log.Error(err, "CheckDirty() git status error")
rs.dirtyLabel.SetValue("error")
if start != "error" {
rs.NoteChange("git status is in error " + fmt.Sprint(err))
}
return true
}
last := out[strings.LastIndex(out, "\n")+1:]
if last == "nothing to commit, working tree clean" {
log.Log(REPO, "CheckDirty() no", rs.realPath.String())
rs.dirtyLabel.SetValue("no")
if start != "no" {
log.Log(REPOWARN, "is no longer dirty")
rs.NoteChange("is no longer dirty")
}
return false
}
rs.dirtyLabel.SetValue("dirty")
if start != "dirty" {
log.Log(REPOWARN, "is now dirty")
rs.NoteChange("is now dirty")
}
return true
}
func (rs *RepoStatus) CheckoutBranch(bname string) bool {
if rs.CheckDirty() {
log.Log(REPO, rs.realPath.String(), "is dirty")
log.Info(bname, "is dirty", rs.Path())
return false
}
if !rs.TagExists(bname) {
// tag does not exist
log.Log(REPO, "repo does not have branch", bname, rs.Path())
return false
}
cName := rs.GetCurrentBranchName()
if cName == bname {
// already on branch
return true
}
cmd := []string{"git", "checkout", bname}
err, b, output := RunCmd(rs.realPath.String(), cmd)
if err != nil {
log.Log(REPO, err, b, output)
return false
}
rs.checkCurrentBranchName()
rs.checkCurrentBranchVersion()
return true
}
func (rs *RepoStatus) CheckoutMaster() bool {
if rs.CheckDirty() {
log.Log(REPO, rs.realPath.String(), "is dirty")
return false
}
mName := rs.GetMasterBranchName()
if rs.CheckoutBranch(mName) {
return true
}
return true
}
func (rs *RepoStatus) CheckoutDevel() bool {
devel := rs.develWorkingName.String()
// user := rs.userWorkingName.String()
if devel == "" {
return false
}
if rs.CheckDirty() {
log.Log(REPO, rs.realPath.String(), "is dirty")
return false
}
log.Log(REPO, "checkoutBranch", devel)
rs.checkoutBranch("devel", devel)
// log.Log(REPO, "checkoutBranch", user)
// rs.checkoutBranch("user", user)
return true
}
func (rs *RepoStatus) CheckoutUser() bool {
bName := rs.GetUserBranchName()
if bName == "" {
return false
}
if rs.CheckDirty() {
log.Log(REPO, rs.realPath.String(), "is dirty")
return false
}
cmd := []string{"git", "checkout", bName}
err, b, output := RunCmd(rs.realPath.String(), cmd)
if err != nil {
log.Log(REPO, err, b, output)
}
realname := rs.GetCurrentBranchName()
realversion := rs.GetCurrentBranchVersion()
log.Log(REPO, rs.realPath.String(), "realname =", realname, "realversion =", realversion)
if realname != bName {
log.Log(REPO, "git checkout failed", rs.realPath.String(), bName, "!=", realname)
return false
}
rs.userBranchVersion.SetValue(realversion)
return true
}
func (rs *RepoStatus) checkoutBranch(level string, branch string) {
if rs.CheckDirty() {
log.Log(REPO, "checkoutBranch() checkDirty() == true for repo", rs.realPath.String(), "looking for branch:", branch)
return
}
out := run(rs.realPath.String(), "git", "checkout "+branch)
log.Log(REPO, rs.realPath.String(), "git checkout "+branch, "returned", out)
realname := rs.GetCurrentBranchName()
realversion := rs.GetCurrentBranchVersion()
log.Log(REPO, rs.realPath.String(), "realname =", realname, "realversion =", realversion)
switch level {
case "master":
rs.mainBranchVersion.SetValue(realversion)
case "devel":
rs.develBranchVersion.SetValue(realversion)
case "user":
rs.userBranchVersion.SetValue(realversion)
default:
}
}
// attempt's to guess at what master is.
// TODO: fix this properly
func (rs *RepoStatus) guessMainWorkingName() {
if !rs.Ready() {
return
}
if rs.TagExists("guimaster") {
rs.mainWorkingName.SetText("guimaster")
rs.mainBranchVersion.SetLabel("guimaster")
return
}
if rs.TagExists("master") {
rs.mainWorkingName.SetText("master")
rs.mainBranchVersion.SetLabel("master")
return
}
if rs.TagExists("main") {
rs.mainWorkingName.SetText("main")
rs.mainBranchVersion.SetLabel("main")
return
}
// figure out what to do here
rs.mainWorkingName.SetText("FIXME")
rs.mainBranchVersion.SetLabel("FIXME")
}
func (rs *RepoStatus) guessDevelWorkingName() {
if rs.TagExists("guidevel") {
rs.develWorkingName.SetValue("guidevel")
rs.develBranchVersion.SetLabel("guidevel")
return
}
if rs.TagExists("devel") {
rs.develWorkingName.SetValue("devel")
rs.develBranchVersion.SetLabel("devel")
return
}
// figure out what to do here
rs.develWorkingName.SetValue("develFIXME")
rs.develBranchVersion.SetLabel("develFIXME")
}
func (rs *RepoStatus) setUserWorkingName() {
usr, _ := user.Current()
uname := usr.Username
if rs.TagExists(uname) {
rs.userWorkingName.SetValue(uname)
rs.userBranchVersion.SetLabel(uname)
return
}
rs.userWorkingName.SetValue("need to create " + uname)
rs.userBranchVersion.SetLabel("need to create " + uname)
}
// returns "master", "devel", os.Username, etc
func (rs *RepoStatus) GetMasterBranchName() string {
name := rs.mainWorkingName.String()
return name
}
func (rs *RepoStatus) GetDevelBranchName() string {
name := rs.develWorkingName.String()
return name
}
func (rs *RepoStatus) GetUserBranchName() string {
name := rs.userWorkingName.String()
return name
}
// returns the git versions like "1.3-2-laksdjf" or whatever
func (rs *RepoStatus) GetMasterVersion() string {
name := rs.mainBranchVersion.String()
return name
}
func (rs *RepoStatus) GetDevelVersion() string {
name := rs.develBranchVersion.String()
return name
}
func (rs *RepoStatus) GetUserVersion() string {
name := rs.userBranchVersion.String()
return name
}
func (rs *RepoStatus) setMasterVersion(s string) {
old := rs.GetMasterVersion()
if old == s {
return
}
rs.mainBranchVersion.SetValue(s)
if old == "" {
return // don't note if there was nothing before
}
rs.NoteChange("master branch has been changed from " + old + " to " + s)
}
func (rs *RepoStatus) setDevelVersion(s string) {
old := rs.GetDevelVersion()
if old == s {
return
}
if old == "" {
// don't note nothing
} else {
rs.NoteChange("devel branch has been changed from " + old + " to " + s)
}
rs.develBranchVersion.SetValue(s)
}
func (rs *RepoStatus) setUserVersion(s string) {
old := rs.GetUserVersion()
if old == s {
return
}
if old == "" {
// don't note nothing
} else {
rs.NoteChange("user branch has been changed from " + old + " to " + s)
}
rs.userBranchVersion.SetValue(s)
}
func (rs *RepoStatus) GitState() string {
return rs.gitState.String()
}
func (rs *RepoStatus) CheckGitState() string {
rs.setState()
return rs.gitState.String()
}
func (rs *RepoStatus) GetStatus() string {
return rs.gitState.String()
}
func (rs *RepoStatus) setState() {
rs.changed = false
if rs.CheckDirty() {
log.Log(REPO, "CheckDirty() true")
rs.gitState.SetText("dirty")
return
}
if rs.GetUserVersion() != rs.GetDevelVersion() {
rs.gitState.SetText("merge to devel")
return
}
if rs.GetDevelVersion() != rs.GetMasterVersion() {
rs.gitState.SetText("merge to main")
return
}
if rs.lasttag.String() != rs.GetMasterVersion() {
rs.gitState.SetText("unchanged")
return
}
if rs.CheckBranches() {
log.Log(REPO, "Branches are Perfect")
rs.gitState.SetText("PERFECT")
return
}
log.Log(REPO, rs.String(), "Branches are not Perfect")
rs.gitState.SetText("unknown branches")
}
// TODO: make this report the error somewhere
// This is supposed to check all the branches to make sure
// the are the same. that was originally what this was for
// now I think it's jsut probably dumb old code that doesn't
// need to be here
// actually, this is to attempt to verify absolutely everything
// is pushed upstream before doing a rm -rf ~/go/src
// TODO: revisit this code in the autotypist later
func (rs *RepoStatus) CheckBranches() bool {
var hashCheck string
var perfect bool = true
all := rs.getBranches()
path := rs.realPath.String() + "/.git/refs/"
for _, b := range all {
parts := strings.Split(b, "/")
rdir := "heads"
if len(parts) == 2 {
rdir = "remotes"
}
fullfile := path + "/" + rdir + "/" + b
// check if the ref name is "HEAD". if so, skip
runeCount := utf8.RuneCountInString(fullfile)
// Convert the string to a slice of runes
runes := []rune(fullfile)
// Slice the last 4 runes
lastFour := runes[runeCount-4:]
if string(lastFour) == "HEAD" {
log.Log(REPO, "skip HEAD fullfile", fullfile)
continue
}
content, _ := ioutil.ReadFile(fullfile)
hash := strings.TrimSpace(string(content))
if hashCheck == "" {
hashCheck = hash
}
var cmd []string
cmd = append(cmd, "git", "show", "-s", "--format=%ci", hash)
err, output := rs.RunCmd(cmd)
if err != nil {
// log.Log(WARN, "cmd failed", cmd, "err =", err, "in", rs.String())
}
// git show -s --format=%ci <hash> will give you the time
// log.Log(REPO, fullfile)
if hash == hashCheck {
log.Log(REPO, hash, output, b)
} else {
// log.Log(WARN, rs.String(), hash, output, b)
// log.Log(WARN, "UNKNOWN BRANCHES IN THIS REPO", cmd)
rs.versionCmdOutput.SetText("UNKNOWN BRANCHES")
perfect = false
// parts := strings.Split(b, "/")
// log.Warn("git push", parts)
}
}
return perfect
}

View File

@ -1,273 +0,0 @@
package repostatus
import (
"bufio"
"errors"
"os"
"path/filepath"
"strings"
"go.wit.com/log"
)
// GitConfig represents the parsed .git/config data
// type GitConfig map[string]map[string]string
type remote struct {
url string
fetch string
}
type branch struct {
remote string
merge string
}
type GitConfig struct {
core map[string]string // map[origin] = "https:/git.wit.org/gui/gadgets"
remotes map[string]*remote // map[origin] = "https:/git.wit.org/gui/gadgets"
branches map[string]*branch // map[guimaster] = origin guimaster
hashes map[string]string
versions map[string]string
}
type GoConfig map[string]string
func ListGitDirectories() []string {
var all []string
homeDir, err := os.UserHomeDir()
if err != nil {
log.Log(WARN, "Error getting home directory:", err)
return nil
}
srcDir := filepath.Join(homeDir, "go/src")
err = filepath.Walk(srcDir, func(path string, info os.FileInfo, err error) error {
if err != nil {
log.Log(WARN, "Error accessing path:", path, err)
return nil
}
// Check if the current path is a directory and has a .git subdirectory
if info.IsDir() && IsGitDir(path) {
all = append(all, path)
// fmt.Println(path)
}
return nil
})
if err != nil {
log.Log(WARN, "Error walking the path:", srcDir, err)
}
return all
}
// IsGitDir checks if a .git directory exists inside the given directory
func IsGitDir(dir string) bool {
gitDir := filepath.Join(dir, ".git")
info, err := os.Stat(gitDir)
if os.IsNotExist(err) {
return false
}
return info.IsDir()
}
// readGitConfig reads and parses the .git/config file
func (rs *RepoStatus) readGitConfig() error {
filename := filepath.Join(rs.realPath.String(), "/.git/config")
file, err := os.Open(filename)
if err != nil {
log.Log(WARN, "readGitConfig() failed for file:", filename)
filename = filepath.Join(rs.realPath.String(), "../.git/config")
log.Log(WARN, "readGitConfig() trying up one directory instead", filename)
file, err = os.Open(filename)
if err != nil {
return errors.New("couldn't open .git/config")
}
}
defer file.Close()
var currentSection string = ""
var currentName string = ""
rs.gitConfig = new(GitConfig)
rs.gitConfig.core = make(map[string]string)
rs.gitConfig.remotes = make(map[string]*remote)
rs.gitConfig.branches = make(map[string]*branch)
rs.gitConfig.versions = make(map[string]string)
rs.gitConfig.hashes = make(map[string]string)
scanner := bufio.NewScanner(file)
for scanner.Scan() {
line := strings.TrimSpace(scanner.Text())
// Skip empty lines and comments
if line == "" || strings.HasPrefix(line, "#") || strings.HasPrefix(line, ";") {
continue
}
// Check for section headers
if strings.HasPrefix(line, "[") && strings.HasSuffix(line, "]") {
line = strings.Trim(line, "[]")
parts := strings.Split(line, " ")
currentSection = parts[0]
if len(parts) == 2 {
line = strings.Trim(line, "[]")
currentName = strings.Trim(parts[1], "\"")
}
continue
}
partsNew := strings.SplitN(line, "=", 2)
if len(partsNew) != 2 {
log.Log(WARN, "error on config section:", currentSection, "line:", line)
}
key := strings.TrimSpace(partsNew[0])
key = strings.TrimSuffix(key, "\"")
value := strings.TrimSpace(partsNew[1])
value = strings.TrimSuffix(value, "\"")
switch currentSection {
case "core":
rs.gitConfig.core[key] = value
case "pull":
// don't store git config pull settings here
// probably has 'rebase = false'
case "remote":
test, ok := rs.gitConfig.remotes[currentName]
if !ok {
test = new(remote)
rs.gitConfig.remotes[currentName] = test
}
log.Log(INFO, "switch currentSection", currentSection, currentName)
switch key {
case "url":
if test.url == value {
continue
}
if test.url == "" {
test.url = value
continue
}
log.Log(WARN, "error url mismatch", test.url, value)
case "fetch":
if test.fetch == value {
continue
}
if test.fetch == "" {
test.fetch = value
continue
}
log.Log(WARN, "error fetch mismatch", test.fetch, value)
default:
log.Log(WARN, "error unknown remote:", currentSection, currentName, "key", key, "value", value)
}
case "branch":
test, ok := rs.gitConfig.branches[currentName]
if !ok {
test = new(branch)
rs.gitConfig.branches[currentName] = test
rs.processBranch(currentName)
}
switch key {
case "remote":
rs.gitConfig.branches[currentName].remote = value
case "merge":
rs.gitConfig.branches[currentName].merge = value
default:
log.Log(WARN, "error unknown remote:", currentSection, currentName, key, value)
}
default:
log.Log(WARN, "error unknown currentSection", currentSection, "line:", line)
}
}
if err := scanner.Err(); err != nil {
return err
}
return nil
}
func (rs *RepoStatus) GitURL() string {
origin, ok := rs.gitConfig.remotes["origin"]
if ok {
return origin.url
}
for i, s := range rs.gitConfig.remotes {
log.Log(WARN, "remote:", i, s.url)
}
log.Log(WARN, "GitURL() repo has non-standard origin or is not uploaded")
return ""
}
func (rs *RepoStatus) GitLsFiles() (bool, string) {
err, output := rs.RunCmd([]string{"git", "ls-files"})
if err != nil {
log.Warn("git ls-files failed err =", err)
log.Warn("git ls-files failed output =", output)
return false, output
}
return true, output
}
/*
func (rs *RepoStatus) Writable() {
rs.readOnly.SetText("false")
}
*/
func (rs *RepoStatus) ReadOnly() bool {
if rs.readOnly.String() == "true" {
return true
} else {
return false
}
}
func (rs *RepoStatus) SetReadOnly(b bool) {
if b {
rs.readOnly.SetText("true")
} else {
rs.readOnly.SetText("false")
}
}
func (rs *RepoStatus) processBranch(branch string) {
fullpath := rs.realPath.String()
log.Log(INFO, " ", branch)
hash, ok := rs.gitConfig.hashes[branch]
filename := fullpath + "/.git/refs/heads/" + branch
log.Log(INFO, " hash: need to open", filename)
newhash, err := readFileToString(filename)
if err != nil {
log.Log(WARN, "hash: read failed", filename, rs.String())
return
}
log.Log(INFO, " hash:", newhash)
rs.gitConfig.hashes[branch] = newhash
if ok {
if hash != newhash {
log.Log(WARN, "hash changed", hash, rs.String())
}
}
name, _ := rs.gitDescribeByHash(newhash)
rs.gitConfig.versions[newhash] = name
log.Log(INFO, " hash: version", name)
}
func (rs *RepoStatus) BranchExists(branch string) bool {
hash, ok := rs.gitConfig.hashes[branch]
if ok {
log.Log(REPOWARN, rs.Path(), "found branch", branch, hash)
return true
}
return false
}

View File

@ -1,167 +0,0 @@
package repostatus
// does processing on the go.mod and go.sum files
import (
"bufio"
"errors"
"os"
"path/filepath"
"strings"
"go.wit.com/log"
)
// Detect a 'Primative' package. Sets the isPrimative flag
// will return true if the repo is truly not dependent on _anything_ else
// like spew or lib/widget
// it assumes go mod ran init and tidy ran without error
func (rs *RepoStatus) isPrimativeGoMod() (bool, error) {
// go mod init & go mod tidy ran without errors
log.Log(REPO, "isPrimativeGoMod()", rs.realPath.String())
tmp := filepath.Join(rs.realPath.String(), "go.mod")
gomod, err := os.Open(tmp)
if err != nil {
log.Log(REPO, "missing go.mod", rs.realPath.String())
rs.goConfig = nil
return false, err
}
defer gomod.Close()
scanner := bufio.NewScanner(gomod)
for scanner.Scan() {
line := strings.TrimSpace(scanner.Text())
parts := strings.Split(line, " ")
log.Log(REPO, " gomod:", parts)
if len(parts) >= 1 {
log.Log(REPO, " gomod: part[0] =", parts[0])
if parts[0] == "require" {
log.Log(REPO, " should return false here")
return false, errors.New("go.mod file is not primative")
}
}
}
return true, nil
}
// readGoMod reads and parses the go.sum file
// saves the config information in *Repo.goConfig
func (rs *RepoStatus) parseGoSum() (bool, error) {
tmp := filepath.Join(rs.realPath.String(), "go.sum")
gosum, err := os.Open(tmp)
if err != nil {
log.Log(REPO, "missing go.sum", rs.realPath.String())
rs.goConfig = nil
return false, err
}
defer gosum.Close()
var deps GoConfig
deps = make(GoConfig)
scanner := bufio.NewScanner(gosum)
log.Log(REPO, "gosum:", tmp)
for scanner.Scan() {
line := strings.TrimSpace(scanner.Text())
parts := strings.Split(line, " ")
if len(parts) == 3 {
godep := strings.TrimSpace(parts[0])
version := strings.TrimSpace(parts[1])
if strings.HasSuffix(version, "/go.mod") {
version = strings.TrimSuffix(version, "/go.mod")
}
currentversion, ok := deps[godep]
if ok {
// only use the first value found in the file?
// this shouldn't have been possible. this function should
// only be called from MakeRedomod()
// todo: make go things a seperate package so this function
// isn't exported?
if version != currentversion {
log.Log(REPOWARN, "\tgo.sum ", godep, "had both", version, currentversion)
}
} else {
deps[godep] = version
log.Log(REPO, "\t", godep, "=", version)
}
} else {
// I've never seen this happen yet
return false, errors.New("go.sum invalid: " + line)
}
}
if err := scanner.Err(); err != nil {
rs.goConfig = nil
return false, err
}
rs.goConfig = deps
return true, nil
}
func (rs *RepoStatus) GoConfig() map[string]string {
return rs.goConfig
}
// poor name perhaps. It's because in most of these
// repos you can also type "make redomod" to do the same thing
// since it's a Makefile task that is also useful to be able to run
// from the command line
func (rs *RepoStatus) MakeRedomod() (bool, error) {
var err error
var output string
if rs.ReadOnly() {
log.Log(REPO, "will not go mod redo read only repos", rs.String())
return false, errors.New(rs.GoPath() + " is read-only ")
}
// unset the go development ENV var to generate release files
os.Unsetenv("GO111MODULE")
err, output = rs.RunCmd([]string{"rm", "-f", "go.mod", "go.sum"})
if err != nil {
log.Log(REPO, "rm failed", err, output)
return false, err
}
err, output = rs.RunCmd([]string{"go", "mod", "init"})
if err != nil {
log.Log(REPO, "go mod init failed", err, output)
return false, err
}
err, output = rs.RunCmd([]string{"go", "mod", "tidy"})
if err != nil {
log.Log(REPO, "go mod tidy failed", err, output)
return false, err
}
log.Log(REPO, "MakeRedomod() worked", rs.GoPath())
if rs.Exists("go.sum") {
// return the attempt to parse go.mod & go.sum
return rs.parseGoSum()
}
rs.goConfig = nil
rs.primitive.SetText("false")
ok, err := rs.isPrimativeGoMod()
if err != nil {
// this means this repo does not depend on any other package
log.Info("PRIMATIVE repo:", rs.String(), "err =", err)
return false, err
}
if ok {
// this means the repo is primitive so there is no go.sum
rs.primitive.SetText("true")
return true, nil
}
// this should never happen
return false, nil
}
func (rs *RepoStatus) IsReleased() bool {
if rs.GetTargetVersion() == rs.GetCurrentVersion() {
return true
}
return false
}

507
merge.go
View File

@ -1,507 +0,0 @@
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(REPO, rs.Name(), "looking for branch:", apple)
for name, branch := range rs.gitConfig.branches {
if name == apple {
// found the branch!
log.Log(REPO, " ", name, "remote:", branch.remote, "merge", branch.merge)
cmd := []string{"git", "fetch", branch.remote, apple + ":" + apple}
log.Log(REPO, "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) IncrementMinorVersion(reason string) {
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)
oldb += 1
oldc = 0
newa := strconv.Itoa(olda)
newb := strconv.Itoa(oldb)
newc := strconv.Itoa(oldc)
rs.SetVersion(newa, newb, newc, reason)
}
func (rs *RepoStatus) IncrementRevisionVersion(reason string) {
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)
oldc += 1
newa := strconv.Itoa(olda)
newb := strconv.Itoa(oldb)
newc := strconv.Itoa(oldc)
rs.SetVersion(newa, newb, newc, 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"))
}
func (rs *RepoStatus) IsCorrectMode(mode string) bool {
switch mode {
case "master":
if rs.GetCurrentBranchName() == rs.GetMasterBranchName() {
return true
} else {
return false
}
case "devel":
if rs.GetCurrentBranchName() == rs.GetDevelBranchName() {
return true
} else {
return false
}
case "user":
if rs.GetCurrentBranchName() == rs.GetUserBranchName() {
return true
} else {
return false
}
}
return false
}

View File

@ -1,42 +0,0 @@
package repostatus
import (
"go.wit.com/gui"
// "go.wit.com/gui/gui"
)
// this is experiemental work on making 'View's or Table Row's
// this may or may not be a good idea
// returns a widget of the last tag that acts as a mirror
func (rs *RepoStatus) MirrorLastTag() *gui.Node {
return rs.lasttag.MirrorValue()
}
func (rs *RepoStatus) MirrorTargetVersion() *gui.Node {
return rs.targetReleaseVersion.MirrorValue()
}
func (rs *RepoStatus) MirrorCurrentVersion() *gui.Node {
return rs.currentVersion.MirrorValue()
}
func (rs *RepoStatus) MirrorCurrentName() *gui.Node {
return rs.currentBranch.MirrorValue()
}
func (rs *RepoStatus) MirrorGitState() *gui.Node {
return rs.gitState.MirrorValue()
}
func (rs *RepoStatus) MirrorMasterVersion() *gui.Node {
return rs.mainBranchVersion.MirrorValue()
}
func (rs *RepoStatus) MirrorDevelVersion() *gui.Node {
return rs.develBranchVersion.MirrorValue()
}
func (rs *RepoStatus) MirrorUserVersion() *gui.Node {
return rs.userBranchVersion.MirrorValue()
}

150
new.go
View File

@ -1,150 +0,0 @@
package repostatus
import (
"errors"
"os"
"path/filepath"
"strings"
"go.wit.com/lib/gadgets"
"go.wit.com/log"
)
var windowMap map[string]*RepoStatus
func init() {
windowMap = make(map[string]*RepoStatus)
}
// deprecate this
func ListAllOld() {
for path, rs := range windowMap {
log.Warn(rs.GetMasterVersion(), path)
}
}
// returns the object for the path
// deprecate this
func FindPathOld(path string) *RepoStatus {
if windowMap[path] == nil {
log.Log(INFO, "FindPath() not initialized yet", path)
return nil
}
return windowMap[path]
}
// makes a window of the status of the repo
// don't worry, you can think of it like Sierpinski carpet
// it's doesn't need to be displayed so it'll work fine even in an embedded space
func New(path string) (*RepoStatus, error) {
err, r := NewRepoStatusWindow(path)
return r, err
}
func NewRepoStatusWindow(path string) (error, *RepoStatus) {
var realpath string
var isGoLang bool = false
if windowMap[path] == nil {
log.Log(INFO, "NewRepoStatusWindow() adding new", path)
} else {
log.Warn("This already exists for path", path)
log.Warn("should return windowMap[path] here")
return nil, windowMap[path]
}
homeDir, err := os.UserHomeDir()
if err != nil {
log.Log(WARN, "Error getting home directory:", err)
return err, nil
}
goSrcDir := filepath.Join(homeDir, "go/src")
rs := &RepoStatus{
ready: false,
}
// allow arbitrary paths, otherwise, assume the repo is in ~/go/src
if strings.HasPrefix(path, "/") {
realpath = path
} else if strings.HasPrefix(path, "~") {
// TODO: example this to homedir
tmp := strings.TrimPrefix(path, "~")
realpath = filepath.Join(homeDir, tmp)
} else {
realpath = filepath.Join(goSrcDir, path)
isGoLang = true
}
if !IsDirectory(realpath) {
log.Log(REPOWARN, "directory doesn't exist", realpath)
// directory doesn't exist. exit with nil and error nil
return errors.New(realpath + " does not exist"), nil
}
filename := filepath.Join(realpath, ".git/config")
_, err = os.Open(filename)
if err != nil {
// log.Log(WARN, "Error reading .git/config:", filename, err)
// log.Log(WARN, "TODO: find .git/config in parent directory")
return err, nil
}
rs.tags = make(map[string]string)
rs.window = gadgets.RawBasicWindow("GO Repo Details " + path)
rs.window.Horizontal()
rs.window.Make()
basebox := rs.window.Box()
group := basebox.NewGroup("stuff")
primarybox := group.Box()
primarybox.Horizontal()
box2 := group.Box()
rs.ready = true
rs.window.Custom = func() {
rs.Hide()
log.Warn("repostatus user closed the window()")
}
// display the status of the git repository
rs.drawGitStatus(primarybox)
// display the git branches and options
rs.makeBranchesBox(primarybox)
// show standard git commit and merge controls
rs.drawGitCommands(primarybox)
// save ~/go/src & the whole path strings
rs.path.SetValue(path)
rs.goSrcPath.SetValue(goSrcDir)
rs.realPath.SetValue(realpath)
// add all the tags
rs.makeTagBox(box2)
rs.readGitConfig()
rs.readOnly.SetValue("true")
// ignore everything else for now
// todo: move this logic to cfgfile.go
if strings.HasPrefix(path, "go.wit.com") {
rs.readOnly.SetValue("false")
}
if strings.HasPrefix(path, "git.wit.org") {
rs.readOnly.SetValue("false")
}
// tries 'master', 'main', etc.
rs.guessMainWorkingName()
// tries 'devel', etc
rs.guessDevelWorkingName()
// sets this to os.Username
rs.setUserWorkingName()
if isGoLang {
rs.isGoLang.SetText("true")
rs.goPath.SetText(path)
}
windowMap[path] = rs
return nil, rs
}

View File

@ -1,41 +0,0 @@
package repostatus
import "go.wit.com/log"
// reverts master to devel
// used in the unwind process of making GUI releases
func (rs *RepoStatus) RevertMasterToDevel() bool {
if rs.CheckDirty() {
log.Info("sorry, it's still dirty")
return false
}
curName := rs.GetCurrentBranchName()
dName := rs.GetDevelBranchName()
mName := rs.GetMasterBranchName()
if curName != mName {
log.Info("repo is not working from main branch", curName, "!=", mName)
return false
}
log.Info("reset master to devel", curName, rs.String())
var all [][]string
all = append(all, []string{"git", "checkout", dName}) // switch to the devel branch
all = append(all, []string{"git", "branch", "-D", mName})
all = append(all, []string{"git", "branch", mName}) // make a master branch based on devel
all = append(all, []string{"git", "checkout", mName})
all = append(all, []string{"git", "push", "--set-upstream", "--force", "origin", mName})
// don't do anything with tags here
// all = append(all, []string{"git", "tag", "--delete", release.version.String()})
// all = append(all, []string{"git", "push", "--delete", "origin", release.version.String()})
if rs.DoAll(all) {
log.Info("EVERYTHING OK. RERELEASED", rs.String())
return true
}
log.Info("SOMETHING FAILED")
return false
}

View File

@ -3,22 +3,36 @@ package repostatus
import (
"go.wit.com/gui"
"go.wit.com/lib/gadgets"
"go.wit.com/lib/protobuf/gitpb"
)
type RepoStatus struct {
ready bool
changed bool // keeps track of changes that might have happened
changes string
tags map[string]string
// tags map[string]string
InitOk bool // it takes a second or so to init these
pb *gitpb.Repo // the protobuf
// used to temporarily tell the automation tools to
// try to ignore this repo's changes and state
// specifically when doing formal releases, sometimes
// some repos are in flux and can't be changed. This
// means attempt to overlook that situation.
Whitelist bool
window *gadgets.BasicWindow // the main window for this repo
Tags *GitTagBox // a box of all the git tags
dirtyLabel *gadgets.OneLiner
dirtyList string // the output from git status --porcelain
readOnly *gadgets.OneLiner
gitState *gadgets.OneLiner
primitive *gadgets.OneLiner
private *gadgets.OneLiner
primitive *gadgets.OneLiner // aka: doesn't have a go.sum file
private *gadgets.OneLiner // it's not possible to publish this to pkg.go.dev
protobuf *gadgets.OneLiner // is this repo a protobuf repo?
path *gadgets.OneLiner
goSrcPath *gadgets.OneLiner
@ -60,8 +74,8 @@ type RepoStatus struct {
speed *gadgets.OneLiner
speedActual *gadgets.OneLiner
gitConfig *GitConfig
goConfig GoConfig
// gitConfig *GitConfig
// goConfig GoConfig
switchBranchB *gui.Node
targetBranch *gui.Node

View File

@ -1,14 +1,15 @@
package repostatus
import (
"errors"
"path/filepath"
"regexp"
"slices"
"strings"
"sync"
"time"
"go.wit.com/gui"
"go.wit.com/lib/gui/shell"
"go.wit.com/log"
)
@ -44,14 +45,14 @@ type GitTagBox struct {
tags []*Tag
}
func (rs *RepoStatus) makeTagBox(box *gui.Node) {
func (rs *RepoStatus) makeTagBox(box *gui.Node) error {
if rs.Tags != nil {
log.Log(WARN, "already scanned tags")
return
return errors.New("already scanned tags")
}
tagB := new(GitTagBox)
rs.Tags = tagB
tagB.group = box.NewGroup(".git tags for " + rs.String())
tagB.group = box.NewGroup(".git tags for " + rs.Path())
// tagB.group.NewButton("prune tags", func() {
// tagB.Prune()
@ -69,14 +70,16 @@ func (rs *RepoStatus) makeTagBox(box *gui.Node) {
}
}
tagB.group.NewButton("delete all", func() {
for i, t := range tagB.tags {
if t.hidden {
// log.Info("tag is hidden", i, t.tag.String())
continue
/*
for i, t := range tagB.tags {
if t.hidden {
// log.Info("tag is hidden", i, t.tag.String())
continue
}
log.Info("tag is shown", i, t.tag.String())
// rs.DeleteTag(t)
}
log.Info("tag is shown", i, t.tag.String())
rs.DeleteTag(t)
}
*/
})
grid := tagB.group.NewGrid("tags", 0, 0)
@ -86,66 +89,43 @@ func (rs *RepoStatus) makeTagBox(box *gui.Node) {
grid.NewLabel("ref")
grid.NewLabel("date")
grid.NewLabel("release subject")
// works like a typerwriter
grid.NextRow()
grid.NextRow() // works like a typerwriter newline
// git tag --list --sort=taggerdate
// git for-each-ref --sort=taggerdate --format '%(tag) %(*objectname) %(taggerdate)'
// git rev-parse HEAD
// if last tag == HEAD, then remove it
loop := rs.pb.Tags.SortByAge()
for loop.Scan() {
tag := loop.Next()
tags := []string{"%(objectname)", "%(creatordate)", "%(*authordate)", "%(refname)", "%(subject)"}
format := strings.Join(tags, "_,,,_")
cmd := []string{"git", "for-each-ref", "--sort=taggerdate", "--format", format}
// log.Info("RUNNING:", strings.Join(cmd, " "))
err, output := rs.RunCmd(cmd)
if err != nil {
output = "git error_,,,_a_,,,_b_,,,c"
}
lines := strings.Split(output, "\n")
// reverse the git order
slices.Reverse(lines)
tagB.tags = make([]*Tag, 0)
for i, line := range lines {
var parts []string
parts = make([]string, 0)
parts = strings.Split(line, "_,,,_")
if len(parts) != 5 {
log.Info("tag error:", i, parts)
continue
}
// log.Info("found tag:", i, parts)
rTag := new(Tag)
rTag.tag = grid.NewLabel(parts[3])
rTag.ref = grid.NewEntrybox(parts[0])
rTag.tag = grid.NewLabel(tag.GetRefname())
rTag.ref = grid.NewEntrybox(tag.GetHash())
_, stamp, dur := getGitDateStamp(parts[1])
rTag.date = grid.NewLabel(stamp)
ctime := tag.GetAuthordate().AsTime()
dur := shell.GetDurationStamp(ctime)
rTag.date = grid.NewLabel(ctime.Format("YYYY/MM/DD"))
rTag.duration = grid.NewLabel(dur)
rTag.subject = grid.NewLabel(parts[4])
rTag.subject = grid.NewLabel(tag.GetSubject())
rTag.deleteB = grid.NewButton("delete", func() {
tagversion := parts[0]
log.Info("remove tag", tagversion)
var all [][]string
all = append(all, []string{"git", "tag", "--delete", tagversion})
all = append(all, []string{"git", "push", "--delete", "origin", tagversion})
/*
tagversion := tag.GetRefname()
log.Info("remove tag", tagversion)
var all [][]string
all = append(all, []string{"git", "tag", "--delete", tagversion})
all = append(all, []string{"git", "push", "--delete", "origin", tagversion})
if rs.DoAll(all) {
log.Info("TAG DELETED", rs.String(), tagversion)
} else {
log.Info("TAG DELETE FAILED", rs.String(), tagversion)
}
if rs.DoAll(all) {
log.Info("TAG DELETED", rs.Path(), tagversion)
} else {
log.Info("TAG DELETE FAILED", rs.Path(), tagversion)
}
*/
})
tagB.tags = append(tagB.tags, rTag)
// works like a typerwriter
grid.NextRow()
}
// reverse the git order
// slices.Reverse(rtags.tags)
return nil
}
func (rtags *GitTagBox) ListAll() []*Tag {
@ -240,29 +220,33 @@ func (rtags *GitTagBox) PruneSmart() {
}
}
/*
// deleting it locally triggers some but when
// the git server was uncontactable (over IPv6 if that matters, probably it doesn't)
// and then the local delete re-added it into the tag
func (rs *RepoStatus) DeleteTag(rt *Tag) {
cmd := []string{"git", "push", "--delete", "origin", rt.tag.String()}
log.Info("RUN:", cmd)
err, output := rs.RunCmd(cmd)
if err != nil {
log.Info("cmd failed", err)
r := rs.Run(cmd)
output := strings.Join(r.Stdout, "\n")
if r.Error != nil {
log.Info("cmd failed", r.Error)
log.Info("output:", output)
}
log.Info("output:", output)
cmd = []string{"git", "tag", "--delete", rt.tag.String()}
log.Info("RUN:", cmd)
err, output = rs.RunCmd(cmd)
if err != nil {
log.Info("cmd failed", err)
r = rs.Run(cmd)
output = strings.Join(r.Stdout, "\n")
if r.Error != nil {
log.Info("cmd failed", r.Error)
log.Info("output:", output)
}
log.Info("output:", output)
}
*/
func (rt *Tag) TagString() string {
return rt.tag.String()
@ -351,7 +335,7 @@ func (t *Tag) Name() string {
return t.tag.String()
}
func (t *Tag) getDate() (time.Time, error) {
func (t *Tag) GetDate() (time.Time, error) {
const gitLayout = "Mon Jan 2 15:04:05 2006 -0700"
tagTime, err := time.Parse(gitLayout, t.date.String())
@ -375,7 +359,7 @@ func (rs *RepoStatus) NewestTag() *Tag {
allTags = append(allTags, junk...)
for _, t := range allTags {
mu.Lock()
if tagTime, err = t.getDate(); err != nil {
if tagTime, err = t.GetDate(); err != nil {
mu.Unlock()
continue
}

View File

@ -1,19 +0,0 @@
package repostatus
import (
"time"
)
// timeFunction takes a function as an argument and returns the execution time.
func timeFunction(f func()) time.Duration {
startTime := time.Now() // Record the start time
f() // Execute the function
return time.Since(startTime) // Calculate the elapsed time
}
func (ls *RepoStatus) SetSpeedActual(s string) {
if !ls.Ready() {
return
}
ls.speedActual.SetValue(s)
}

451
unix.go
View File

@ -1,451 +0,0 @@
package repostatus
import (
"errors"
"fmt"
"io/ioutil"
"os"
"os/exec"
"os/user"
"path/filepath"
"regexp"
"strconv"
"strings"
"time"
"go.wit.com/lib/gui/shell"
"go.wit.com/log"
)
func run(path string, thing string, cmdline string) string {
parts := strings.Split(cmdline, " ")
// Create the command
cmd := exec.Command(thing, parts...)
// Set the working directory
cmd.Dir = path
// Execute the command
output, err := cmd.CombinedOutput()
tmp := string(output)
tmp = strings.TrimSpace(tmp)
if err != nil {
log.Log(WARN, "run()", path, thing, cmdline, "=", tmp)
log.Error(err, "cmd error'd out", parts)
return ""
}
// Print the output
log.Log(INFO, "run()", path, thing, cmdline, "=", tmp)
return tmp
}
// goes in one directory so it gets remote branch names
func listFiles(directory string) []string {
var files []string
fileInfo, err := os.ReadDir(directory)
if err != nil {
log.Error(err)
return nil
}
for _, file := range fileInfo {
if file.IsDir() {
dirname := file.Name()
newdir, _ := os.ReadDir(directory + "/" + dirname)
for _, file := range newdir {
if !file.IsDir() {
files = append(files, dirname+"/"+file.Name())
}
}
} else {
files = append(files, file.Name())
}
}
return files
}
/*
// string handling examples that might be helpful for normalizeInt()
isAlpha := regexp.MustCompile(`^[A-Za-z]+$`).MatchString
for _, username := range []string{"userone", "user2", "user-three"} {
if !isAlpha(username) {
log.Log(GUI, "%q is not valid\n", username)
}
}
const alpha = "abcdefghijklmnopqrstuvwxyz"
func alphaOnly(s string) bool {
for _, char := range s {
if !strings.Contains(alpha, strings.ToLower(string(char))) {
return false
}
}
return true
}
*/
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(WARN, "normalizeVersion() regexp.Compile() ERROR =", err)
return parts[0]
}
clean := reg.ReplaceAllString(parts[0], "")
log.Log(INFO, "normalizeVersion() s =", clean)
return clean
}
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]
}
}
func (rs *RepoStatus) RunCmdEcho(parts []string) (error, string) {
log.Info("RunCmdEcho()", parts)
return rs.RunCmd(parts)
}
func (rs *RepoStatus) RunCmd(parts []string) (error, string) {
path := rs.realPath.String()
err, _, output := shell.RunCmd(path, parts)
if err != nil {
log.Log(WARN, "cmd:", parts)
log.Log(WARN, "ouptput:", output)
log.Log(WARN, "failed with error:", err)
}
return err, output
}
// temp hack. fix this
func runCmd(path string, parts []string) (error, bool, string) {
return shell.RunCmd(path, parts)
}
func RunCmd(workingpath string, parts []string) (error, bool, string) {
if len(parts) == 0 {
log.Warn("command line was empty")
return errors.New("empty"), false, ""
}
if parts[0] == "" {
log.Warn("command line was empty")
return errors.New("empty"), false, ""
}
thing := parts[0]
parts = parts[1:]
log.Log(INFO, "working path =", workingpath, "thing =", thing, "cmdline =", parts)
// Create the command
cmd := exec.Command(thing, parts...)
// Set the working directory
cmd.Dir = workingpath
// Execute the command
output, err := cmd.CombinedOutput()
if err != nil {
if thing == "git" {
log.Log(INFO, "git ERROR. maybe okay", workingpath, "thing =", thing, "cmdline =", parts)
log.Log(INFO, "git ERROR. maybe okay err =", err)
if err.Error() == "exit status 1" {
log.Log(INFO, "git ERROR. normal exit status 1")
if parts[0] == "diff-index" {
log.Log(INFO, "git normal diff-index when repo dirty")
return nil, false, "git diff-index exit status 1"
}
}
}
log.Log(WARN, "ERROR working path =", workingpath, "thing =", thing, "cmdline =", parts)
log.Log(WARN, "ERROR working path =", workingpath, "thing =", thing, "cmdline =", parts)
log.Log(WARN, "ERROR working path =", workingpath, "thing =", thing, "cmdline =", parts)
log.Error(err)
log.Warn("output was", string(output))
log.Warn("cmd exited with error", err)
// panic("fucknuts")
return err, false, string(output)
/* todo: see if there is a way to get the exit value
// The command failed (non-zero exit status)
if exitErr, ok := err.(*exec.ExitError); ok {
// Assert that it is an exec.ExitError and get the exit code
if status, ok := exitErr.Sys().(syscall.WaitStatus); ok {
log.Warn("Exit Status: %d\n", status.ExitStatus())
}
} else {
log.Warn("cmd.Run() failed with %s\n", err)
}
*/
}
tmp := string(output)
tmp = strings.TrimSpace(tmp)
// Print the output
return nil, true, tmp
}
// Set the path to the package
func getfiles(pathToPackage string) {
// List files in the directory
err := filepath.Walk(pathToPackage, nil) // compiles but crashes
if err == nil {
log.Log(INFO, "directory ok", pathToPackage)
} else {
log.Warn("directory wrong", pathToPackage)
}
}
func IsDirectory(path string) bool {
info, err := os.Stat(path)
if err != nil {
return false
}
return info.IsDir()
}
func (rs *RepoStatus) Exists(filename string) bool {
usr, err := user.Current()
if err != nil {
log.Error(err, "Exists() error: could not determine what your username is")
return false
}
testf := filepath.Join(usr.HomeDir, "go/src/", rs.String(), filename)
if Exists(testf) {
return true
}
return false
}
func (rs *RepoStatus) mtime(filename string) (time.Time, error) {
pathf := filepath.Join(rs.Path(), filename)
statf, err := os.Stat(pathf)
if err == nil {
return statf.ModTime(), nil
}
log.Log(REPOWARN, "mtime() error", pathf, err)
return time.Now(), err
}
// returns true if the file exists
func Exists(file string) bool {
_, err := os.Stat(file)
if err != nil {
return false
}
return true
}
func readFileToString(filename string) (string, error) {
data, err := ioutil.ReadFile(filename)
if err != nil {
return "", err
}
return strings.TrimSpace(string(data)), nil
}
// converts a git for-each-ref date. "Wed Feb 7 10:13:38 2024 -0600"
func getGitDateStamp(gitdefault string) (time.Time, string, string) {
// now := time.Now().Format("Wed Feb 7 10:13:38 2024 -0600")
const gitLayout = "Mon Jan 2 15:04:05 2006 -0700"
tagTime, err := time.Parse(gitLayout, gitdefault)
if err != nil {
log.Warn("GOT THIS IN PARSE AAA." + gitdefault + ".AAA")
log.Warn(err)
return time.Now(), "Feb 1 12:34:56 1978 -0600", ""
}
return tagTime, gitdefault, getDurationStamp(tagTime)
}
func getRawDateStamp(raw string) (time.Time, string, string) {
parts := strings.Split(raw, " ")
if len(parts) == 0 {
// raw was blank here
// return "Jan 4 1977", "40y" // eh, why not. it'll be easy to grep for this
return time.Now(), "Jan 4 1977", "40y" // eh, why not. it'll be easy to grep for this
}
i, err := strconv.ParseInt(parts[0], 10, 64) // base 10 string, return int64
if err != nil {
log.Warn("Error converting timestamp:", raw)
log.Warn("Error converting timestamp err =", err)
return time.Now(), "", ""
}
// Parse the Unix timestamp into a time.Time object
gitTagDate := time.Unix(i, 0)
return gitTagDate, gitTagDate.UTC().Format("2006/01/02 15:04:05 UTC"), getDurationStamp(gitTagDate)
}
func getDurationStamp(t time.Time) string {
// Get the current time
currentTime := time.Now()
// Calculate the duration between t current time
duration := currentTime.Sub(t)
return formatDuration(duration)
}
func formatDuration(d time.Duration) string {
seconds := int(d.Seconds()) % 60
minutes := int(d.Minutes()) % 60
hours := int(d.Hours()) % 24
days := int(d.Hours()) / 24
years := int(d.Hours()) / (24 * 365)
result := ""
if years > 0 {
result += fmt.Sprintf("%dy ", years)
return result
}
if days > 0 {
result += fmt.Sprintf("%dd ", days)
return result
}
if hours > 0 {
result += fmt.Sprintf("%dh ", hours)
return result
}
if minutes > 0 {
result += fmt.Sprintf("%dm ", minutes)
return result
}
if seconds > 0 {
result += fmt.Sprintf("%ds", seconds)
}
return result
}
func (rs *RepoStatus) XtermNohup(cmdline string) {
shell.XtermCmd(rs.Path(), []string{cmdline})
}
func (rs *RepoStatus) Xterm(cmdline string) {
shell.XtermCmd(rs.Path(), []string{cmdline})
}
func (rs *RepoStatus) XtermWait(cmdline string) {
shell.XtermCmdWait(rs.Path(), []string{cmdline})
}
/*
func (rs *RepoStatus) XtermNohup(args []string) {
var argsX = []string{"xterm", "-geometry", "120x40"}
argsX = append(argsX, "-e", "bash", "-c")
argsX = append(argsX, args...)
log.Info("xterm cmd=", argsX)
// set less to not exit on small diff's
os.Setenv("LESS", "-+F -+X -R")
cmd := exec.Command("nohup", argsX...)
path := rs.realPath.String()
cmd.Dir = path
log.Info("path =", path)
log.Info("cmd =", strings.Join(args, " "))
if err := cmd.Run(); err != nil {
log.Info("xterm.Run() failed")
log.Info("path =", path)
log.Info("cmd =", argsX)
} else {
log.Info("xterm.Run() worked")
log.Info("path =", path)
log.Info("cmd =", argsX)
}
}
*/
/*
func (rs *RepoStatus) Xterm(args []string) {
var argsX = []string{"-geometry", "120x40"}
argsX = append(argsX, "-e", "bash", "-c")
argsX = append(argsX, args...)
log.Info("xterm cmd=", argsX)
// set less to not exit on small diff's
os.Setenv("LESS", "-+F -+X -R")
cmd := exec.Command("xterm", argsX...)
path := rs.realPath.String()
cmd.Dir = path
if err := cmd.Run(); err != nil {
log.Info("xterm.Run() failed")
log.Info("path =", path)
log.Info("cmd = xterm", argsX)
} else {
log.Info("xterm.Run() worked")
log.Info("path =", path)
log.Info("cmd = xterm", argsX)
}
}
*/
/*
func (rs *RepoStatus) XtermHold(args []string) {
var argsX = []string{"-hold", "-geometry", "120x40"}
tmp := strings.Join(args, " ") + ";bash"
argsX = append(argsX, "-e", "bash", "-c", tmp)
argsX = append(argsX, args...)
log.Info("xterm cmd=", argsX)
// set less to not exit on small diff's
os.Setenv("LESS", "-+F -+X -R")
cmd := exec.Command("xterm", argsX...)
path := rs.realPath.String()
cmd.Dir = path
if err := cmd.Run(); err != nil {
log.Info("xterm.Run() failed")
log.Info("path =", path)
log.Info("cmd = xterm", argsX)
} else {
log.Info("xterm.Run() worked")
log.Info("path =", path)
log.Info("cmd = xterm", argsX)
}
}
*/
func (rs *RepoStatus) XtermBash(args []string) {
var argsX = []string{"-geometry", "120x40"}
tmp := strings.Join(args, " ") + ";bash"
argsX = append(argsX, "-e", "bash", "-c", tmp)
argsX = append(argsX, args...)
log.Info("xterm cmd=", argsX)
// set less to not exit on small diff's
os.Setenv("LESS", "-+F -+X -R")
cmd := exec.Command("xterm", argsX...)
path := rs.realPath.String()
cmd.Dir = path
if err := cmd.Run(); err != nil {
log.Log(WARN, "xterm.Run() failed")
log.Log(WARN, "path =", path)
log.Log(WARN, "cmd = xterm", argsX)
} else {
log.Log(WARN, "xterm.Run() worked")
log.Log(WARN, "path =", path)
log.Log(WARN, "cmd = xterm", argsX)
}
}
func (rs *RepoStatus) DoAll(all [][]string) bool {
for _, cmd := range all {
log.Log(WARN, "doAll() RUNNING: cmd =", cmd)
err, out := rs.RunCmd(cmd)
if err != nil {
log.Log(WARN, "doAll() err =", err)
log.Log(WARN, "doAll() out =", out)
return false
}
}
return true
}

179
update.go
View File

@ -2,163 +2,48 @@ package repostatus
import (
"errors"
"fmt"
"strings"
"time"
"go.wit.com/log"
)
func (rs *RepoStatus) gitBranchAll() {
err, out := rs.RunCmd([]string{"git", "branch", "--all"})
log.Log(WARN, "git branch failed string =", rs.String())
log.Log(WARN, "git branch failed realpath =", rs.realPath.String())
if err != nil {
log.Log(WARN, "git branch failed string =", rs.String())
log.Log(WARN, "git branch failed realpath =", rs.realPath.String())
return
}
all := strings.Split(out, "\n")
for _, s := range all {
// log.Log(WARN, "found branch", i, s)
rs.targetBranch.AddText(s)
}
// i := len(all)
// log.Log(WARN, "branch count =", i)
}
func (rs *RepoStatus) updateNew() {
if !rs.Ready() {
log.Log(WARN, "can't update yet. ready is false")
log.Error(errors.New("Update() is not ready yet"))
return
}
// store the current checked out branch name and version
rs.checkCurrentBranchName()
rs.checkCurrentBranchVersion()
// read in the tags
rs.populateTags()
// record if the repo is dirty
rs.CheckDirty()
// store the last tag version
rs.setLastTagVersion()
// store the master branch version
mName := rs.GetMasterBranchName()
out, _ := rs.gitDescribeByName(mName)
rs.setMasterVersion(out)
// store the devel branch version
dName := rs.GetDevelBranchName()
if dName == "" {
rs.setDevelVersion("")
} else {
out, _ = rs.gitDescribeByName(dName)
rs.setDevelVersion(out)
}
// store the user branch version
uName := rs.GetUserBranchName()
if uName == "" {
rs.setUserVersion("")
} else {
out, _ = rs.gitDescribeByName(uName)
rs.setUserVersion(out)
}
// populates a string into the rs.gitState widget
// todo: make the values from this function a bit cleaner
rs.CheckGitState()
}
func (rs *RepoStatus) Update() {
if !rs.Ready() {
log.Log(WARN, "can't update yet. ready is false")
log.Error(errors.New("Update() is not ready yet"))
return
}
log.Log(INFO, "Update() START")
duration := timeFunction(func() {
rs.updateNew()
})
rs.setSpeed(duration)
log.Log(INFO, "Update() END")
pb := rs.pb
// store the current checked out branch name and version
rs.checkCurrentBranchName()
out := rs.pb.GetCurrentVersion()
rs.currentVersion.SetValue(out)
// read in the tags
// rs.populateTags()
// record if the repo is dirty
pb.CheckDirty()
// display the last tag version
name := rs.pb.GetLastTagVersion()
rs.lasttag.SetText(name)
// store the master branch version
ver := pb.GetMasterVersion()
rs.mainBranchVersion.SetValue(ver)
rs.develBranchVersion.SetValue(pb.GetDevelVersion())
rs.userBranchVersion.SetValue(pb.GetUserVersion())
// populates a string into the rs.gitState widget
// todo: make the values from this function a bit cleaner
rs.CheckGitState()
}
func (rs *RepoStatus) setSpeed(duration time.Duration) {
s := fmt.Sprint(duration)
if rs.speedActual == nil {
log.Log(WARN, "rs.speedActual == nil")
return
}
rs.speedActual.SetValue(s)
if duration > 200*time.Millisecond {
rs.speed.SetValue("SLOW")
} else if duration > 50*time.Millisecond {
rs.speed.SetValue("OK")
} else {
rs.speed.SetValue("FAST")
}
}
// disable all things besides Update() button
func (rs *RepoStatus) DisableEverything() {
log.Log(INFO, "DisableEverything()")
// choosing a major, minor or revision
rs.major.Disable()
rs.minor.Disable()
rs.revision.Disable()
// disable adding a tag message
rs.versionMessage.Disable()
// disable the merge devel to master button
rs.develMergeB.Disable()
// disable the tag a new version button
rs.releaseVersion.Disable()
}
// this means devel needs to be merged to master
func (rs *RepoStatus) EnableMergeDevel() {
rs.DisableEverything()
rs.develMergeB.Enable()
}
func (rs *RepoStatus) Disable() {
rs.window.Disable()
}
func (rs *RepoStatus) Enable() {
rs.window.Enable()
}
// this means you need to release a new version of the master repository
func (rs *RepoStatus) EnableSelectTag() {
rs.DisableEverything()
// choosing a major, minor or revision
rs.major.Enable()
rs.minor.Enable()
rs.revision.Enable()
// disable adding a tag message
rs.versionMessage.Enable()
rs.develMergeB.SetLabel("ready to release")
if len(rs.versionMessage.String()) == 0 {
// force there to be a commit message
rs.releaseVersion.Disable()
} else {
rs.generateCmd()
rs.releaseVersion.Enable()
}
func (rs *RepoStatus) CheckGitState() string {
state := rs.pb.GetState()
rs.gitState.SetText(state)
return state
}

127
windowBranches.go Normal file
View File

@ -0,0 +1,127 @@
package repostatus
import (
"go.wit.com/lib/gadgets"
"go.wit.com/lib/protobuf/gitpb"
"go.wit.com/log"
"go.wit.com/gui"
)
type repoBranchesWindow struct {
repo *gitpb.Repo // the repo protobuf
win *gadgets.BasicWindow // the patches window
stack *gui.Node // the top box set as vertical
//shelf *gui.Node // the first box in the stack, set as horizontal
//grid *gui.Node // the list of available patches
//setgrid *gui.Node // the list of each patchset
}
// todo: autogenerate these or make them standared 'gui' package functions
// make this an go interface somehow
// is the window hidden right now?
func (w *repoBranchesWindow) Hidden() bool {
return w.win.Hidden()
}
// switches between the window being visable or hidden on the desktop
func (w *repoBranchesWindow) Toggle() {
if w.Hidden() {
w.Show()
} else {
w.Hide()
}
}
// hides the window completely
func (w *repoBranchesWindow) Show() {
w.win.Show()
}
func (w *repoBranchesWindow) Hide() {
w.win.Hide()
}
// should be the first box/widget in the window
// greys out the window to the user
func (w *repoBranchesWindow) Disable() {
w.stack.Disable()
}
func (w *repoBranchesWindow) Enable() {
w.stack.Enable()
}
// you can only have one of these
func MakeRepoBranchesWindow(repo *gitpb.Repo) *repoBranchesWindow {
pw := new(repoBranchesWindow)
// sync.Once()
pw.win = gadgets.RawBasicWindow("Branches for " + repo.GetGoPath())
pw.win.Make()
pw.stack = pw.win.Box().NewBox("bw vbox", false)
// me.reposwin.Draw()
pw.win.Custom = func() {
log.Info("Got close. setting win.Hide()")
// sets the hidden flag to false so Toggle() works
pw.win.Hide()
}
grid := pw.stack.NewGrid("", 0, 0)
grid.NewGroup("Branches")
grid.NextRow()
grid.NewGroup("Name")
grid.NewGroup("Forge use")
grid.NewGroup("Ref Version")
grid.NewGroup("Type")
grid.NewGroup("Hash")
grid.NextRow()
/*
for _, b := range repo.GetLocalBranches() {
hash := repo.GetBranchHash(b)
grid.NewLabel(b)
grid.NewLabel(repo.GetBranchVersion(b))
if s, err := repo.GetHashName(hash); err == nil {
grid.NewLabel(s)
} else {
grid.NewLabel("err")
}
grid.NewLabel("local")
grid.NewLabel(hash)
grid.NewButton("Delete", func() {
repo.RunVerbose([]string{"git", "branch", "-D", b})
})
grid.NextRow()
}
for _, b := range repo.GetRemoteBranches() {
hash := repo.GetBranchHash(b)
grid.NewLabel(b)
forgeuse := repo.GetBranchVersion(b)
grid.NewLabel(forgeuse)
if s, err := repo.GetHashName(hash); err == nil {
grid.NewLabel(s)
} else {
grid.NewLabel("")
}
grid.NewLabel("remote")
grid.NewLabel(hash)
if b == "origin/HEAD" || forgeuse == "remote master" {
// can't delete these
} else {
grid.NewButton("Delete Remote", func() {
})
}
grid.NextRow()
}
*/
return pw
}

62
windowMain.go Normal file
View File

@ -0,0 +1,62 @@
package repostatus
import (
"go.wit.com/lib/gadgets"
"go.wit.com/lib/protobuf/gitpb"
"go.wit.com/log"
)
var windowMap map[string]*RepoStatus
func init() {
windowMap = make(map[string]*RepoStatus)
}
// makes a window of the status of the repo
// don't worry, you can think of it like Sierpinski carpet
// it's doesn't need to be displayed so it'll work fine even in an embedded space
func NewRepoStatusWindow(repo *gitpb.Repo) (*RepoStatus, error) {
path := repo.GetGoPath()
if windowMap[path] == nil {
log.Log(INFO, "NewRepoStatusWindow() adding new", path)
} else {
log.Warn("This already exists for path", path)
log.Warn("should return windowMap[path] here")
return windowMap[path], nil
}
rs := &RepoStatus{
ready: false,
}
rs.pb = repo
// realpath := repo.FullPath
// isGoLang := true
// rs.tags = make(map[string]string)
rs.window = gadgets.RawBasicWindow("GO Repo Details " + path)
rs.window.Horizontal()
rs.window.Make()
basebox := rs.window.Box()
group := basebox.NewGroup("stuff")
primarybox := group.Box()
primarybox.Horizontal()
// box2 := group.Box()
rs.ready = true
rs.window.Custom = func() {
rs.Hide()
log.Warn("repostatus user closed the window()")
}
// display the status of the git repository
rs.drawGitStatus(primarybox)
// display the git branches and options
rs.makeBranchesBox(primarybox)
// var win *gadgets.BasicWindow
// show standard git commit and merge controls
rs.drawGitCommands(primarybox)
windowMap[path] = rs
return rs, nil
}

216
windowMerge.go Normal file
View File

@ -0,0 +1,216 @@
package repostatus
import (
"go.wit.com/lib/gadgets"
"go.wit.com/lib/protobuf/gitpb"
"go.wit.com/log"
"go.wit.com/gui"
)
type repoMergeWindow struct {
repo *gitpb.Repo // the repo protobuf
win *gadgets.BasicWindow // the patches window
stack *gui.Node // the top box set as vertical
lasttag *gadgets.OneLiner // the last tag version
mainBranchVersion *gadgets.OneLiner // the primary branch version
develBranchVersion *gadgets.OneLiner // the devel branch version
userBranchVersion *gadgets.OneLiner // the user branch version
currentVersion *gadgets.OneLiner // the devel branch version
currentBranch *gadgets.OneLiner // the user branch version
mergeD *gui.Node // the merge button
mergeM *gui.Node // the merge button
}
// todo: autogenerate these or make them standared 'gui' package functions
// make this an go interface somehow
// is the window hidden right now?
func (w *repoMergeWindow) Hidden() bool {
return w.win.Hidden()
}
// switches between the window being visable or hidden on the desktop
func (w *repoMergeWindow) Toggle() {
if w.Hidden() {
w.Show()
} else {
w.Hide()
}
}
// hides the window completely
func (w *repoMergeWindow) Show() {
w.win.Show()
w.Update()
}
func (w *repoMergeWindow) Hide() {
w.win.Hide()
}
// should be the first box/widget in the window
// greys out the window to the user
func (w *repoMergeWindow) Disable() {
w.stack.Disable()
}
func (w *repoMergeWindow) Enable() {
w.stack.Enable()
}
func (w *repoMergeWindow) Update() {
w.lasttag.SetText(w.repo.GetLastTag())
w.mainBranchVersion.SetText(w.repo.GetMasterVersion())
w.develBranchVersion.SetText(w.repo.GetDevelVersion())
w.userBranchVersion.SetText(w.repo.GetUserVersion())
w.currentBranch.SetText(w.repo.GetCurrentBranchName())
w.currentVersion.SetText(w.repo.GetCurrentVersion())
if w.repo.GetCurrentBranchName() == w.repo.GetDevelBranchName() {
w.mergeD.Enable()
} else {
w.mergeD.Disable()
}
if w.repo.GetCurrentBranchName() == w.repo.GetMasterBranchName() {
w.mergeM.Enable()
} else {
w.mergeM.Disable()
}
}
func (rs *RepoStatus) MakeRepoMergeWindow(repo *gitpb.Repo) *repoMergeWindow {
w := new(repoMergeWindow)
w.repo = repo
// sync.Once()
w.win = gadgets.RawBasicWindow("Merge controls for " + repo.GetGoPath())
w.win.Make()
w.stack = w.win.Box().NewBox("bw vbox", false)
// me.reposwin.Draw()
w.win.Custom = func() {
log.Info("Got close. setting win.Hide()")
// sets the hidden flag to false so Toggle() works
w.win.Hide()
}
grid := w.stack.NewGrid("", 0, 0)
grid.NewGroup("Merge Options")
grid.NextRow()
grid.NewButton("checkout user", func() {
w.Disable()
defer w.Enable()
if err := repo.CheckoutUser(); err != nil {
log.Info(repo.GetFullPath(), err)
}
w.repo.Reload()
w.Update()
})
grid.NextRow()
grid.NewButton("checkout devel", func() {
w.Disable()
defer w.Enable()
repo.CheckoutDevel()
w.repo.Reload()
w.Update()
})
w.mergeD = grid.NewButton("merge to devel", func() {
w.Disable()
defer w.Enable()
log.Info("repo:", repo.GetGoPath())
if result, err := repo.MergeToDevel(); err == nil {
log.Warn("THINGS SEEM OK", repo.GetFullPath())
for _, line := range result.Stdout {
log.Warn("stdout:", line)
}
for _, line := range result.Stderr {
log.Warn("stderr:", line)
}
} else {
log.Warn("THINGS FAILED ", repo.GetFullPath())
log.Warn("err", err)
for _, line := range result.Stdout {
log.Warn("stdout:", line)
}
for _, line := range result.Stderr {
log.Warn("stderr:", line)
}
}
w.repo.Reload()
w.Update()
})
grid.NextRow()
grid.NewButton("checkout master", func() {
w.Disable()
defer w.Enable()
repo.CheckoutMaster()
w.repo.Reload()
w.Update()
})
w.mergeM = grid.NewButton("merge to master", func() {
w.Disable()
defer w.Enable()
log.Info("repo:", repo.GetGoPath())
if result, err := repo.MergeToMaster(); err == nil {
log.Warn("THINGS SEEM OK", repo.GetFullPath())
for _, line := range result.Stdout {
log.Warn("stdout:", line)
}
for _, line := range result.Stderr {
log.Warn("stderr:", line)
}
} else {
log.Warn("THINGS FAILED ", repo.GetFullPath())
log.Warn("err", err)
for _, line := range result.Stdout {
log.Warn("stdout:", line)
}
for _, line := range result.Stderr {
log.Warn("stderr:", line)
}
}
w.repo.Reload()
w.Update()
})
grid.NextRow()
w.lasttag = gadgets.NewOneLiner(grid, "last tag") // `progname:"LASTTAG"`
grid.NextRow()
w.mainBranchVersion = gadgets.NewOneLiner(grid, "master") // `progname:"MASTERBRANCH"`
grid.NextRow()
w.develBranchVersion = gadgets.NewOneLiner(grid, "devel") // `progname:"DEVELBRANCH"`
grid.NextRow()
w.userBranchVersion = gadgets.NewOneLiner(grid, "user") // `progname:"USERBRANCH"`
grid.NextRow()
w.currentBranch = gadgets.NewOneLiner(grid, "current branch") // `progname:"CURRENTBRANCH"`
grid.NextRow()
w.currentVersion = gadgets.NewOneLiner(grid, "current version") // `progname:"CURRENTVERSION"`
grid.NextRow()
w.Update()
return w
}
/*
rs.showBranchesButton = newgrid.NewButton("find user and devel", func() {
log.Info("redo this")
})
newgrid.NextRow()
rs.checkBranchesButton = newgrid.NewButton("CheckBranches()", func() {
log.Info("redo this")
})
newgrid.NextRow()
newgrid.NewButton("Revert master to devel", func() {
log.Info("redo this")
})
*/

View File

@ -15,7 +15,7 @@ func (rs *RepoStatus) drawGitCommands(box *gui.Node) {
})
newgrid.NewButton("CheckDirty()", func() {
if rs.CheckDirty() {
if rs.pb.CheckDirty() {
log.Log(WARN, "is dirty")
} else {
log.Log(WARN, "is not dirty")
@ -23,34 +23,34 @@ func (rs *RepoStatus) drawGitCommands(box *gui.Node) {
})
newgrid.NewButton("show .git/config", func() {
if rs.gitConfig == nil {
log.Log(WARN, "Nonexistant or damaged .git/config", rs.String())
if rs.pb.GitConfig == nil {
log.Log(WARN, "Nonexistant or damaged .git/config", rs.Path())
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, remote := range rs.pb.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)
for name, branch := range rs.pb.GitConfig.Branches {
log.Log(WARN, " ", name, "remote:", branch.Remote, "merge", branch.Merge)
}
})
newgrid.NextRow()
newgrid.NewButton("git pull", func() {
rs.GitPull()
rs.pb.GitPull()
})
newgrid.NextRow()
label := "merge " + rs.userWorkingName.String() + " to " + rs.develWorkingName.String()
rs.develMergeB = newgrid.NewButton(label, func() {
rs.Disable()
if rs.MergeUserToDevel() {
if result, err := rs.pb.MergeToDevel(); err == nil {
log.Warn("THINGS SEEM OK fullAutomation() returned true.")
} else {
log.Warn("THINGS FAILED fullAutomation() returned false")
log.Warn("THINGS FAILED fullAutomation() returned false", result.Error)
}
rs.Enable()
})
@ -58,38 +58,39 @@ func (rs *RepoStatus) drawGitCommands(box *gui.Node) {
label = "merge " + rs.develWorkingName.String() + " to " + rs.mainWorkingName.String()
rs.mainMergeB = newgrid.NewButton(label, func() {
rs.Disable()
if rs.MergeDevelToMaster() {
if result, err := rs.pb.MergeToMaster(); err == nil {
log.Warn("THINGS SEEM OK fullAutomation() returned true.")
} else {
log.Warn("THINGS FAILED fullAutomation() returned false")
log.Warn("THINGS FAILED fullAutomation() returned false", result.Error)
}
rs.Enable()
})
newgrid.NewButton("increment version", func() {
rs.IncrementVersion()
log.Info("broken")
// rs.IncrementVersion()
})
newgrid.NextRow()
rs.major = gadgets.NewBasicCombobox(newgrid, "major")
rs.major.Custom = func() {
rs.setTag()
rs.generateCmd()
// rs.setTag()
// rs.generateCmd()
}
// rs.major.Hide()
newgrid.NextRow()
rs.minor = gadgets.NewBasicCombobox(newgrid, "minor")
rs.minor.Custom = func() {
rs.setTag()
rs.generateCmd()
// rs.setTag()
// rs.generateCmd()
}
// rs.minor.Hide()
newgrid.NextRow()
rs.revision = gadgets.NewBasicCombobox(newgrid, "revision")
rs.revision.Custom = func() {
rs.setTag()
rs.generateCmd()
// rs.setTag()
// rs.generateCmd()
}
// rs.revision.Hide()
newgrid.NextRow()
@ -101,7 +102,7 @@ func (rs *RepoStatus) drawGitCommands(box *gui.Node) {
rs.versionMessage = gadgets.NewBasicEntry(newgrid, "tag message")
rs.versionMessage.Custom = func() {
rs.generateCmd()
// rs.generateCmd()
}
// rs.versionMessage.Hide()
newgrid.NextRow()
@ -112,7 +113,7 @@ func (rs *RepoStatus) drawGitCommands(box *gui.Node) {
rs.releaseVersion = newgrid.NewButton("tag and release new version", func() {
rs.Disable()
rs.MergeDevelToMaster()
rs.pb.MergeToMaster()
})
// rs.releaseVersion.Hide()
newgrid.NextRow()

73
windowRepo.go Normal file
View File

@ -0,0 +1,73 @@
package repostatus
import (
"go.wit.com/lib/gadgets"
"go.wit.com/lib/protobuf/gitpb"
"go.wit.com/gui"
)
type repoWindow struct {
repo *gitpb.Repo // the repo protobuf
win *gadgets.BasicWindow // the patches window
stack *gui.Node // the top box set as vertical
//shelf *gui.Node // the first box in the stack, set as horizontal
//grid *gui.Node // the list of available patches
//setgrid *gui.Node // the list of each patchset
}
// todo: autogenerate these or make them standared 'gui' package functions
// make this an go interface somehow
// is the window hidden right now?
func (w *repoWindow) Hidden() bool {
return w.win.Hidden()
}
// switches between the window being visable or hidden on the desktop
func (w *repoWindow) Toggle() {
if w.Hidden() {
w.Show()
} else {
w.Hide()
}
}
// hides the window completely
func (w *repoWindow) Show() {
w.win.Show()
}
func (w *repoWindow) Hide() {
w.win.Hide()
}
// should be the first box/widget in the window
// greys out the window to the user
func (w *repoWindow) Disable() {
w.stack.Disable()
}
func (w *repoWindow) Enable() {
w.stack.Enable()
}
// you can only have one of these
func MakeRepoWindow(repo *gitpb.Repo) *repoWindow {
pw := new(repoWindow)
// sync.Once()
pw.win = gadgets.RawBasicWindow("Patcheset for " + repo.GetGoPath())
pw.win.Make()
pw.stack = pw.win.Box().NewBox("bw vbox", false)
// me.reposwin.Draw()
pw.win.Custom = func() {
// sets the hidden flag to false so Toggle() works
pw.win.Hide()
}
// grid := pw.stack.NewGrid("", 0, 0)
return pw
}