Compare commits
117 Commits
Author | SHA1 | Date |
---|---|---|
Jeff Carr | 9d13c972e4 | |
Jeff Carr | 2866815e3c | |
Jeff Carr | 4c46927bc7 | |
Jeff Carr | a1ce58e9d0 | |
Jeff Carr | 94e98f2145 | |
Jeff Carr | 9358005c9d | |
Jeff Carr | 2e8a1d4793 | |
Jeff Carr | 4ab00cce02 | |
Jeff Carr | a7c5499221 | |
Jeff Carr | 009d8f3b9d | |
Jeff Carr | 55acea0bd7 | |
Jeff Carr | 29545d3f04 | |
Jeff Carr | 5be028858c | |
Jeff Carr | 6b1330d7f3 | |
Jeff Carr | 3ce9f5f773 | |
Jeff Carr | 44ab5deb3f | |
Jeff Carr | 31355467a5 | |
Jeff Carr | e6f883a9b5 | |
Jeff Carr | 8eb7501855 | |
Jeff Carr | 8786690d46 | |
Jeff Carr | b451591006 | |
Jeff Carr | bf2a42ec64 | |
Jeff Carr | 5bc1a24a69 | |
Jeff Carr | 2ce9051921 | |
Jeff Carr | 804acc169a | |
Jeff Carr | 2622e90b1f | |
Jeff Carr | 7d3e4ce84e | |
Jeff Carr | 546ad6a842 | |
Jeff Carr | 54367ddc72 | |
Jeff Carr | 2cdf2c3cda | |
Jeff Carr | f99dc30b68 | |
Jeff Carr | 65a94faa57 | |
Jeff Carr | 412c84fcd9 | |
Jeff Carr | b2d3d13ed9 | |
Jeff Carr | b12bc0a9ec | |
Jeff Carr | 4d2f68606e | |
Jeff Carr | 035b4eb443 | |
Jeff Carr | fc849f6003 | |
Jeff Carr | 9a1347c03f | |
Jeff Carr | b354d7dd27 | |
Jeff Carr | cec5e7f3b4 | |
Jeff Carr | ccee573364 | |
Jeff Carr | ddd95e9afc | |
Jeff Carr | 2a62d23482 | |
Jeff Carr | 28a20e0922 | |
Jeff Carr | 5268267408 | |
Jeff Carr | 1b65474a69 | |
Jeff Carr | 5105bd4a99 | |
Jeff Carr | 359ebce26e | |
Jeff Carr | cd5f1d9d0f | |
Jeff Carr | 5aaf02ee3a | |
Jeff Carr | 70e8c98b1c | |
Jeff Carr | 2a19cd5eef | |
Jeff Carr | e1e81ab2bf | |
Jeff Carr | d16cc92286 | |
Jeff Carr | ae7e9ba42c | |
Jeff Carr | ad21d5d5db | |
Jeff Carr | be73f6af0e | |
Jeff Carr | 1bafc298d3 | |
Jeff Carr | 6a6ebf78b8 | |
Jeff Carr | 4d1301288e | |
Jeff Carr | 0e26f2024a | |
Jeff Carr | 45519f2370 | |
Jeff Carr | 6e7759f570 | |
Jeff Carr | f82743d487 | |
Jeff Carr | c7aaea4ae1 | |
Jeff Carr | 0b4f4d7686 | |
Jeff Carr | bd62a89a67 | |
Jeff Carr | 88ca40bcfa | |
Jeff Carr | 2bc2096e84 | |
Jeff Carr | e6eb92845a | |
Jeff Carr | 3d6002b055 | |
Jeff Carr | 73d711ad2b | |
Jeff Carr | d7e391fed0 | |
Jeff Carr | a223e9f1c3 | |
Jeff Carr | 07a60ffe3c | |
Jeff Carr | f7947b08b6 | |
Jeff Carr | 95fd6ca05a | |
Jeff Carr | d7a0246af9 | |
Jeff Carr | e7a3ef1298 | |
Jeff Carr | b4a571fb70 | |
Jeff Carr | ba4051cb0c | |
Jeff Carr | 2b172338f6 | |
Jeff Carr | b694fc2fe2 | |
Jeff Carr | 35e03959ab | |
Jeff Carr | 49724b16e8 | |
Jeff Carr | 678d6357b1 | |
Jeff Carr | 309cf80e16 | |
Jeff Carr | abb1f0ea21 | |
Jeff Carr | 118825e7a3 | |
Jeff Carr | 3937902a7d | |
Jeff Carr | 08b122ea2c | |
Jeff Carr | 4d665387fe | |
Jeff Carr | dbf10cddf7 | |
Jeff Carr | fae78b1812 | |
Jeff Carr | 1fda646fef | |
Jeff Carr | 78049e664d | |
Jeff Carr | 940096ff40 | |
Jeff Carr | ca09e7cf47 | |
Jeff Carr | a05f6c35ce | |
Jeff Carr | 7e7dbebcee | |
Jeff Carr | 408a400e93 | |
Jeff Carr | 856b479edb | |
Jeff Carr | 7bcbca3fce | |
Jeff Carr | e6cb846ccf | |
Jeff Carr | 318b748509 | |
Jeff Carr | 6d8a49d432 | |
Jeff Carr | 386125826f | |
Jeff Carr | 9147079092 | |
Jeff Carr | 2723e53396 | |
Jeff Carr | 9f26bc2d44 | |
Jeff Carr | 2aed84cf3a | |
Jeff Carr | 45e7aab862 | |
Jeff Carr | a80347531e | |
Jeff Carr | 86136ce615 | |
Jeff Carr | 4beeb0bb13 | |
Jeff Carr | 21546ce2c0 |
|
@ -1 +1,3 @@
|
||||||
*.swp
|
*.swp
|
||||||
|
go.mod
|
||||||
|
go.sum
|
||||||
|
|
4
Makefile
4
Makefile
|
@ -1,7 +1,5 @@
|
||||||
all:
|
all:
|
||||||
@echo
|
GO111MODULE=off go vet
|
||||||
@echo Run: make redomod
|
|
||||||
@echo
|
|
||||||
|
|
||||||
goimports:
|
goimports:
|
||||||
goimports -w *.go
|
goimports -w *.go
|
||||||
|
|
9
args.go
9
args.go
|
@ -12,6 +12,9 @@ var INFO *log.LogFlag
|
||||||
var WARN *log.LogFlag
|
var WARN *log.LogFlag
|
||||||
var CHANGE *log.LogFlag
|
var CHANGE *log.LogFlag
|
||||||
|
|
||||||
|
var REPO *log.LogFlag
|
||||||
|
var REPOWARN *log.LogFlag
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
full := "go.wit.com/lib/gui/repostatus"
|
full := "go.wit.com/lib/gui/repostatus"
|
||||||
short := "repostatus"
|
short := "repostatus"
|
||||||
|
@ -19,4 +22,10 @@ func init() {
|
||||||
INFO = log.NewFlag("INFO", false, full, short, "general repo things")
|
INFO = log.NewFlag("INFO", false, full, short, "general repo things")
|
||||||
WARN = log.NewFlag("WARN", true, full, short, "bad things")
|
WARN = log.NewFlag("WARN", true, full, short, "bad things")
|
||||||
CHANGE = log.NewFlag("CHANGE", true, full, short, "when repo changes")
|
CHANGE = log.NewFlag("CHANGE", true, full, short, "when repo changes")
|
||||||
|
|
||||||
|
full = "go.wit.com/lib/gui/repo"
|
||||||
|
short = "repo"
|
||||||
|
|
||||||
|
REPO = log.NewFlag("REPO", false, full, short, "general repo things")
|
||||||
|
REPOWARN = log.NewFlag("REPOWARN", true, full, short, "repo warnings")
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,71 @@
|
||||||
|
package repostatus
|
||||||
|
|
||||||
|
import (
|
||||||
|
"go.wit.com/gui"
|
||||||
|
"go.wit.com/lib/gadgets"
|
||||||
|
"go.wit.com/log"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (rs *RepoStatus) makeBranchesBox(parent *gui.Node) {
|
||||||
|
rs.gitBranchesGroup = parent.NewGroup("branches") // `progname:"BRANCHES"` // can the toolkits use these for i18n support?
|
||||||
|
newgrid := rs.gitBranchesGroup.NewGrid("gridnuts", 0, 0)
|
||||||
|
|
||||||
|
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")
|
||||||
|
}
|
||||||
|
rs.updateNew()
|
||||||
|
})
|
||||||
|
|
||||||
|
rs.targetBranch = newgrid.NewDropdown() // `progname:"TARGET"`
|
||||||
|
newgrid.NextRow()
|
||||||
|
|
||||||
|
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")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
newgrid.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()
|
||||||
|
})
|
||||||
|
}
|
|
@ -0,0 +1,263 @@
|
||||||
|
package repostatus
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"go.wit.com/lib/gui/shell"
|
||||||
|
"go.wit.com/log"
|
||||||
|
)
|
||||||
|
|
||||||
|
// guess the paths. returns
|
||||||
|
|
||||||
|
// realpath : the actual path on the filesystem
|
||||||
|
// goSrcPath : this could be ~/go/src, or where the go.work file is
|
||||||
|
|
||||||
|
// goPath : go.wit.com/lib/gui/repostatus (for example)
|
||||||
|
// true/false if the repo is a golang repo
|
||||||
|
func guessPaths(path string) (string, string, string, bool, error) {
|
||||||
|
var realpath, goSrcDir string
|
||||||
|
var isGoLang bool = false
|
||||||
|
|
||||||
|
homeDir, err := os.UserHomeDir()
|
||||||
|
if err != nil {
|
||||||
|
log.Log(WARN, "Error getting home directory:", err)
|
||||||
|
return path, realpath, goSrcDir, false, err
|
||||||
|
}
|
||||||
|
goSrcDir = filepath.Join(homeDir, "go/src")
|
||||||
|
|
||||||
|
// allow arbitrary paths, otherwise, assume the repo is in ~/go/src
|
||||||
|
// unless REPO_WORK_PATH was set. to over-ride ~/go/src
|
||||||
|
// todo, look for go.work
|
||||||
|
if os.Getenv("REPO_WORK_PATH") == "" {
|
||||||
|
os.Setenv("REPO_WORK_PATH", goSrcDir)
|
||||||
|
} else {
|
||||||
|
goSrcDir = os.Getenv("REPO_WORK_PATH")
|
||||||
|
}
|
||||||
|
|
||||||
|
// todo: this is dumb
|
||||||
|
if strings.HasPrefix(path, "/") {
|
||||||
|
realpath = path
|
||||||
|
} else if strings.HasPrefix(path, "~") {
|
||||||
|
tmp := strings.TrimPrefix(path, "~")
|
||||||
|
realpath = filepath.Join(homeDir, tmp)
|
||||||
|
} else {
|
||||||
|
realpath = filepath.Join(goSrcDir, path)
|
||||||
|
isGoLang = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if os.Getenv("REPO_AUTO_CLONE") == "true" {
|
||||||
|
err := Clone(goSrcDir, path)
|
||||||
|
if err != nil {
|
||||||
|
// directory doesn't exist. exit with nil and error nil
|
||||||
|
return path, realpath, goSrcDir, false, errors.New("git clone")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !IsDirectory(realpath) {
|
||||||
|
log.Log(REPOWARN, "directory doesn't exist", realpath)
|
||||||
|
// directory doesn't exist. exit with nil and error nil
|
||||||
|
return path, realpath, goSrcDir, false, errors.New(realpath + " does not exist")
|
||||||
|
}
|
||||||
|
|
||||||
|
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 path, realpath, goSrcDir, false, err
|
||||||
|
}
|
||||||
|
return path, realpath, goSrcDir, isGoLang, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: make some config file for things like this
|
||||||
|
// can be used to work around temporary problems
|
||||||
|
func clonePathHack(dirname string, basedir string, gopath string) error {
|
||||||
|
// newdir = helloworld
|
||||||
|
// basedir = /home/jcarr/go/src/go.wit.com/apps
|
||||||
|
// giturl = https://gitea.wit.com/gui/helloworld
|
||||||
|
// func cloneActual(newdir, basedir, giturl string) error {
|
||||||
|
|
||||||
|
switch gopath {
|
||||||
|
case "golang.org/x/crypto":
|
||||||
|
return cloneActual(dirname, basedir, "https://" + "go.googlesource.com/crypto")
|
||||||
|
case "golang.org/x/mod":
|
||||||
|
return cloneActual(dirname, basedir, "https://" + "go.googlesource.com/mod")
|
||||||
|
case "golang.org/x/net":
|
||||||
|
return cloneActual(dirname, basedir, "https://" + "go.googlesource.com/net")
|
||||||
|
case "golang.org/x/sys":
|
||||||
|
return cloneActual(dirname, basedir, "https://" + "go.googlesource.com/sys")
|
||||||
|
case "golang.org/x/sync":
|
||||||
|
return cloneActual(dirname, basedir, "https://" + "go.googlesource.com/sync")
|
||||||
|
case "golang.org/x/term":
|
||||||
|
return cloneActual(dirname, basedir, "https://" + "go.googlesource.com/term")
|
||||||
|
case "golang.org/x/text":
|
||||||
|
return cloneActual(dirname, basedir, "https://" + "go.googlesource.com/text")
|
||||||
|
case "golang.org/x/tools":
|
||||||
|
return cloneActual(dirname, basedir, "https://" + "go.googlesource.com/tools")
|
||||||
|
case "golang.org/x/xerrors":
|
||||||
|
return cloneActual(dirname, basedir, "https://" + "go.googlesource.com/xerrors")
|
||||||
|
case "google.golang.org/protobuf":
|
||||||
|
return cloneActual(dirname, basedir, "https://" + "go.googlesource.com/protobuf")
|
||||||
|
case "google.golang.org/genproto":
|
||||||
|
return cloneActual(dirname, basedir, "https://" + "go.googlesource.com/genproto")
|
||||||
|
case "google.golang.org/api":
|
||||||
|
return cloneActual(dirname, basedir, "https://" + "go.googlesource.com/api")
|
||||||
|
case "google.golang.org/grpc":
|
||||||
|
return cloneActual(dirname, basedir, "https://" + "go.googlesource.com/grpc")
|
||||||
|
case "google.golang.org/appengine":
|
||||||
|
return cloneActual(dirname, basedir, "https://" + "go.googlesource.com/appengine")
|
||||||
|
}
|
||||||
|
|
||||||
|
return errors.New("no gopath override here")
|
||||||
|
}
|
||||||
|
|
||||||
|
// attempt to git clone if the go path doesn't exist
|
||||||
|
// does a git clone, if it works, returns true
|
||||||
|
// workdir = /home/jcarr/go/src/
|
||||||
|
// gopath = go.wit.com/apps/helloworld
|
||||||
|
func Clone(workdir, gopath string) error {
|
||||||
|
fullpath := filepath.Join(workdir, gopath)
|
||||||
|
dirname := filepath.Base(fullpath)
|
||||||
|
|
||||||
|
basedir := strings.TrimSuffix(fullpath, dirname)
|
||||||
|
|
||||||
|
var err error
|
||||||
|
url := "https://" + gopath
|
||||||
|
log.Info("trying git clone")
|
||||||
|
log.Info("gopath =", gopath)
|
||||||
|
|
||||||
|
|
||||||
|
// try a direct git clone against the gopath
|
||||||
|
// cloneActual("helloworld", "/home/jcarr/go/src/go.wit.com/apps", "https://go.wit.com/apps/helloworld")
|
||||||
|
if err = cloneActual(dirname, basedir, url); err == nil {
|
||||||
|
// git clone worked!
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
log.Info("direct attempt at git clone failed", url)
|
||||||
|
|
||||||
|
// if direct git clone doesn't work, look for a redirect
|
||||||
|
// go directly to the URL as that is autoritive. If that failes
|
||||||
|
// try the go package system as maybe the git site no longer exists
|
||||||
|
if url, err = findGoImport(url); err != nil {
|
||||||
|
log.Info("findGoImport() DID NOT WORK", url)
|
||||||
|
log.Info("findGoImport() DID NOT WORK", err)
|
||||||
|
} else {
|
||||||
|
if err := cloneActual(dirname, basedir, url); err == nil {
|
||||||
|
// git clone worked!
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
log.Info("git clone from 'go-import' info failed", url)
|
||||||
|
|
||||||
|
// query the golang package system for the last known location
|
||||||
|
// NOTE: take time to thank the go developers and google for designing this wonderful system
|
||||||
|
if url, err = runGoList(gopath); err != nil {
|
||||||
|
log.Info("go list failed", err)
|
||||||
|
} else {
|
||||||
|
if err := cloneActual(dirname, basedir, url); err == nil {
|
||||||
|
// git clone worked!
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
log.Info("git clone from 'git list' info failed", url)
|
||||||
|
|
||||||
|
// try to parse a redirect
|
||||||
|
|
||||||
|
if err = clonePathHack(dirname, basedir, gopath); err == nil {
|
||||||
|
// WTF didn't go-import or go list work?
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return errors.New("can not find git sources for gopath " + gopath)
|
||||||
|
}
|
||||||
|
|
||||||
|
// newdir = helloworld
|
||||||
|
// basedir = /home/jcarr/go/src/go.wit.com/apps
|
||||||
|
// giturl = https://gitea.wit.com/gui/helloworld
|
||||||
|
func cloneActual(newdir, basedir, giturl string) error {
|
||||||
|
log.Info("cloneActual() newdir =", newdir)
|
||||||
|
log.Info("cloneActual() basedir =", basedir)
|
||||||
|
log.Info("cloneActual() giturl =", giturl)
|
||||||
|
if !IsDirectory(basedir) {
|
||||||
|
os.MkdirAll(basedir, 0750)
|
||||||
|
}
|
||||||
|
err := os.Chdir(basedir)
|
||||||
|
if err != nil {
|
||||||
|
log.Warn("chdir failed", basedir, err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd := []string{"git", "clone", "--verbose", "--progress", giturl, newdir}
|
||||||
|
log.Info("Running:", cmd)
|
||||||
|
r := shell.PathRunRealtime(basedir, cmd)
|
||||||
|
if r.Error != nil {
|
||||||
|
log.Warn("git clone error", r.Error)
|
||||||
|
return r.Error
|
||||||
|
}
|
||||||
|
|
||||||
|
fullpath := filepath.Join(basedir, newdir)
|
||||||
|
if !IsDirectory(fullpath) {
|
||||||
|
log.Info("git clone failed", giturl)
|
||||||
|
return errors.New("git clone failed " + giturl)
|
||||||
|
}
|
||||||
|
gitdir := filepath.Join(fullpath, ".git")
|
||||||
|
if IsDirectory(gitdir) {
|
||||||
|
log.Info("git cloned worked to", fullpath)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
// git clone didn't really work but did make a directory
|
||||||
|
log.Info("fullpath is probably empty", fullpath)
|
||||||
|
panic("crapnuts. rmdir fullpath here?")
|
||||||
|
}
|
||||||
|
|
||||||
|
// check the server for the current go path to git url mapping
|
||||||
|
// for example:
|
||||||
|
// This will check go.wit.com for "go.wit.com/apps/go-clone"
|
||||||
|
// and return where the URL to do git clone should be
|
||||||
|
func findGoImport(url string) (string, error) {
|
||||||
|
resp, err := http.Get(url)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
bodyBytes, err := ioutil.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
tmp := string(bodyBytes)
|
||||||
|
parts := strings.Split(tmp, "go-import")
|
||||||
|
if len(parts) < 2 {
|
||||||
|
return "", errors.New("missing go-import")
|
||||||
|
}
|
||||||
|
// this is terrible, it doesn't even look for 'content='
|
||||||
|
// but again, this is just a hack for my own code to be
|
||||||
|
// usuable after the removal in go v1.22 of the go get clone behavior that was in v1.21
|
||||||
|
parts = strings.Split(parts[1], "\"")
|
||||||
|
var newurl string
|
||||||
|
for {
|
||||||
|
if len(parts) == 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
tmp := strings.TrimSpace(parts[0])
|
||||||
|
fields := strings.Split(tmp, " ")
|
||||||
|
// log.Info("FIELDS:", fields)
|
||||||
|
if len(fields) == 3 {
|
||||||
|
newurl = fields[2]
|
||||||
|
break
|
||||||
|
}
|
||||||
|
parts = parts[1:]
|
||||||
|
}
|
||||||
|
if newurl == "" {
|
||||||
|
return "", errors.New("missing git content string")
|
||||||
|
}
|
||||||
|
|
||||||
|
return newurl, nil
|
||||||
|
}
|
256
common.go
256
common.go
|
@ -1,28 +1,110 @@
|
||||||
package repostatus
|
package repostatus
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
"unicode"
|
||||||
|
|
||||||
|
"go.wit.com/lib/gui/shell"
|
||||||
"go.wit.com/log"
|
"go.wit.com/log"
|
||||||
// "go.wit.com/gui/gui"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// reports externally if something has changed
|
// reports externally if something has changed
|
||||||
// since the last time it was asked about it
|
// since the last time it was asked about it
|
||||||
func (rs *RepoStatus) Changed() bool {
|
func (rs *RepoStatus) Changed() (string, bool) {
|
||||||
if !rs.Ready() {
|
if !rs.Ready() {
|
||||||
return false
|
return "", false
|
||||||
}
|
}
|
||||||
|
|
||||||
return rs.changed
|
return rs.getChanges(), rs.changed
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rs *RepoStatus) Draw() {
|
// keeps a human readable list of things that have
|
||||||
if !rs.Ready() {
|
// changed. todo: timestampe these?
|
||||||
return
|
func (rs *RepoStatus) getChanges() string {
|
||||||
|
return rs.changes
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
}
|
}
|
||||||
log.Log(CHANGE, "Draw() window ready =", rs.ready)
|
return false
|
||||||
rs.window.TestDraw()
|
}
|
||||||
// rs.window.Draw()
|
|
||||||
rs.ready = true
|
func (rs *RepoStatus) IsProtobuf() (bool, []string, error) {
|
||||||
|
fullp, fullc, err := ScanForProtobuf(rs.Path())
|
||||||
|
protos := make(map[string]string)
|
||||||
|
protoc := make(map[string]string)
|
||||||
|
var anyfound bool = false
|
||||||
|
var allc []string
|
||||||
|
for _, s := range fullp {
|
||||||
|
filebase := filepath.Base(s)
|
||||||
|
name := strings.TrimSuffix(filebase, ".proto")
|
||||||
|
anyfound = true
|
||||||
|
protos[name] = s
|
||||||
|
}
|
||||||
|
for pname, _ := range protos {
|
||||||
|
var found bool = false
|
||||||
|
for _, s := range fullc {
|
||||||
|
cfilebase := filepath.Base(s)
|
||||||
|
cname := strings.TrimSuffix(cfilebase, ".pb.go")
|
||||||
|
protoc[cname] = s
|
||||||
|
if cname == pname {
|
||||||
|
found = true
|
||||||
|
allc = append(allc, cfilebase)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if found {
|
||||||
|
// log.Info("found ok")
|
||||||
|
} else {
|
||||||
|
log.Info("missing compiled proto file:", pname+"pb.go")
|
||||||
|
err = errors.New("compiled file " + pname + ".pb.go missing")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return anyfound, allc, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// returns the filesystem path to the repo
|
||||||
|
func (rs *RepoStatus) Path() string {
|
||||||
|
if rs == nil {
|
||||||
|
log.Warn("rs == nil")
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
if rs.realPath == nil {
|
||||||
|
log.Warn("rs.realPath == nil")
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return rs.realPath.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rs *RepoStatus) Show() {
|
func (rs *RepoStatus) Show() {
|
||||||
|
@ -31,7 +113,6 @@ func (rs *RepoStatus) Show() {
|
||||||
}
|
}
|
||||||
log.Log(CHANGE, "Show() window ready =", rs.ready)
|
log.Log(CHANGE, "Show() window ready =", rs.ready)
|
||||||
rs.window.Show()
|
rs.window.Show()
|
||||||
rs.hidden = false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rs *RepoStatus) Hide() {
|
func (rs *RepoStatus) Hide() {
|
||||||
|
@ -40,7 +121,6 @@ func (rs *RepoStatus) Hide() {
|
||||||
}
|
}
|
||||||
log.Log(CHANGE, "Hide() window ready =", rs.ready)
|
log.Log(CHANGE, "Hide() window ready =", rs.ready)
|
||||||
rs.window.Hide()
|
rs.window.Hide()
|
||||||
rs.hidden = true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rs *RepoStatus) Toggle() {
|
func (rs *RepoStatus) Toggle() {
|
||||||
|
@ -48,7 +128,7 @@ func (rs *RepoStatus) Toggle() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
log.Log(CHANGE, "Toggle() window ready =", rs.ready)
|
log.Log(CHANGE, "Toggle() window ready =", rs.ready)
|
||||||
if rs.hidden {
|
if rs.window.Hidden() {
|
||||||
rs.Show()
|
rs.Show()
|
||||||
} else {
|
} else {
|
||||||
rs.Hide()
|
rs.Hide()
|
||||||
|
@ -65,11 +145,147 @@ func (rs *RepoStatus) Ready() bool {
|
||||||
return rs.ready
|
return rs.ready
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
func (rs *RepoStatus) IsGoLang() bool {
|
||||||
func (rs *RepoStatus) Initialized() bool {
|
if !rs.Ready() {
|
||||||
log.Log(CHANGE, "checking Initialized()")
|
return false
|
||||||
if rs == nil {return false}
|
}
|
||||||
if rs.parent == nil {return false}
|
if rs.isGoLang.String() == "true" {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// experiment to determine the golang package type
|
||||||
|
func (rs *RepoStatus) RepoType() string {
|
||||||
|
if !rs.IsGoLang() {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
if !rs.Exists("go.mod") {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
os.Setenv("GO111MODULE", "off")
|
||||||
|
cmd := []string{"go", "list", "-f", "'{{if eq .Name \"main\"}}binary{{else}}library{{end}}'"}
|
||||||
|
r := shell.PathRunLog(rs.Path(), cmd, INFO)
|
||||||
|
output := strings.TrimSpace(strings.Join(r.Stdout, "\n"))
|
||||||
|
if r.Error != nil {
|
||||||
|
log.Info("go package error:", r.Error)
|
||||||
|
}
|
||||||
|
return output
|
||||||
|
}
|
||||||
|
|
||||||
|
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) Build() bool {
|
||||||
|
if !rs.IsGoLang() {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
name := rs.BinaryName()
|
||||||
|
// removes the binary if it already exists
|
||||||
|
rs.Run([]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) GetTargetVersion() string {
|
||||||
|
return rs.targetReleaseVersion.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rs *RepoStatus) GetCurrentVersion() string {
|
||||||
|
return rs.currentVersion.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rs *RepoStatus) LastTag() string {
|
||||||
|
return rs.lasttag.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
return true
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
// 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")
|
||||||
|
} else {
|
||||||
|
rs.private.SetText("false")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,57 @@
|
||||||
|
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(REPO, "\tmissing go.sum", rs.realPath.String())
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
defer gosum.Close()
|
||||||
|
|
||||||
|
var deps GoConfig
|
||||||
|
deps = make(GoConfig)
|
||||||
|
|
||||||
|
scanner := bufio.NewScanner(gosum)
|
||||||
|
log.Log(REPO, "\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.Log(REPO, "\tREPO:", rs.String(), rs.realPath.String())
|
||||||
|
log.Log(REPO, "\t version mismatch:", godep, version, currentversion)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
deps[godep] = version
|
||||||
|
log.Log(REPO, "\t", godep, "=", version)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
log.Log(REPO, "\t INVALID:", parts)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := scanner.Err(); err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return deps
|
||||||
|
}
|
461
draw.go
461
draw.go
|
@ -1,477 +1,36 @@
|
||||||
package repostatus
|
package repostatus
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"strconv"
|
"go.wit.com/gui"
|
||||||
"strings"
|
|
||||||
|
|
||||||
"go.wit.com/lib/gadgets"
|
"go.wit.com/lib/gadgets"
|
||||||
"go.wit.com/log"
|
|
||||||
"go.wit.com/widget"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// creates the actual widgets.
|
func (rs *RepoStatus) drawGitStatus(box *gui.Node) {
|
||||||
// it's assumed you are always passing in a box
|
rs.gitStatusGroup = box.NewGroup("What GIT Knows It Has")
|
||||||
func (rs *RepoStatus) draw() {
|
|
||||||
if !rs.Ready() {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// display the status of the git repository
|
|
||||||
rs.drawGitStatus()
|
|
||||||
|
|
||||||
// display the git branches and options
|
|
||||||
rs.drawGitBranches()
|
|
||||||
|
|
||||||
// show standard git commit and merge controls
|
|
||||||
rs.drawGitCommands()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (rs *RepoStatus) drawGitBranches() {
|
|
||||||
rs.gitBranchesGroup = rs.window.Box().NewGroup("branches")
|
|
||||||
newgrid := rs.gitBranchesGroup.NewGrid("gridnuts", 2, 2)
|
|
||||||
|
|
||||||
rs.masterDrop = gadgets.NewBasicDropdown(newgrid, "main branch")
|
|
||||||
rs.masterDrop.Custom = func() {
|
|
||||||
log.Log(WARN, "Switching main branch to:", rs.masterDrop.String())
|
|
||||||
rs.masterBranchVersion.SetLabel(rs.masterDrop.String())
|
|
||||||
rs.mainWorkingName.SetValue(rs.masterDrop.String())
|
|
||||||
}
|
|
||||||
rs.develDrop = gadgets.NewBasicDropdown(newgrid, "devel branch")
|
|
||||||
rs.develDrop.Custom = func() {
|
|
||||||
log.Log(WARN, "Switching devel branch to:", rs.develDrop.String())
|
|
||||||
rs.develBranchVersion.SetLabel(rs.develDrop.String())
|
|
||||||
rs.develWorkingName.SetValue(rs.develDrop.String())
|
|
||||||
}
|
|
||||||
rs.userDrop = gadgets.NewBasicDropdown(newgrid, "user branch")
|
|
||||||
rs.userDrop.Custom = func() {
|
|
||||||
log.Log(WARN, "Switching user branch to:", rs.userDrop.String())
|
|
||||||
rs.userBranchVersion.SetLabel(rs.userDrop.String())
|
|
||||||
rs.userWorkingName.SetValue(rs.userDrop.String())
|
|
||||||
}
|
|
||||||
|
|
||||||
rs.lasttag = gadgets.NewOneLiner(newgrid, "last tag")
|
|
||||||
|
|
||||||
rs.masterBranchVersion = gadgets.NewOneLiner(newgrid, "master")
|
|
||||||
rs.develBranchVersion = gadgets.NewOneLiner(newgrid, "devel")
|
|
||||||
rs.userBranchVersion = gadgets.NewOneLiner(newgrid, "user")
|
|
||||||
|
|
||||||
rs.currentBranch = gadgets.NewOneLiner(newgrid, "current branch")
|
|
||||||
rs.currentVersion = gadgets.NewOneLiner(newgrid, "current version")
|
|
||||||
|
|
||||||
/*
|
|
||||||
var master = ""
|
|
||||||
all := rs.getBranches()
|
|
||||||
for _, branch := range all {
|
|
||||||
log.Log(INFO, "getBranches()", branch)
|
|
||||||
rs.masterDrop.AddText(branch)
|
|
||||||
rs.develDrop.AddText(branch)
|
|
||||||
rs.userDrop.AddText(branch)
|
|
||||||
if branch == "master" {
|
|
||||||
master = "master"
|
|
||||||
}
|
|
||||||
if branch == "main" {
|
|
||||||
master = "main"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
// relabel the various gadgets with the right branch name
|
|
||||||
// rs.masterBranchVersion.SetLabel(master)
|
|
||||||
|
|
||||||
rs.showBranchesButton = newgrid.NewButton("getBranches()", func() {
|
|
||||||
all := rs.getBranches()
|
|
||||||
i := len(all)
|
|
||||||
log.Log(WARN, "branch count =", i)
|
|
||||||
})
|
|
||||||
|
|
||||||
rs.checkBranchesButton = newgrid.NewButton("CheckBranches()", func() {
|
|
||||||
if rs.CheckBranches() {
|
|
||||||
log.Log(WARN, "Branches are perfect")
|
|
||||||
} else {
|
|
||||||
log.Log(WARN, "Branches are not perfect")
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
newgrid.NewButton("show .git/config", func() {
|
|
||||||
if rs.gitConfig == nil {
|
|
||||||
log.Log(WARN, "Nonexistant or damaged .git/config", rs.String())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
log.Log(WARN, ".git/config:", rs.realPath.String())
|
|
||||||
|
|
||||||
// The info:
|
|
||||||
for name, remote := range rs.gitConfig.remotes {
|
|
||||||
log.Log(WARN, " ", name, "url:", remote.url)
|
|
||||||
}
|
|
||||||
for name, branch := range rs.gitConfig.branches {
|
|
||||||
log.Log(WARN, " ", name, "remote:", branch.remote, "merge", branch.merge)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
newgrid.NewButton("check go.sum", func() {
|
|
||||||
rs.CheckGoSum()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (rs *RepoStatus) drawGitStatus() {
|
|
||||||
rs.gitStatusGroup = rs.window.Box().NewGroup("What GO Knows It Has")
|
|
||||||
newgrid := rs.gitStatusGroup.NewGrid("gridnuts", 2, 2)
|
newgrid := rs.gitStatusGroup.NewGrid("gridnuts", 2, 2)
|
||||||
newgrid.Margin()
|
newgrid.Margin()
|
||||||
newgrid.Pad()
|
newgrid.Pad()
|
||||||
|
|
||||||
rs.path = gadgets.NewOneLiner(newgrid, "path")
|
rs.path = gadgets.NewOneLiner(newgrid, "path")
|
||||||
rs.goSrcPath = gadgets.NewOneLiner(newgrid, "~/go/src")
|
rs.goSrcPath = gadgets.NewOneLiner(newgrid, "~/go/src")
|
||||||
|
rs.goPath = gadgets.NewOneLiner(newgrid, "go path")
|
||||||
rs.realPath = gadgets.NewOneLiner(newgrid, "full path")
|
rs.realPath = gadgets.NewOneLiner(newgrid, "full path")
|
||||||
rs.realPath.Hide()
|
rs.isGoLang = gadgets.NewOneLiner(newgrid, "Is GO Lang?")
|
||||||
|
rs.isGoLang.SetText("false")
|
||||||
rs.mainWorkingName = gadgets.NewOneLiner(newgrid, "main working branch")
|
rs.mainWorkingName = gadgets.NewOneLiner(newgrid, "main working branch")
|
||||||
rs.mainWorkingName.SetValue("???")
|
rs.mainWorkingName.SetValue("???")
|
||||||
rs.develWorkingName = gadgets.NewOneLiner(newgrid, "devel working branch")
|
rs.develWorkingName = gadgets.NewOneLiner(newgrid, "devel working branch")
|
||||||
rs.develWorkingName.SetValue("devel")
|
rs.develWorkingName.SetValue("devel")
|
||||||
rs.userWorkingName = gadgets.NewOneLiner(newgrid, "user working branch")
|
rs.userWorkingName = gadgets.NewOneLiner(newgrid, "user working branch")
|
||||||
rs.userWorkingName.SetValue("uid")
|
rs.userWorkingName.SetValue("uid")
|
||||||
rs.tagsDrop = gadgets.NewBasicDropdown(newgrid, "all releases")
|
|
||||||
|
|
||||||
// git for-each-ref --sort=taggerdate --format '%(tag) ,,,_,,, %(subject)' refs/tags
|
|
||||||
var cmd []string
|
|
||||||
cmd = append(cmd, "git", "for-each-ref", "--sort=taggerdate", "--format", "%(tag) %(subject)", "refs/tags")
|
|
||||||
_, _, output := RunCmd(rs.realPath.String(), cmd)
|
|
||||||
log.Log(INFO, output)
|
|
||||||
for _, line := range strings.Split(output, "\n") {
|
|
||||||
rs.tagsDrop.AddText(line)
|
|
||||||
}
|
|
||||||
|
|
||||||
rs.dirtyLabel = gadgets.NewOneLiner(newgrid, "dirty")
|
rs.dirtyLabel = gadgets.NewOneLiner(newgrid, "dirty")
|
||||||
|
rs.gitState = gadgets.NewOneLiner(newgrid, "git state")
|
||||||
rs.readOnly = gadgets.NewOneLiner(newgrid, "read only")
|
rs.readOnly = gadgets.NewOneLiner(newgrid, "read only")
|
||||||
|
rs.primitive = gadgets.NewOneLiner(newgrid, "primitive")
|
||||||
|
rs.private = gadgets.NewOneLiner(newgrid, "private")
|
||||||
|
rs.targetReleaseVersion = gadgets.NewOneLiner(newgrid, "target release version")
|
||||||
|
|
||||||
rs.speed = gadgets.NewOneLiner(newgrid, "refresh speed =")
|
rs.speed = gadgets.NewOneLiner(newgrid, "refresh speed =")
|
||||||
rs.speedActual = gadgets.NewOneLiner(newgrid, "speed actual =")
|
rs.speedActual = gadgets.NewOneLiner(newgrid, "speed actual =")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rs *RepoStatus) drawGitCommands() {
|
|
||||||
rs.gitCommandsGroup = rs.window.Box().NewGroup("git commands")
|
|
||||||
newgrid := rs.gitCommandsGroup.NewGrid("gridnuts", 2, 2)
|
|
||||||
|
|
||||||
newgrid.NewButton("update", func() {
|
|
||||||
rs.Update()
|
|
||||||
})
|
|
||||||
|
|
||||||
newgrid.NewButton("git pull", func() {
|
|
||||||
var cmd []string
|
|
||||||
cmd = append(cmd, "git", "pull")
|
|
||||||
err, b, output := RunCmd(rs.realPath.String(), cmd)
|
|
||||||
log.Warn("Did git pull here", err, b, output)
|
|
||||||
})
|
|
||||||
|
|
||||||
rs.major = gadgets.NewBasicCombobox(newgrid, "major")
|
|
||||||
rs.major.Custom = func() {
|
|
||||||
rs.setTag()
|
|
||||||
rs.generateCmd()
|
|
||||||
}
|
|
||||||
rs.minor = gadgets.NewBasicCombobox(newgrid, "minor")
|
|
||||||
rs.minor.Custom = func() {
|
|
||||||
rs.setTag()
|
|
||||||
rs.generateCmd()
|
|
||||||
}
|
|
||||||
rs.revision = gadgets.NewBasicCombobox(newgrid, "revision")
|
|
||||||
rs.revision.Custom = func() {
|
|
||||||
rs.setTag()
|
|
||||||
rs.generateCmd()
|
|
||||||
}
|
|
||||||
newgrid.NewLabel("new tag version")
|
|
||||||
rs.newversion = newgrid.NewLabel("0.0.1")
|
|
||||||
|
|
||||||
rs.versionMessage = gadgets.NewBasicEntry(newgrid, "tag message")
|
|
||||||
rs.versionMessage.Custom = func() {
|
|
||||||
rs.generateCmd()
|
|
||||||
}
|
|
||||||
rs.versionCmdOutput = gadgets.NewOneLiner(newgrid, "tag cmd")
|
|
||||||
|
|
||||||
label := "merge " + rs.masterDrop.String() + " to devel"
|
|
||||||
rs.develMerge = newgrid.NewButton(label, func() {
|
|
||||||
rs.Disable()
|
|
||||||
master := rs.masterDrop.String()
|
|
||||||
rs.checkoutBranch("master", master)
|
|
||||||
if rs.getCurrentBranchName() != master {
|
|
||||||
log.Warn("something went wrong switching to the master branch. full stop!")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if !rs.runGitCommands() {
|
|
||||||
log.Warn("SOMETHING WENT WRONG")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
rs.Update()
|
|
||||||
rs.Enable()
|
|
||||||
log.Warn("THINGS SEEM OK")
|
|
||||||
})
|
|
||||||
|
|
||||||
rs.releaseVersion = newgrid.NewButton("tag and release new version", func() {
|
|
||||||
if !rs.generateCmd() {
|
|
||||||
log.Warn("something is wrong. fix the errors first")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
rs.releaseVersion.Disable()
|
|
||||||
log.Warn("COMMIT IT HERE")
|
|
||||||
if !rs.runGitCommands() {
|
|
||||||
log.Warn("SOMETHING WENT WRONG")
|
|
||||||
}
|
|
||||||
rs.Update()
|
|
||||||
log.Warn("THINGS SEEM OK")
|
|
||||||
})
|
|
||||||
|
|
||||||
newgrid.Margin()
|
|
||||||
newgrid.Pad()
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
func (rs *RepoStatus) SetVersion(a, b, c string, reason string) {
|
|
||||||
rs.major.SetText(a)
|
|
||||||
rs.minor.SetText(b)
|
|
||||||
rs.revision.SetText(c)
|
|
||||||
|
|
||||||
rs.versionMessage.SetLabel(reason)
|
|
||||||
rs.versionMessage.SetText(reason)
|
|
||||||
// rs.versionMessage.SetValue(reason)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (rs *RepoStatus) setTag() bool {
|
|
||||||
lasttag := rs.lasttag.String()
|
|
||||||
var major, minor, revision string
|
|
||||||
major, minor, revision = splitVersion(lasttag)
|
|
||||||
|
|
||||||
olda, _ := strconv.Atoi(major)
|
|
||||||
oldb, _ := strconv.Atoi(minor)
|
|
||||||
oldc, _ := strconv.Atoi(revision)
|
|
||||||
|
|
||||||
log.Log(INFO, "current version here", lasttag)
|
|
||||||
log.Log(INFO, "current release a,b,c =", major, minor, revision)
|
|
||||||
|
|
||||||
newa, _ := strconv.Atoi(rs.major.String())
|
|
||||||
|
|
||||||
newver := strconv.Itoa(newa)
|
|
||||||
if newa < olda {
|
|
||||||
log.Warn("new version bad", newver, "vs old version", lasttag, "newa =", newa, "olda =", olda)
|
|
||||||
rs.newversion.SetLabel("bad")
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if newa > olda {
|
|
||||||
log.Log(INFO, "new version ok", newver, "vs old version", lasttag)
|
|
||||||
rs.newversion.SetLabel(newver)
|
|
||||||
rs.minor.SetText("")
|
|
||||||
rs.revision.SetText("")
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
newb, _ := strconv.Atoi(rs.minor.String())
|
|
||||||
newver = strconv.Itoa(newa) + "." + strconv.Itoa(newb)
|
|
||||||
if newb < oldb {
|
|
||||||
log.Warn("new version bad", newver, "vs old version", lasttag, "newb =", newb, "oldb =", oldb)
|
|
||||||
rs.newversion.SetLabel("bad")
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
if newb > oldb {
|
|
||||||
log.Log(INFO, "new version ok", newver, "vs old version", lasttag)
|
|
||||||
rs.newversion.SetLabel(newver)
|
|
||||||
rs.revision.SetText("")
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
newc, _ := strconv.Atoi(rs.revision.String())
|
|
||||||
newver = strconv.Itoa(newa) + "." + strconv.Itoa(newb) + "." + strconv.Itoa(newc)
|
|
||||||
if newc <= oldc {
|
|
||||||
log.Warn("new version bad", newver, "vs old version", lasttag)
|
|
||||||
rs.newversion.SetLabel("bad")
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
log.Log(INFO, "new version ok", newver, "vs old version", lasttag)
|
|
||||||
rs.newversion.SetLabel(newver)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
func (rs *RepoStatus) incrementVersion() {
|
|
||||||
lasttag := rs.lasttag.String()
|
|
||||||
var major, minor, revision string
|
|
||||||
major, minor, revision = splitVersion(lasttag)
|
|
||||||
log.Warn("Should release version here", lasttag)
|
|
||||||
log.Log(INFO, "Should release a,b,c", major, minor, revision)
|
|
||||||
|
|
||||||
a, _ := strconv.Atoi(major)
|
|
||||||
b, _ := strconv.Atoi(minor)
|
|
||||||
c, _ := strconv.Atoi(revision)
|
|
||||||
|
|
||||||
rs.major.AddText(widget.GetString(a))
|
|
||||||
rs.major.AddText(widget.GetString(a + 1))
|
|
||||||
rs.major.SetText(widget.GetString(a))
|
|
||||||
|
|
||||||
rs.minor.AddText(widget.GetString(b))
|
|
||||||
rs.minor.AddText(widget.GetString(b + 1))
|
|
||||||
rs.minor.SetText(widget.GetString(b))
|
|
||||||
|
|
||||||
// rs.c := strconv.Atoi(revision)
|
|
||||||
rs.revision.AddText(widget.GetString(c + 1))
|
|
||||||
rs.revision.AddText(widget.GetString(c + 2))
|
|
||||||
rs.revision.SetText(widget.GetString(c + 1))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (rs *RepoStatus) recommend() {
|
|
||||||
log.Log(INFO, "Is repo dirty?", rs.dirtyLabel.String())
|
|
||||||
log.Log(INFO, "list the known tags")
|
|
||||||
rs.DisableEverything()
|
|
||||||
rs.populateTags()
|
|
||||||
log.Log(INFO, "Does devel == user?", rs.develBranchVersion.String(), rs.userBranchVersion.String())
|
|
||||||
if rs.develBranchVersion.String() != rs.userBranchVersion.String() {
|
|
||||||
log.Log(INFO, "devel does not equal user")
|
|
||||||
log.Log(INFO, "merge or squash?")
|
|
||||||
rs.EnableMergeDevel()
|
|
||||||
rs.setMergeUserCommands()
|
|
||||||
label := "merge user into " + rs.GetDevelBranchName()
|
|
||||||
rs.develMerge.SetLabel(label)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
log.Log(INFO, "Does master == devel? ", rs.masterBranchVersion.String(), rs.develBranchVersion.String())
|
|
||||||
if rs.masterBranchVersion.String() != rs.develBranchVersion.String() {
|
|
||||||
log.Log(INFO, "master does not equal devel. merge devel into master")
|
|
||||||
rs.EnableMergeDevel()
|
|
||||||
rs.setMergeDevelCommands()
|
|
||||||
label := "merge devel into " + rs.GetMasterBranchName()
|
|
||||||
rs.develMerge.SetLabel(label)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
rs.getLastTagVersion()
|
|
||||||
if rs.lasttag.String() != rs.masterBranchVersion.String() {
|
|
||||||
log.Log(INFO, "master does not equal last tag")
|
|
||||||
rs.incrementVersion()
|
|
||||||
rs.EnableSelectTag()
|
|
||||||
rs.setTag()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
log.Log(INFO, "Is repo pushed upstream? git.wit.org or github?")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (rs *RepoStatus) generateCmd() bool {
|
|
||||||
// the length of 24 is arbitrary, but should be short
|
|
||||||
// they should be things like perhaps, major release names
|
|
||||||
// or something the users might see.
|
|
||||||
// aka: "Topsy", "Picasso", "Buzz", etc
|
|
||||||
|
|
||||||
if !rs.setTag() {
|
|
||||||
log.Log(INFO, "tag sucked. fix your tag version")
|
|
||||||
rs.versionMessage.SetLabel("tag message (bad version)")
|
|
||||||
rs.releaseVersion.Disable()
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Log(INFO, "tag is valid!!!!")
|
|
||||||
rs.setGitCommands()
|
|
||||||
|
|
||||||
if rs.versionMessage.String() == "" {
|
|
||||||
log.Log(INFO, "tag message is empty!!!!")
|
|
||||||
rs.releaseVersion.Disable()
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if len(rs.versionMessage.String()) > 24 {
|
|
||||||
rs.versionMessage.SetLabel("tag message (too long)")
|
|
||||||
} else {
|
|
||||||
rs.versionMessage.SetLabel("tag message")
|
|
||||||
}
|
|
||||||
rs.releaseVersion.Enable()
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
func (rs *RepoStatus) runGitCommands() bool {
|
|
||||||
for _, line := range rs.versionCmds {
|
|
||||||
s := strings.Join(line, " ")
|
|
||||||
log.Log(INFO, "NEED TO RUN:", s)
|
|
||||||
rs.develMerge.SetText(s)
|
|
||||||
err, b, output := runCmd(rs.realPath.String(), line)
|
|
||||||
if err != nil {
|
|
||||||
log.Warn("ABEND EXECUTION")
|
|
||||||
log.Warn("error =", err)
|
|
||||||
log.Warn("output =", output)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
log.Log(INFO, "Returned with b =", b)
|
|
||||||
log.Log(INFO, "output was =", output)
|
|
||||||
log.Log(INFO, "RUN DONE")
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
func (rs *RepoStatus) setGitCommands() {
|
|
||||||
var line1, line2, line3 []string
|
|
||||||
var all [][]string
|
|
||||||
|
|
||||||
newTag := rs.newversion.String()
|
|
||||||
line1 = append(line1, "git", "tag", "v"+newTag, "-m", rs.versionMessage.String())
|
|
||||||
all = append(all, line1)
|
|
||||||
line2 = append(line2, "git", "push", "--tags")
|
|
||||||
all = append(all, line2)
|
|
||||||
line3 = append(line3, "git", "push", "--prune", "--tags")
|
|
||||||
all = append(all, line3)
|
|
||||||
|
|
||||||
rs.versionCmds = all
|
|
||||||
|
|
||||||
var tmp []string
|
|
||||||
// convert to displayable to the user text
|
|
||||||
for _, line := range all {
|
|
||||||
s := strings.Join(line, " ")
|
|
||||||
log.Log(INFO, "s =", s)
|
|
||||||
tmp = append(tmp, s)
|
|
||||||
}
|
|
||||||
|
|
||||||
rs.versionCmdOutput.SetValue(strings.Join(tmp, "\n"))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (rs *RepoStatus) setMergeDevelCommands() {
|
|
||||||
var line1, line2, line3 []string
|
|
||||||
var all [][]string
|
|
||||||
|
|
||||||
master := rs.GetMasterBranchName()
|
|
||||||
devel := rs.GetDevelBranchName()
|
|
||||||
|
|
||||||
line1 = append(line1, "git", "checkout", master)
|
|
||||||
all = append(all, line1)
|
|
||||||
line2 = append(line2, "git", "merge", devel)
|
|
||||||
all = append(all, line2)
|
|
||||||
line3 = append(line3, "git", "push")
|
|
||||||
all = append(all, line3)
|
|
||||||
|
|
||||||
rs.versionCmds = all
|
|
||||||
|
|
||||||
var tmp []string
|
|
||||||
// convert to displayable to the user text
|
|
||||||
for _, line := range all {
|
|
||||||
s := strings.Join(line, " ")
|
|
||||||
log.Log(INFO, "s =", s)
|
|
||||||
tmp = append(tmp, s)
|
|
||||||
}
|
|
||||||
|
|
||||||
rs.versionCmdOutput.SetValue(strings.Join(tmp, "\n"))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (rs *RepoStatus) setMergeUserCommands() {
|
|
||||||
var line1, line2, line3 []string
|
|
||||||
var all [][]string
|
|
||||||
|
|
||||||
devel := rs.GetDevelBranchName()
|
|
||||||
user := rs.GetUserBranchName()
|
|
||||||
|
|
||||||
line1 = append(line1, "git", "checkout", devel)
|
|
||||||
all = append(all, line1)
|
|
||||||
line2 = append(line2, "git", "merge", user)
|
|
||||||
all = append(all, line2)
|
|
||||||
line3 = append(line3, "git", "push")
|
|
||||||
all = append(all, line3)
|
|
||||||
|
|
||||||
rs.versionCmds = all
|
|
||||||
|
|
||||||
var tmp []string
|
|
||||||
// convert to displayable to the user text
|
|
||||||
for _, line := range all {
|
|
||||||
s := strings.Join(line, " ")
|
|
||||||
log.Log(INFO, "s =", s)
|
|
||||||
tmp = append(tmp, s)
|
|
||||||
}
|
|
||||||
|
|
||||||
rs.versionCmdOutput.SetValue(strings.Join(tmp, "\n"))
|
|
||||||
}
|
|
||||||
|
|
510
git.go
510
git.go
|
@ -1,24 +1,19 @@
|
||||||
package repostatus
|
package repostatus
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"os/user"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
"unicode/utf8"
|
"unicode/utf8"
|
||||||
|
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
|
||||||
|
"go.wit.com/lib/gui/shell"
|
||||||
"go.wit.com/log"
|
"go.wit.com/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (rs *RepoStatus) String() string {
|
|
||||||
return rs.path.String()
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
func (rs *RepoStatus) GetPath() string {
|
|
||||||
return rs.path.String()
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
func (rs *RepoStatus) GetCurrentBranchName() string {
|
func (rs *RepoStatus) GetCurrentBranchName() string {
|
||||||
return rs.currentBranch.String()
|
return rs.currentBranch.String()
|
||||||
}
|
}
|
||||||
|
@ -27,45 +22,142 @@ func (rs *RepoStatus) GetCurrentBranchVersion() string {
|
||||||
return rs.currentVersion.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")
|
||||||
|
r := rs.Run(cmd)
|
||||||
|
output := strings.Join(r.Stdout, "\n")
|
||||||
|
if r.Error != nil {
|
||||||
|
output = "git error_,,,_a_,,,_b_,,,c"
|
||||||
|
}
|
||||||
|
if r.Error == 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(), r.Error)
|
||||||
|
}
|
||||||
|
return output, r.Error
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
// this isn't right
|
||||||
|
func (rs *RepoStatus) LastTagAge() (time.Time, string) {
|
||||||
|
return time.Now(), rs.lasttag.String()
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
func (rs *RepoStatus) GetLastTagVersion() string {
|
func (rs *RepoStatus) GetLastTagVersion() string {
|
||||||
return rs.lasttag.String()
|
return rs.lasttag.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rs *RepoStatus) getCurrentBranchName() string {
|
// stores the current branch name
|
||||||
|
func (rs *RepoStatus) checkCurrentBranchName() string {
|
||||||
|
currentname := rs.currentBranch.String()
|
||||||
out := run(rs.realPath.String(), "git", "branch --show-current")
|
out := run(rs.realPath.String(), "git", "branch --show-current")
|
||||||
log.Log(INFO, "getCurrentBranchName() =", out)
|
if currentname == out {
|
||||||
|
// nothing changed
|
||||||
|
return currentname
|
||||||
|
}
|
||||||
rs.currentBranch.SetValue(out)
|
rs.currentBranch.SetValue(out)
|
||||||
|
if currentname == "" {
|
||||||
|
return out // don't note if there was nothing before
|
||||||
|
}
|
||||||
|
rs.NoteChange("current branch has changed from " + currentname + " to " + out)
|
||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rs *RepoStatus) getCurrentBranchVersion() string {
|
func (rs *RepoStatus) gitDescribeByHash(hash string) (string, error) {
|
||||||
out := run(rs.realPath.String(), "git", "describe --tags")
|
if hash == "" {
|
||||||
log.Log(INFO, "getCurrentBranchVersion()", out)
|
return "", errors.New("hash was blank")
|
||||||
|
}
|
||||||
|
r := shell.PathRunLog(rs.Path(), []string{"git", "describe", "--tags", "--always", hash}, INFO)
|
||||||
|
out := strings.Join(r.Stdout, "\n")
|
||||||
|
if r.Error != nil {
|
||||||
|
log.Warn("not in a git repo or bad hash?", r.Error, rs.Path())
|
||||||
|
return out, r.Error
|
||||||
|
}
|
||||||
|
return out, r.Error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rs *RepoStatus) gitDescribeByName(name string) (string, error) {
|
||||||
|
name = strings.TrimSpace(name)
|
||||||
|
|
||||||
|
if name == "" {
|
||||||
|
// git will return the current tag
|
||||||
|
r := shell.PathRunLog(rs.Path(), []string{"git", "describe", "--tags", "--always"}, INFO)
|
||||||
|
output := strings.Join(r.Stdout, "\n")
|
||||||
|
if r.Error != nil {
|
||||||
|
log.Warn("gitDescribeByName() not in a git repo?", r.Error, rs.Path())
|
||||||
|
}
|
||||||
|
return strings.TrimSpace(output), r.Error
|
||||||
|
}
|
||||||
|
if !rs.LocalTagExists(name) {
|
||||||
|
// tag does not exist
|
||||||
|
return "", errors.New("gitDescribeByName() git fatal: Not a valid object name")
|
||||||
|
}
|
||||||
|
cmd := []string{"git", "describe", "--tags", "--always", name}
|
||||||
|
r := shell.PathRunLog(rs.Path(), cmd, INFO)
|
||||||
|
output := strings.Join(r.Stdout, "\n")
|
||||||
|
if r.Error != nil {
|
||||||
|
log.Warn("cmd =", cmd)
|
||||||
|
log.Warn("err =", r.Error)
|
||||||
|
log.Warn("not in a git repo or bad tag?", rs.Path())
|
||||||
|
}
|
||||||
|
|
||||||
|
return strings.TrimSpace(output), r.Error
|
||||||
|
}
|
||||||
|
|
||||||
|
// todo: don't run git every time?
|
||||||
|
func (rs *RepoStatus) checkCurrentBranchVersion() string {
|
||||||
|
out, _ := rs.gitDescribeByName("")
|
||||||
|
log.Log(REPO, "checkCurrentBranchVersion()", out)
|
||||||
rs.currentVersion.SetValue(out)
|
rs.currentVersion.SetValue(out)
|
||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rs *RepoStatus) getLastTagVersion() string {
|
// this should get the most recent tag
|
||||||
out := run(rs.realPath.String(), "git", "rev-list --tags --max-count=1")
|
func (rs *RepoStatus) setLastTagVersion() {
|
||||||
log.Log(INFO, "getLastTagVersion()", out)
|
hash := run(rs.realPath.String(), "git", "rev-list --tags --max-count=1")
|
||||||
// rs.lasttagrev = out
|
log.Log(REPO, "getLastTagVersion()", hash)
|
||||||
|
|
||||||
lastreal := "describe --tags " + out
|
name, _ := rs.gitDescribeByHash(hash)
|
||||||
// out = run(r.path, "git", "describe --tags c871d5ecf051a7dc4e3a77157cdbc0a457eb9ae1")
|
rs.lasttag.SetText(name)
|
||||||
out = run(rs.realPath.String(), "git", lastreal)
|
return
|
||||||
rs.lasttag.SetValue(out)
|
|
||||||
rs.tagsDrop.SetText(out)
|
|
||||||
// rs.lastLabel.SetText(out)
|
|
||||||
return out
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rs *RepoStatus) populateTags() {
|
func (rs *RepoStatus) populateTags() {
|
||||||
tmp := rs.realPath.String() + "/.git/refs/tags"
|
tmp := rs.realPath.String() + "/.git/refs/tags"
|
||||||
log.Log(INFO, "populateTags() path =", tmp)
|
log.Log(REPO, "populateTags() path =", tmp)
|
||||||
for _, tag := range listFiles(tmp) {
|
for _, tag := range listFiles(tmp) {
|
||||||
if rs.tags[tag] == "" {
|
if rs.tags[tag] == "" {
|
||||||
log.Log(INFO, "populateTags() Adding new tag", tag)
|
log.Log(REPO, "populateTags() Adding new tag", tag)
|
||||||
rs.tagsDrop.AddText(tag)
|
// rs.tagsDrop.AddText(tag)
|
||||||
rs.tags[tag] = "origin"
|
rs.tags[tag] = "origin"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -84,60 +176,189 @@ func (rs *RepoStatus) getBranches() []string {
|
||||||
all = append(all, remotes...)
|
all = append(all, remotes...)
|
||||||
|
|
||||||
for _, branch := range all {
|
for _, branch := range all {
|
||||||
log.Log(INFO, "getBranches()", branch)
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
// return the list of dirty files (but ignores go.mod & go.sum)
|
||||||
|
func (rs *RepoStatus) DirtyList() []string {
|
||||||
|
var all []string
|
||||||
|
for _, line := range strings.Split(rs.dirtyList, "\n") {
|
||||||
|
line = strings.TrimSpace(line)
|
||||||
|
parts := strings.Split(line, " ")
|
||||||
|
if len(parts) != 2 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if parts[1] == "go.mod" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if parts[1] == "go.sum" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
all = append(all, parts[1])
|
||||||
}
|
}
|
||||||
return all
|
return all
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rs *RepoStatus) CheckDirty() bool {
|
func (rs *RepoStatus) CheckDirty() bool {
|
||||||
cmd := []string{"git", "diff-index", "--quiet", "HEAD"}
|
var start string = rs.dirtyLabel.String()
|
||||||
path := rs.realPath.String()
|
cmd := []string{"git", "status", "--porcelain"}
|
||||||
err, b, out := RunCmd(path, cmd)
|
r := shell.PathRunLog(rs.Path(), cmd, INFO)
|
||||||
if err != nil {
|
out := strings.Join(r.Stdout, "\n")
|
||||||
log.Warn("CheckDirty() b =", b)
|
if r.Error != nil {
|
||||||
log.Warn("CheckDirty() path =", path)
|
log.Warn("CheckDirty() status cmd =", cmd)
|
||||||
log.Warn("CheckDirty() out =", out)
|
log.Warn("CheckDirty() status out =", out)
|
||||||
log.Warn("CheckDirty() err =", err)
|
log.Warn("CheckDirty() status err =", r.Error)
|
||||||
log.Error(err, "CheckDirty() error")
|
log.Error(r.Error, "CheckDirty() git status error")
|
||||||
rs.dirtyLabel.SetValue("error")
|
rs.dirtyLabel.SetValue("error")
|
||||||
|
if start != "error" {
|
||||||
|
rs.NoteChange("git status is in error " + fmt.Sprint(r.Error))
|
||||||
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
if b {
|
|
||||||
log.Log(INFO, "CheckDirty() b =", b, "path =", path, "out =", out)
|
rs.dirtyList = out
|
||||||
log.Log(INFO, "CheckDirty() no", rs.realPath.String())
|
|
||||||
|
// last := out[strings.LastIndex(out, "\n")+1:]
|
||||||
|
// if last == "nothing to commit, working tree clean" {
|
||||||
|
|
||||||
|
if len(rs.DirtyList()) == 0 {
|
||||||
|
log.Log(REPO, "CheckDirty() no", rs.realPath.String())
|
||||||
rs.dirtyLabel.SetValue("no")
|
rs.dirtyLabel.SetValue("no")
|
||||||
|
if start == "" {
|
||||||
|
// don't record a change as this is the initial run
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if start != "no" {
|
||||||
|
log.Log(REPOWARN, "is no longer dirty")
|
||||||
|
rs.NoteChange("is no longer dirty")
|
||||||
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
log.Log(INFO, "CheckDirty() true", rs.realPath.String())
|
|
||||||
rs.dirtyLabel.SetValue("dirty")
|
rs.dirtyLabel.SetValue("dirty")
|
||||||
|
if start == "" {
|
||||||
|
// don't record a change as this is the initial run
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if start != "dirty" {
|
||||||
|
log.Log(REPOWARN, "is now dirty")
|
||||||
|
rs.NoteChange("is now dirty")
|
||||||
|
}
|
||||||
return true
|
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}
|
||||||
|
r := rs.Run(cmd)
|
||||||
|
if r.Error != nil {
|
||||||
|
log.Log(REPO, "git checkout error:", r.Error)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
rs.checkCurrentBranchName()
|
||||||
|
rs.checkCurrentBranchVersion()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
func (rs *RepoStatus) CheckoutBranch(branch string) (string, string) {
|
func (rs *RepoStatus) CheckoutMaster() bool {
|
||||||
// run(rs.realPath.String(), "git", "checkout " + branch)
|
if rs.CheckDirty() {
|
||||||
|
log.Log(REPO, rs.realPath.String(), "is dirty")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
mName := rs.GetMasterBranchName()
|
||||||
|
if rs.CheckoutBranch(mName) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
realname := rs.getCurrentBranchName()
|
func (rs *RepoStatus) CheckoutDevel() bool {
|
||||||
realversion := rs.getCurrentBranchVersion()
|
devel := rs.develWorkingName.String()
|
||||||
log.Log(INFO, rs.realPath.String(), "realname =", realname, "realversion =", realversion)
|
// user := rs.userWorkingName.String()
|
||||||
return realname, realversion
|
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
|
||||||
|
}
|
||||||
|
if !rs.BranchExists(bName) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
cmd := []string{"git", "checkout", bName}
|
||||||
|
r := rs.Run(cmd)
|
||||||
|
if r.Error != nil {
|
||||||
|
log.Log(REPO, "git checkout error:", r.Error)
|
||||||
|
}
|
||||||
|
|
||||||
|
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) {
|
func (rs *RepoStatus) checkoutBranch(level string, branch string) {
|
||||||
if rs.CheckDirty() {
|
if rs.CheckDirty() {
|
||||||
log.Log(INFO, "checkoutBranch() checkDirty() == true for repo", rs.realPath.String(), "looking for branch:", branch)
|
log.Log(REPO, "checkoutBranch() checkDirty() == true for repo", rs.realPath.String(), "looking for branch:", branch)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
out := run(rs.realPath.String(), "git", "checkout "+branch)
|
out := run(rs.realPath.String(), "git", "checkout "+branch)
|
||||||
log.Log(INFO, rs.realPath.String(), "git checkout "+branch, "returned", out)
|
log.Log(REPO, rs.realPath.String(), "git checkout "+branch, "returned", out)
|
||||||
|
|
||||||
realname := rs.getCurrentBranchName()
|
realname := rs.GetCurrentBranchName()
|
||||||
realversion := rs.getCurrentBranchVersion()
|
realversion := rs.GetCurrentBranchVersion()
|
||||||
log.Log(INFO, rs.realPath.String(), "realname =", realname, "realversion =", realversion)
|
log.Log(REPO, rs.realPath.String(), "realname =", realname, "realversion =", realversion)
|
||||||
|
|
||||||
switch level {
|
switch level {
|
||||||
case "master":
|
case "master":
|
||||||
rs.masterBranchVersion.SetValue(realversion)
|
rs.mainBranchVersion.SetValue(realversion)
|
||||||
case "devel":
|
case "devel":
|
||||||
rs.develBranchVersion.SetValue(realversion)
|
rs.develBranchVersion.SetValue(realversion)
|
||||||
case "user":
|
case "user":
|
||||||
|
@ -146,42 +367,80 @@ func (rs *RepoStatus) checkoutBranch(level string, branch string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rs *RepoStatus) SetMainWorkingName(s string) {
|
// attempt's to guess at what master is.
|
||||||
rs.mainWorkingName.SetValue(s)
|
// TODO: fix this properly
|
||||||
rs.masterDrop.SetLabel(s)
|
func (rs *RepoStatus) guessMainWorkingName() {
|
||||||
rs.masterDrop.SetText("guimaster")
|
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) SetDevelWorkingName(s string) {
|
func (rs *RepoStatus) guessDevelWorkingName() {
|
||||||
rs.develWorkingName.SetValue(s)
|
if rs.TagExists("guidevel") {
|
||||||
rs.develBranchVersion.SetLabel(s)
|
rs.develWorkingName.SetValue("guidevel")
|
||||||
rs.develDrop.SetLabel(s)
|
rs.develBranchVersion.SetLabel("guidevel")
|
||||||
rs.develDrop.SetText(s)
|
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(s string) {
|
func (rs *RepoStatus) setUserWorkingName() {
|
||||||
rs.userWorkingName.SetValue(s)
|
usr, _ := user.Current()
|
||||||
rs.userBranchVersion.SetLabel(s)
|
uname := usr.Username
|
||||||
rs.userDrop.SetText(s)
|
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
|
// returns "master", "devel", os.Username, etc
|
||||||
func (rs *RepoStatus) GetMasterBranchName() string {
|
func (rs *RepoStatus) GetMasterBranchName() string {
|
||||||
name := rs.masterDrop.String()
|
name := rs.mainWorkingName.String()
|
||||||
return name
|
return name
|
||||||
}
|
}
|
||||||
func (rs *RepoStatus) GetDevelBranchName() string {
|
func (rs *RepoStatus) GetDevelBranchName() string {
|
||||||
name := rs.develDrop.String()
|
name := rs.develWorkingName.String()
|
||||||
return name
|
return name
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rs *RepoStatus) GetUserBranchName() string {
|
func (rs *RepoStatus) GetUserBranchName() string {
|
||||||
name := rs.userDrop.String()
|
name := rs.userWorkingName.String()
|
||||||
return name
|
return name
|
||||||
}
|
}
|
||||||
|
|
||||||
// returns the git versions like "1.3-2-laksdjf" or whatever
|
// returns the git versions like "1.3-2-laksdjf" or whatever
|
||||||
func (rs *RepoStatus) GetMasterVersion() string {
|
func (rs *RepoStatus) GetMasterVersion() string {
|
||||||
name := rs.masterBranchVersion.String()
|
name := rs.mainBranchVersion.String()
|
||||||
return name
|
return name
|
||||||
}
|
}
|
||||||
func (rs *RepoStatus) GetDevelVersion() string {
|
func (rs *RepoStatus) GetDevelVersion() string {
|
||||||
|
@ -193,58 +452,95 @@ func (rs *RepoStatus) GetUserVersion() string {
|
||||||
return name
|
return name
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rs *RepoStatus) SetMasterVersion(s string) {
|
func (rs *RepoStatus) setMasterVersion(s string) {
|
||||||
if rs.GetMasterVersion() == s {
|
old := rs.GetMasterVersion()
|
||||||
|
if old == s {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
rs.changed = true
|
rs.mainBranchVersion.SetValue(s)
|
||||||
log.Verbose("git", rs.GetMasterBranchName(), "is now version =", s)
|
if old == "" {
|
||||||
rs.masterBranchVersion.SetValue(s)
|
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) {
|
func (rs *RepoStatus) setDevelVersion(s string) {
|
||||||
if rs.GetDevelVersion() == s {
|
old := rs.GetDevelVersion()
|
||||||
|
if old == s {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
rs.changed = true
|
if old == "" {
|
||||||
|
// don't note nothing
|
||||||
|
} else {
|
||||||
|
rs.NoteChange("devel branch has been changed from " + old + " to " + s)
|
||||||
|
}
|
||||||
rs.develBranchVersion.SetValue(s)
|
rs.develBranchVersion.SetValue(s)
|
||||||
log.Verbose("git", rs.GetDevelBranchName(), "s now version =", s)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rs *RepoStatus) SetUserVersion(s string) {
|
func (rs *RepoStatus) setUserVersion(s string) {
|
||||||
if rs.GetUserVersion() == s {
|
old := rs.GetUserVersion()
|
||||||
|
if old == s {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
rs.changed = true
|
if old == "" {
|
||||||
|
// don't note nothing
|
||||||
|
} else {
|
||||||
|
rs.NoteChange("user branch has been changed from " + old + " to " + s)
|
||||||
|
}
|
||||||
rs.userBranchVersion.SetValue(s)
|
rs.userBranchVersion.SetValue(s)
|
||||||
log.Verbose("git", rs.GetUserBranchName(), "is now version =", 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 {
|
func (rs *RepoStatus) GetStatus() string {
|
||||||
|
return rs.gitState.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rs *RepoStatus) setState() {
|
||||||
rs.changed = false
|
rs.changed = false
|
||||||
if rs.CheckDirty() {
|
if rs.CheckDirty() {
|
||||||
log.Log(INFO, "CheckDirty() true")
|
log.Log(REPO, "CheckDirty() true")
|
||||||
return "dirty"
|
rs.gitState.SetText("dirty")
|
||||||
|
return
|
||||||
}
|
}
|
||||||
if rs.userBranchVersion.String() != rs.develBranchVersion.String() {
|
if rs.GetUserVersion() != rs.GetDevelVersion() {
|
||||||
return "merge to devel"
|
rs.gitState.SetText("merge to devel")
|
||||||
|
return
|
||||||
}
|
}
|
||||||
if rs.userBranchVersion.String() != rs.masterBranchVersion.String() {
|
if rs.GetDevelVersion() != rs.GetMasterVersion() {
|
||||||
return "ready to release"
|
rs.gitState.SetText("merge to main")
|
||||||
|
return
|
||||||
}
|
}
|
||||||
if rs.lasttag.String() != rs.masterBranchVersion.String() {
|
if rs.lasttag.String() != rs.GetMasterVersion() {
|
||||||
return "ready to tag version"
|
rs.gitState.SetText("unchanged")
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if rs.CheckBranches() {
|
if rs.CheckBranches() {
|
||||||
log.Log(INFO, "Branches are Perfect")
|
log.Log(REPO, "Branches are Perfect")
|
||||||
return "PERFECT"
|
rs.gitState.SetText("PERFECT")
|
||||||
|
return
|
||||||
}
|
}
|
||||||
log.Log(INFO, rs.String(), "Branches are not Perfect")
|
log.Log(REPO, rs.String(), "Branches are not Perfect")
|
||||||
return "unknown branches"
|
rs.gitState.SetText("unknown branches")
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: make this report the error somewhere
|
// 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 {
|
func (rs *RepoStatus) CheckBranches() bool {
|
||||||
var hashCheck string
|
var hashCheck string
|
||||||
var perfect bool = true
|
var perfect bool = true
|
||||||
|
@ -265,7 +561,7 @@ func (rs *RepoStatus) CheckBranches() bool {
|
||||||
// Slice the last 4 runes
|
// Slice the last 4 runes
|
||||||
lastFour := runes[runeCount-4:]
|
lastFour := runes[runeCount-4:]
|
||||||
if string(lastFour) == "HEAD" {
|
if string(lastFour) == "HEAD" {
|
||||||
log.Log(INFO, "skip HEAD fullfile", fullfile)
|
log.Log(REPO, "skip HEAD fullfile", fullfile)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -276,17 +572,21 @@ func (rs *RepoStatus) CheckBranches() bool {
|
||||||
}
|
}
|
||||||
var cmd []string
|
var cmd []string
|
||||||
cmd = append(cmd, "git", "show", "-s", "--format=%ci", hash)
|
cmd = append(cmd, "git", "show", "-s", "--format=%ci", hash)
|
||||||
_, _, output := RunCmd(rs.realPath.String(), cmd)
|
r := shell.PathRunLog(rs.Path(), cmd, INFO)
|
||||||
|
if r.Error != nil {
|
||||||
|
log.Log(WARN, "CheckBranches() git show error:", r.Error)
|
||||||
|
}
|
||||||
// git show -s --format=%ci <hash> will give you the time
|
// git show -s --format=%ci <hash> will give you the time
|
||||||
// log.Log(INFO, fullfile)
|
// log.Log(REPO, fullfile)
|
||||||
if hash == hashCheck {
|
if hash == hashCheck {
|
||||||
log.Log(INFO, hash, output, b)
|
log.Log(REPO, "notsure why this git show is here", hash)
|
||||||
} else {
|
} else {
|
||||||
log.Warn("UNKNOWN BRANCHES IN THIS REPO")
|
// log.Log(WARN, rs.String(), hash, output, b)
|
||||||
rs.versionMessage.SetText("UNKNOWN BRANCHES")
|
// log.Log(WARN, "UNKNOWN BRANCHES IN THIS REPO", cmd)
|
||||||
|
rs.versionCmdOutput.SetText("UNKNOWN BRANCHES")
|
||||||
perfect = false
|
perfect = false
|
||||||
parts := strings.Split(b, "/")
|
// parts := strings.Split(b, "/")
|
||||||
log.Warn("git push", parts)
|
// log.Warn("git push", parts)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return perfect
|
return perfect
|
||||||
|
|
231
gitConfig.go
231
gitConfig.go
|
@ -11,6 +11,7 @@ import (
|
||||||
|
|
||||||
// GitConfig represents the parsed .git/config data
|
// GitConfig represents the parsed .git/config data
|
||||||
// type GitConfig map[string]map[string]string
|
// type GitConfig map[string]map[string]string
|
||||||
|
// TODO: switch to protobuf
|
||||||
|
|
||||||
type remote struct {
|
type remote struct {
|
||||||
url string
|
url string
|
||||||
|
@ -23,16 +24,17 @@ type branch struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type GitConfig struct {
|
type GitConfig struct {
|
||||||
core map[string]string // map[origin] = "https:/git.wit.org/gui/gadgets"
|
core map[string]string // map[origin] = "https:/git.wit.org/gui/gadgets"
|
||||||
remotes map[string]*remote // 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
|
branches map[string]*branch // map[guimaster] = origin guimaster
|
||||||
hashes map[string]string
|
submodules map[string]string
|
||||||
versions map[string]string
|
hashes map[string]string
|
||||||
|
versions map[string]string
|
||||||
}
|
}
|
||||||
|
|
||||||
type GoConfig map[string]string
|
type GoConfig map[string]string
|
||||||
|
|
||||||
func listGitDirectories() []string {
|
func ListGitDirectories() []string {
|
||||||
var all []string
|
var all []string
|
||||||
homeDir, err := os.UserHomeDir()
|
homeDir, err := os.UserHomeDir()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -49,7 +51,7 @@ func listGitDirectories() []string {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if the current path is a directory and has a .git subdirectory
|
// Check if the current path is a directory and has a .git subdirectory
|
||||||
if info.IsDir() && isGitDir(path) {
|
if info.IsDir() && IsGitDir(path) {
|
||||||
all = append(all, path)
|
all = append(all, path)
|
||||||
// fmt.Println(path)
|
// fmt.Println(path)
|
||||||
}
|
}
|
||||||
|
@ -64,8 +66,8 @@ func listGitDirectories() []string {
|
||||||
return all
|
return all
|
||||||
}
|
}
|
||||||
|
|
||||||
// isGitDir checks if a .git directory exists inside the given directory
|
// IsGitDir checks if a .git directory exists inside the given directory
|
||||||
func isGitDir(dir string) bool {
|
func IsGitDir(dir string) bool {
|
||||||
gitDir := filepath.Join(dir, ".git")
|
gitDir := filepath.Join(dir, ".git")
|
||||||
info, err := os.Stat(gitDir)
|
info, err := os.Stat(gitDir)
|
||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
|
@ -79,7 +81,13 @@ func (rs *RepoStatus) readGitConfig() error {
|
||||||
filename := filepath.Join(rs.realPath.String(), "/.git/config")
|
filename := filepath.Join(rs.realPath.String(), "/.git/config")
|
||||||
file, err := os.Open(filename)
|
file, err := os.Open(filename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 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 err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
defer file.Close()
|
defer file.Close()
|
||||||
|
|
||||||
|
@ -90,6 +98,7 @@ func (rs *RepoStatus) readGitConfig() error {
|
||||||
rs.gitConfig.core = make(map[string]string)
|
rs.gitConfig.core = make(map[string]string)
|
||||||
rs.gitConfig.remotes = make(map[string]*remote)
|
rs.gitConfig.remotes = make(map[string]*remote)
|
||||||
rs.gitConfig.branches = make(map[string]*branch)
|
rs.gitConfig.branches = make(map[string]*branch)
|
||||||
|
rs.gitConfig.submodules = make(map[string]string)
|
||||||
rs.gitConfig.versions = make(map[string]string)
|
rs.gitConfig.versions = make(map[string]string)
|
||||||
rs.gitConfig.hashes = make(map[string]string)
|
rs.gitConfig.hashes = make(map[string]string)
|
||||||
|
|
||||||
|
@ -129,6 +138,9 @@ func (rs *RepoStatus) readGitConfig() error {
|
||||||
switch currentSection {
|
switch currentSection {
|
||||||
case "core":
|
case "core":
|
||||||
rs.gitConfig.core[key] = value
|
rs.gitConfig.core[key] = value
|
||||||
|
case "pull":
|
||||||
|
// don't store git config pull settings here
|
||||||
|
// probably has 'rebase = false'
|
||||||
case "remote":
|
case "remote":
|
||||||
test, ok := rs.gitConfig.remotes[currentName]
|
test, ok := rs.gitConfig.remotes[currentName]
|
||||||
if !ok {
|
if !ok {
|
||||||
|
@ -145,7 +157,7 @@ func (rs *RepoStatus) readGitConfig() error {
|
||||||
test.url = value
|
test.url = value
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
log.Log(WARN, "error url mismatch", test.url, value)
|
log.Log(REPO, "error url mismatch", test.url, value)
|
||||||
case "fetch":
|
case "fetch":
|
||||||
if test.fetch == value {
|
if test.fetch == value {
|
||||||
continue
|
continue
|
||||||
|
@ -154,9 +166,9 @@ func (rs *RepoStatus) readGitConfig() error {
|
||||||
test.fetch = value
|
test.fetch = value
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
log.Log(WARN, "error fetch mismatch", test.fetch, value)
|
log.Log(REPO, "error fetch mismatch", test.fetch, value)
|
||||||
default:
|
default:
|
||||||
log.Log(WARN, "error unknown remote:", currentSection, currentName, "key", key, "value", value)
|
log.Log(REPO, "unknown remote:", rs.Path(), line)
|
||||||
}
|
}
|
||||||
case "branch":
|
case "branch":
|
||||||
test, ok := rs.gitConfig.branches[currentName]
|
test, ok := rs.gitConfig.branches[currentName]
|
||||||
|
@ -171,10 +183,21 @@ func (rs *RepoStatus) readGitConfig() error {
|
||||||
case "merge":
|
case "merge":
|
||||||
rs.gitConfig.branches[currentName].merge = value
|
rs.gitConfig.branches[currentName].merge = value
|
||||||
default:
|
default:
|
||||||
log.Log(WARN, "error unknown remote:", currentSection, currentName, key, value)
|
log.Log(REPO, "error unknown remote:", currentSection, currentName, key, value)
|
||||||
|
log.Log(REPO, "unknown branch:", rs.Path(), line)
|
||||||
|
}
|
||||||
|
case "submodule":
|
||||||
|
// test, ok := rs.gitConfig.submodules[currentName]
|
||||||
|
switch key {
|
||||||
|
case "active":
|
||||||
|
// probably 'true' or 'false'
|
||||||
|
case "url":
|
||||||
|
rs.gitConfig.submodules[currentName] = value
|
||||||
|
default:
|
||||||
|
log.Log(REPOWARN, "unknown submodule line:", rs.Path(), line)
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
log.Log(WARN, "error unknown currentSection", currentSection, "line:", line)
|
log.Log(REPOWARN, "unknown line:", rs.Path(), line)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -185,161 +208,83 @@ func (rs *RepoStatus) readGitConfig() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// readGoMod reads and parses the go.sum file (TODO: do the go.mod file)
|
func (rs *RepoStatus) GitURL() string {
|
||||||
func (rs *RepoStatus) ReadGoMod() bool {
|
origin, ok := rs.gitConfig.remotes["origin"]
|
||||||
tmp := filepath.Join(rs.realPath.String(), "go.sum")
|
if ok {
|
||||||
gomod, err := os.Open(tmp)
|
return origin.url
|
||||||
if err != nil {
|
|
||||||
log.Log(WARN, "missing go.mod", rs.realPath.String())
|
|
||||||
rs.goConfig = nil
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
defer gomod.Close()
|
for i, s := range rs.gitConfig.remotes {
|
||||||
|
log.Log(WARN, "remote:", i, s.url)
|
||||||
tmp = filepath.Join(rs.realPath.String(), "go.sum")
|
|
||||||
gosum, err := os.Open(tmp)
|
|
||||||
if err != nil {
|
|
||||||
log.Log(WARN, "missing go.sum", rs.realPath.String())
|
|
||||||
rs.goConfig = nil
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
defer gosum.Close()
|
log.Log(WARN, "GitURL() repo has non-standard origin or is not uploaded")
|
||||||
|
return ""
|
||||||
var deps GoConfig
|
|
||||||
deps = make(GoConfig)
|
|
||||||
|
|
||||||
scanner := bufio.NewScanner(gosum)
|
|
||||||
log.Log(INFO, "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 {
|
|
||||||
if currentversion != version {
|
|
||||||
log.Log(WARN, "REPO:", rs.String(), rs.realPath.String())
|
|
||||||
log.Log(WARN, " version mismatch:", godep, version, currentversion)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
deps[godep] = version
|
|
||||||
log.Log(INFO, "\t", godep, "=", version)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
log.Log(WARN, "\t INVALID:", parts)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := scanner.Err(); err != nil {
|
|
||||||
rs.goConfig = nil
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
rs.goConfig = deps
|
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func ScanGoSrc() {
|
func (rs *RepoStatus) GitLsFiles() (bool, string) {
|
||||||
log.Log(WARN, "Scanning all go.sum files")
|
r := rs.Run([]string{"git", "ls-files"})
|
||||||
for path, rs := range windowMap {
|
output := strings.Join(r.Stdout, "\n")
|
||||||
if rs.ReadGoMod() {
|
if r.Error != nil {
|
||||||
// everything is ok
|
log.Warn("git ls-files failed err =", r.Error)
|
||||||
} else {
|
log.Warn("git ls-files failed output =", output)
|
||||||
log.Log(WARN, "failed reading go.sum repo:", path)
|
return false, output
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
return true, output
|
||||||
}
|
}
|
||||||
|
|
||||||
func ScanGitConfig() {
|
func (rs *RepoStatus) ReadOnly() bool {
|
||||||
/*
|
if rs.readOnly.String() == "true" {
|
||||||
for i, path := range listGitDirectories() {
|
return true
|
||||||
filename := filepath.Join(path, ".git/config")
|
|
||||||
_, err := readGitConfig(filename)
|
|
||||||
if err != nil {
|
|
||||||
log.Log(WARN, "repo =", i, path)
|
|
||||||
log.Log(WARN, "Error reading .git/config:", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
func (rs *RepoStatus) ScanGoSrc() {
|
|
||||||
if rs.ReadGoMod() {
|
|
||||||
log.Log(INFO, "parsed go.mod", rs.realPath.String())
|
|
||||||
} else {
|
} else {
|
||||||
log.Log(WARN, "Something went wrong parsing go.mod", rs.realPath.String())
|
return false
|
||||||
}
|
|
||||||
|
|
||||||
log.Log(WARN, "go.sum:", rs.realPath.String())
|
|
||||||
for depname, version := range rs.goConfig {
|
|
||||||
log.Log(WARN, " ", depname, version)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rs *RepoStatus) CheckGoSum() bool {
|
func (rs *RepoStatus) SetReadOnly(b bool) {
|
||||||
if rs.ReadGoMod() {
|
if b {
|
||||||
log.Log(INFO, "parsed go.mod", rs.realPath.String())
|
rs.readOnly.SetText("true")
|
||||||
} else {
|
} else {
|
||||||
log.Log(WARN, "Something went wrong parsing go.mod", rs.realPath.String())
|
rs.readOnly.SetText("false")
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
log.Log(WARN, "go.sum:", rs.realPath.String())
|
|
||||||
for depname, version := range rs.goConfig {
|
|
||||||
log.Log(WARN, " ", depname, version)
|
|
||||||
newrs, ok := windowMap[depname]
|
|
||||||
if ok {
|
|
||||||
if newrs.CheckDirty() {
|
|
||||||
log.Log(WARN, " IS DIRTY", newrs.String())
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
log.Log(WARN, " FOUND", newrs.String())
|
|
||||||
username := newrs.userWorkingName.String()
|
|
||||||
userhash, _ := newrs.gitConfig.hashes[username]
|
|
||||||
userversion, _ := newrs.gitConfig.versions[userhash]
|
|
||||||
log.Log(WARN, " username :" + username, userhash)
|
|
||||||
log.Log(WARN, " username :" + username, userversion)
|
|
||||||
if version == userversion {
|
|
||||||
log.Log(WARN, " USER VERSIONS MATCH", version, userversion)
|
|
||||||
} else {
|
|
||||||
log.Log(WARN, " USER VERSIONS MISMATCH", version, userversion)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
log.Log(WARN, " NOT FOUND", depname)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rs *RepoStatus) processBranch(branch string) {
|
func (rs *RepoStatus) processBranch(branch string) {
|
||||||
fullpath := rs.realPath.String()
|
fullpath := rs.realPath.String()
|
||||||
log.Log(WARN, " ", branch)
|
log.Log(INFO, " ", branch)
|
||||||
hash, ok := rs.gitConfig.hashes[branch]
|
hash, ok := rs.gitConfig.hashes[branch]
|
||||||
filename := fullpath + "/.git/refs/heads/" + branch
|
filename := fullpath + "/.git/refs/heads/" + branch
|
||||||
log.Log(WARN, " hash: need to open", filename)
|
log.Log(INFO, " hash: need to open", filename)
|
||||||
newhash, err := readFileToString(filename)
|
newhash, err := readFileToString(filename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Log(WARN, " hash: read failed", filename)
|
log.Log(WARN, "hash: read failed", filename, rs.String())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
log.Log(WARN, " hash:", newhash)
|
log.Log(INFO, " hash:", newhash)
|
||||||
rs.gitConfig.hashes[branch] = newhash
|
rs.gitConfig.hashes[branch] = newhash
|
||||||
if ok {
|
if ok {
|
||||||
if hash != newhash {
|
if hash != newhash {
|
||||||
log.Log(WARN, " hash changed!!!!!!!!!", hash)
|
log.Log(WARN, "hash changed", hash, rs.String())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var cmd []string
|
name, _ := rs.gitDescribeByHash(newhash)
|
||||||
cmd = append(cmd, "git", "describe", "--tags", newhash)
|
rs.gitConfig.versions[newhash] = name
|
||||||
_, _, output := RunCmd(rs.realPath.String(), cmd)
|
log.Log(INFO, " hash: version", name)
|
||||||
output = strings.TrimSpace(output)
|
}
|
||||||
rs.gitConfig.versions[newhash] = output
|
|
||||||
log.Log(WARN, " hash: version", output)
|
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
|
||||||
|
}
|
||||||
|
for i, t := range rs.Tags.tags {
|
||||||
|
base := filepath.Base(t.tag.String())
|
||||||
|
if base == branch {
|
||||||
|
log.Info("found branch tag:", i, t.tag.String())
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// log.Info("not tag:", i, t.tag.String())
|
||||||
|
}
|
||||||
|
log.Log(REPOWARN, rs.Path(), "did not find branch", branch)
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
16
go.mod
16
go.mod
|
@ -1,16 +0,0 @@
|
||||||
module go.wit.com/lib/gui/repostatus
|
|
||||||
|
|
||||||
go 1.21.4
|
|
||||||
|
|
||||||
require (
|
|
||||||
go.wit.com/gui v0.12.20
|
|
||||||
go.wit.com/lib/gadgets v0.12.16
|
|
||||||
go.wit.com/log v0.5.6
|
|
||||||
go.wit.com/widget v1.1.6
|
|
||||||
)
|
|
||||||
|
|
||||||
require (
|
|
||||||
go.wit.com/dev/alexflint/arg v1.4.5 // indirect
|
|
||||||
go.wit.com/dev/alexflint/scalar v1.2.1 // indirect
|
|
||||||
go.wit.com/dev/davecgh/spew v1.1.4 // indirect
|
|
||||||
)
|
|
14
go.sum
14
go.sum
|
@ -1,14 +0,0 @@
|
||||||
go.wit.com/dev/alexflint/arg v1.4.5 h1:asDx5f9IlfpknKjPBqqb2qndE91Pbo7ZDkWUgddfMhY=
|
|
||||||
go.wit.com/dev/alexflint/arg v1.4.5/go.mod h1:wnWc+c6z8kSdDKYriMf6RpM+FiXmo5RYp/t4FNi0MU0=
|
|
||||||
go.wit.com/dev/alexflint/scalar v1.2.1 h1:loXOcbVnd+8YeJRLey+XXidecBiedMDO00zQ26TvKNs=
|
|
||||||
go.wit.com/dev/alexflint/scalar v1.2.1/go.mod h1:+rYsfxqdI2cwA8kJ7GCMwWbNJvfvWUurOCXLiwdTtSs=
|
|
||||||
go.wit.com/dev/davecgh/spew v1.1.4 h1:C9hj/rjlUpdK+E6aroyLjCbS5MFcyNUOuP1ICLWdNek=
|
|
||||||
go.wit.com/dev/davecgh/spew v1.1.4/go.mod h1:sihvWmnQ/09FWplnEmozt90CCVqBtGuPXM811tgfhFA=
|
|
||||||
go.wit.com/gui v0.12.20 h1:mIc2DKGcpQjZdgtAj5qzkBrBDiteWfIaEpLyMnIBkh8=
|
|
||||||
go.wit.com/gui v0.12.20/go.mod h1:v2VgnOL3dlZ13KclYeedZ1cd20nQdvwjyJTNKvFX3DA=
|
|
||||||
go.wit.com/lib/gadgets v0.12.16 h1:xHz8zZiTe8xiGvfWs3s9drYUbePTT/Te58u7WXHjx0s=
|
|
||||||
go.wit.com/lib/gadgets v0.12.16/go.mod h1:9779QoRZlk+G3/MCcX4Io1eH3HTLImE0AXdAMMdw+0U=
|
|
||||||
go.wit.com/log v0.5.6 h1:rDC3ju95zfEads4f1Zm+QMkqjZ39CsYAT/UmQQs7VP4=
|
|
||||||
go.wit.com/log v0.5.6/go.mod h1:BaJBfHFqcJSJLXGQ9RHi3XVhPgsStxSMZRlaRxW4kAo=
|
|
||||||
go.wit.com/widget v1.1.6 h1:av2miF5vlohMfARA/QGPTPfgW/ADup1c+oeAOKgroPY=
|
|
||||||
go.wit.com/widget v1.1.6/go.mod h1:I8tnD3x3ECbB/CRNnLCdC+uoyk7rK0AEkzK1bQYSqoQ=
|
|
|
@ -0,0 +1,176 @@
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
// for now, even check cmd.Exit
|
||||||
|
func (rs *RepoStatus) strictRun(cmd []string) (bool, error) {
|
||||||
|
r := rs.Run(cmd)
|
||||||
|
if r.Error != nil {
|
||||||
|
log.Log(REPO, "go mod init failed err:", r.Error)
|
||||||
|
return false, r.Error
|
||||||
|
}
|
||||||
|
if r.Exit != 0 {
|
||||||
|
log.Log(REPO, "go mod init exit =", r.Exit)
|
||||||
|
return false, r.Error
|
||||||
|
}
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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) {
|
||||||
|
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")
|
||||||
|
if ok, err := rs.strictRun([]string{"rm", "-f", "go.mod", "go.sum"}); !ok {
|
||||||
|
log.Log(REPO, "rm go.mod go.sum failed", err)
|
||||||
|
return ok, err
|
||||||
|
}
|
||||||
|
if ok, err := rs.strictRun([]string{"go", "mod", "init", rs.GoPath()}); !ok {
|
||||||
|
log.Log(REPO, "go mod init failed", err)
|
||||||
|
return ok, err
|
||||||
|
}
|
||||||
|
if ok, err := rs.strictRun([]string{"go", "mod", "tidy"}); !ok {
|
||||||
|
log.Log(REPO, "go mod tidy failed", err)
|
||||||
|
return ok, 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, errors.New("MakeRedomod() logic failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rs *RepoStatus) IsReleased() bool {
|
||||||
|
if rs.GetTargetVersion() == rs.GetCurrentVersion() {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
|
@ -0,0 +1,117 @@
|
||||||
|
package repostatus
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"go.wit.com/lib/gui/shell"
|
||||||
|
"go.wit.com/log"
|
||||||
|
)
|
||||||
|
|
||||||
|
// go list -json -m go.wit.com/apps/go-clone@latest
|
||||||
|
|
||||||
|
// go list -json -m go.wit.com/apps/go-clone@latest
|
||||||
|
// {
|
||||||
|
// "Path": "go.wit.com/apps/go-clone",
|
||||||
|
// "Version": "v0.0.6",
|
||||||
|
// "Query": "latest",
|
||||||
|
// "Time": "2024-03-10T04:12:15Z",
|
||||||
|
// "GoMod": "/home/jcarr/go/pkg/mod/cache/download/go.wit.com/apps/go-clone/@v/v0.0.6.mod",
|
||||||
|
// "GoVersion": "1.22.0"
|
||||||
|
// }
|
||||||
|
|
||||||
|
type Module struct {
|
||||||
|
Path string // module path
|
||||||
|
Query string // version query corresponding to this version
|
||||||
|
Version string // module version
|
||||||
|
Versions []string // available module versions
|
||||||
|
Replace *Module // replaced by this module
|
||||||
|
Time *time.Time // time version was created
|
||||||
|
Update *Module // available update (with -u)
|
||||||
|
Main bool // is this the main module?
|
||||||
|
Indirect bool // module is only indirectly needed by main module
|
||||||
|
Dir string // directory holding local copy of files, if any
|
||||||
|
GoMod string // path to go.mod file describing module, if any
|
||||||
|
GoVersion string // go version used in module
|
||||||
|
Retracted []string // retraction information, if any (with -retracted or -u)
|
||||||
|
Deprecated string // deprecation message, if any (with -u)
|
||||||
|
Error *ModuleError // error loading module
|
||||||
|
Sum string // checksum for path, version (as in go.sum)
|
||||||
|
GoModSum string // checksum for go.mod (as in go.sum)
|
||||||
|
Reuse bool // reuse of old module info is safe
|
||||||
|
Origin Origin
|
||||||
|
}
|
||||||
|
|
||||||
|
type ModuleError struct {
|
||||||
|
Err string // the error itself
|
||||||
|
}
|
||||||
|
|
||||||
|
// An Origin describes the provenance of a given repo method result.
|
||||||
|
// It can be passed to CheckReuse (usually in a different go command invocation)
|
||||||
|
// to see whether the result remains up-to-date.
|
||||||
|
type Origin struct {
|
||||||
|
VCS string `json:",omitempty"` // "git" etc
|
||||||
|
URL string `json:",omitempty"` // URL of repository
|
||||||
|
Subdir string `json:",omitempty"` // subdirectory in repo
|
||||||
|
|
||||||
|
Hash string `json:",omitempty"` // commit hash or ID
|
||||||
|
|
||||||
|
// If TagSum is non-empty, then the resolution of this module version
|
||||||
|
// depends on the set of tags present in the repo, specifically the tags
|
||||||
|
// of the form TagPrefix + a valid semver version.
|
||||||
|
// If the matching repo tags and their commit hashes still hash to TagSum,
|
||||||
|
// the Origin is still valid (at least as far as the tags are concerned).
|
||||||
|
// The exact checksum is up to the Repo implementation; see (*gitRepo).Tags.
|
||||||
|
TagPrefix string `json:",omitempty"`
|
||||||
|
TagSum string `json:",omitempty"`
|
||||||
|
|
||||||
|
// If Ref is non-empty, then the resolution of this module version
|
||||||
|
// depends on Ref resolving to the revision identified by Hash.
|
||||||
|
// If Ref still resolves to Hash, the Origin is still valid (at least as far as Ref is concerned).
|
||||||
|
// For Git, the Ref is a full ref like "refs/heads/main" or "refs/tags/v1.2.3",
|
||||||
|
// and the Hash is the Git object hash the ref maps to.
|
||||||
|
// Other VCS might choose differently, but the idea is that Ref is the name
|
||||||
|
// with a mutable meaning while Hash is a name with an immutable meaning.
|
||||||
|
Ref string `json:",omitempty"`
|
||||||
|
|
||||||
|
// If RepoSum is non-empty, then the resolution of this module version
|
||||||
|
// failed due to the repo being available but the version not being present.
|
||||||
|
// This depends on the entire state of the repo, which RepoSum summarizes.
|
||||||
|
// For Git, this is a hash of all the refs and their hashes.
|
||||||
|
RepoSum string `json:",omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// A Tags describes the available tags in a code repository.
|
||||||
|
|
||||||
|
func runGoList(url string) (string, error) {
|
||||||
|
ver, err := getLatestVersion(url)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
r := shell.Run([]string{"go", "list", "-json", "-m", url + "@" + ver})
|
||||||
|
var modInfo Module
|
||||||
|
out := strings.Join(r.Stdout, "\n")
|
||||||
|
err = json.Unmarshal([]byte(out), &modInfo)
|
||||||
|
if err != nil {
|
||||||
|
log.Info("runGoList() r.Output =", out)
|
||||||
|
log.Info("runGoList() json.Unmarshal() error =", err)
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
log.Info("runGoList() Output.Origin.URL =", modInfo.Origin.URL)
|
||||||
|
return modInfo.Origin.URL, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func getLatestVersion(url string) (string, error) {
|
||||||
|
r := shell.Run([]string{"go", "list", "-json", "-m", url + "@latest"})
|
||||||
|
var modInfo Module
|
||||||
|
out := strings.Join(r.Stdout, "\n")
|
||||||
|
err := json.Unmarshal([]byte(out), &modInfo)
|
||||||
|
if err != nil {
|
||||||
|
log.Info("runGoList() r.Output =", out)
|
||||||
|
log.Info("runGoList() json.Unmarshal() error =", err)
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
log.Info("runGoList() Output.Version =", modInfo.Version)
|
||||||
|
return modInfo.Version, err
|
||||||
|
}
|
|
@ -0,0 +1,512 @@
|
||||||
|
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.fetchBranchByName(master)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rs *RepoStatus) FetchDevel() (error, string) {
|
||||||
|
devel := rs.GetDevelBranchName()
|
||||||
|
return rs.fetchBranchByName(devel)
|
||||||
|
}
|
||||||
|
|
||||||
|
// fetch the branch by name
|
||||||
|
func (rs *RepoStatus) fetchBranchByName(bname 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:", bname)
|
||||||
|
for name, branch := range rs.gitConfig.branches {
|
||||||
|
if name == bname {
|
||||||
|
// found the branch!
|
||||||
|
log.Log(REPO, " ", name, "remote:", branch.remote, "merge", branch.merge)
|
||||||
|
cmd := []string{"git", "fetch", branch.remote, bname + ":" + bname}
|
||||||
|
log.Log(REPO, "running:", rs.Name(), cmd)
|
||||||
|
r := rs.Run(cmd)
|
||||||
|
output := strings.Join(r.Stdout, "\n")
|
||||||
|
return r.Error, strings.TrimSpace(output)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return errors.New("branch " + bname + " 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 {
|
||||||
|
var line []string
|
||||||
|
for _, line = range rs.versionCmds {
|
||||||
|
s := strings.Join(line, " ")
|
||||||
|
if verbose {
|
||||||
|
log.Log(WARN, "RUNNING:", s)
|
||||||
|
}
|
||||||
|
rs.develMergeB.SetText(s)
|
||||||
|
r := rs.Run(line)
|
||||||
|
output := strings.TrimSpace(strings.Join(r.Stdout, "\n"))
|
||||||
|
if r.Error != nil {
|
||||||
|
log.Warn("ABEND EXECUTION")
|
||||||
|
log.Warn("error =", r.Error)
|
||||||
|
log.Warn("output =", output)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if r.Exit != 0 {
|
||||||
|
log.Warn("Returned with exit =", r.Exit)
|
||||||
|
log.Warn("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
|
||||||
|
}
|
|
@ -0,0 +1,42 @@
|
||||||
|
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()
|
||||||
|
}
|
|
@ -0,0 +1,122 @@
|
||||||
|
package repostatus
|
||||||
|
|
||||||
|
import (
|
||||||
|
"go.wit.com/gui"
|
||||||
|
"go.wit.com/lib/gadgets"
|
||||||
|
"go.wit.com/log"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (rs *RepoStatus) drawGitCommands(box *gui.Node) {
|
||||||
|
rs.gitCommandsGroup = box.NewGroup("modify")
|
||||||
|
newgrid := rs.gitCommandsGroup.NewGrid("gridnuts", 0, 0)
|
||||||
|
|
||||||
|
newgrid.NewButton("Rescan Repo", func() {
|
||||||
|
rs.Update()
|
||||||
|
})
|
||||||
|
|
||||||
|
newgrid.NewButton("CheckDirty()", func() {
|
||||||
|
if rs.CheckDirty() {
|
||||||
|
log.Log(WARN, "is dirty")
|
||||||
|
} else {
|
||||||
|
log.Log(WARN, "is not dirty")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
newgrid.NewButton("show .git/config", func() {
|
||||||
|
if rs.gitConfig == nil {
|
||||||
|
log.Log(WARN, "Nonexistant or damaged .git/config", rs.String())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
log.Log(WARN, ".git/config:", rs.realPath.String())
|
||||||
|
|
||||||
|
// The info:
|
||||||
|
for name, remote := range rs.gitConfig.remotes {
|
||||||
|
log.Log(WARN, " ", name, "url:", remote.url)
|
||||||
|
}
|
||||||
|
for name, branch := range rs.gitConfig.branches {
|
||||||
|
log.Log(WARN, " ", name, "remote:", branch.remote, "merge", branch.merge)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
newgrid.NextRow()
|
||||||
|
|
||||||
|
newgrid.NewButton("git pull", func() {
|
||||||
|
rs.GitPull()
|
||||||
|
})
|
||||||
|
newgrid.NextRow()
|
||||||
|
|
||||||
|
label := "merge " + rs.userWorkingName.String() + " to " + rs.develWorkingName.String()
|
||||||
|
rs.develMergeB = newgrid.NewButton(label, func() {
|
||||||
|
rs.Disable()
|
||||||
|
if rs.MergeUserToDevel() {
|
||||||
|
log.Warn("THINGS SEEM OK fullAutomation() returned true.")
|
||||||
|
} else {
|
||||||
|
log.Warn("THINGS FAILED fullAutomation() returned false")
|
||||||
|
}
|
||||||
|
rs.Enable()
|
||||||
|
})
|
||||||
|
|
||||||
|
label = "merge " + rs.develWorkingName.String() + " to " + rs.mainWorkingName.String()
|
||||||
|
rs.mainMergeB = newgrid.NewButton(label, func() {
|
||||||
|
rs.Disable()
|
||||||
|
if rs.MergeDevelToMaster() {
|
||||||
|
log.Warn("THINGS SEEM OK fullAutomation() returned true.")
|
||||||
|
} else {
|
||||||
|
log.Warn("THINGS FAILED fullAutomation() returned false")
|
||||||
|
}
|
||||||
|
rs.Enable()
|
||||||
|
})
|
||||||
|
newgrid.NewButton("increment version", func() {
|
||||||
|
rs.IncrementVersion()
|
||||||
|
})
|
||||||
|
newgrid.NextRow()
|
||||||
|
|
||||||
|
rs.major = gadgets.NewBasicCombobox(newgrid, "major")
|
||||||
|
rs.major.Custom = func() {
|
||||||
|
rs.setTag()
|
||||||
|
rs.generateCmd()
|
||||||
|
}
|
||||||
|
// rs.major.Hide()
|
||||||
|
newgrid.NextRow()
|
||||||
|
|
||||||
|
rs.minor = gadgets.NewBasicCombobox(newgrid, "minor")
|
||||||
|
rs.minor.Custom = func() {
|
||||||
|
rs.setTag()
|
||||||
|
rs.generateCmd()
|
||||||
|
}
|
||||||
|
// rs.minor.Hide()
|
||||||
|
newgrid.NextRow()
|
||||||
|
|
||||||
|
rs.revision = gadgets.NewBasicCombobox(newgrid, "revision")
|
||||||
|
rs.revision.Custom = func() {
|
||||||
|
rs.setTag()
|
||||||
|
rs.generateCmd()
|
||||||
|
}
|
||||||
|
// rs.revision.Hide()
|
||||||
|
newgrid.NextRow()
|
||||||
|
|
||||||
|
// newgrid.NewLabel("new tag version")
|
||||||
|
rs.newversion = newgrid.NewLabel("0.0.1")
|
||||||
|
// rs.newversion.Hide()
|
||||||
|
newgrid.NextRow()
|
||||||
|
|
||||||
|
rs.versionMessage = gadgets.NewBasicEntry(newgrid, "tag message")
|
||||||
|
rs.versionMessage.Custom = func() {
|
||||||
|
rs.generateCmd()
|
||||||
|
}
|
||||||
|
// rs.versionMessage.Hide()
|
||||||
|
newgrid.NextRow()
|
||||||
|
|
||||||
|
rs.versionCmdOutput = gadgets.NewOneLiner(newgrid, "tag cmd")
|
||||||
|
// rs.versionCmdOutput.Hide()
|
||||||
|
newgrid.NextRow()
|
||||||
|
|
||||||
|
rs.releaseVersion = newgrid.NewButton("tag and release new version", func() {
|
||||||
|
rs.Disable()
|
||||||
|
rs.MergeDevelToMaster()
|
||||||
|
})
|
||||||
|
// rs.releaseVersion.Hide()
|
||||||
|
newgrid.NextRow()
|
||||||
|
|
||||||
|
newgrid.Margin()
|
||||||
|
newgrid.Pad()
|
||||||
|
}
|
120
new.go
120
new.go
|
@ -2,59 +2,102 @@ package repostatus
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"go.wit.com/gui"
|
|
||||||
"go.wit.com/lib/gadgets"
|
"go.wit.com/lib/gadgets"
|
||||||
"go.wit.com/log"
|
"go.wit.com/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
var windowMap map[string]*RepoStatus
|
var windowMap map[string]*RepoStatus
|
||||||
|
|
||||||
func ListAll() {
|
func init() {
|
||||||
|
windowMap = make(map[string]*RepoStatus)
|
||||||
|
}
|
||||||
|
|
||||||
|
// deprecate this
|
||||||
|
func ListAllOld() {
|
||||||
for path, rs := range windowMap {
|
for path, rs := range windowMap {
|
||||||
log.Warn(rs.GetMasterVersion(), path)
|
log.Warn(rs.GetMasterVersion(), path)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewRepoStatusWindow(path string) *RepoStatus {
|
// 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 SetWorkPath(path string) {
|
||||||
|
os.Setenv("REPO_WORK_PATH", path)
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewRepoStatusWindow(path string) (error, *RepoStatus) {
|
||||||
|
path, realpath, goSrcDir, isGoLang, err := guessPaths(path)
|
||||||
|
if err != nil {
|
||||||
|
return err, nil
|
||||||
|
}
|
||||||
|
|
||||||
if windowMap[path] == nil {
|
if windowMap[path] == nil {
|
||||||
log.Log(INFO, "NewRepoStatusWindow() adding new", path)
|
log.Log(INFO, "NewRepoStatusWindow() adding new", path)
|
||||||
} else {
|
} else {
|
||||||
log.Warn("This already exists yet for path", path)
|
log.Warn("This already exists for path", path)
|
||||||
log.Warn("should return windowMap[path] here")
|
log.Warn("should return windowMap[path] here")
|
||||||
return windowMap[path]
|
return nil, windowMap[path]
|
||||||
}
|
}
|
||||||
|
|
||||||
homeDir, err := os.UserHomeDir()
|
rs := &RepoStatus{
|
||||||
if err != nil {
|
ready: false,
|
||||||
log.Log(WARN, "Error getting home directory:", err)
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
goSrcDir := filepath.Join(homeDir, "go/src")
|
rs.tags = make(map[string]string)
|
||||||
realpath := filepath.Join(goSrcDir, path)
|
rs.window = gadgets.RawBasicWindow("GO Repo Details " + path)
|
||||||
|
rs.window.Horizontal()
|
||||||
filename := filepath.Join(goSrcDir, path, ".git/config")
|
rs.window.Make()
|
||||||
|
basebox := rs.window.Box()
|
||||||
_, err = os.Open(filename)
|
group := basebox.NewGroup("stuff")
|
||||||
if err != nil {
|
primarybox := group.Box()
|
||||||
log.Log(WARN, "Error reading:", filename, err)
|
primarybox.Horizontal()
|
||||||
return nil
|
box2 := group.Box()
|
||||||
|
rs.ready = true
|
||||||
|
rs.window.Custom = func() {
|
||||||
|
rs.Hide()
|
||||||
|
log.Warn("repostatus user closed the window()")
|
||||||
}
|
}
|
||||||
|
|
||||||
rs := New(gui.TreeRoot(), path)
|
// display the status of the git repository
|
||||||
rs.draw()
|
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
|
// save ~/go/src & the whole path strings
|
||||||
rs.path.SetValue(path)
|
rs.path.SetValue(path)
|
||||||
rs.goSrcPath.SetValue(goSrcDir)
|
rs.goSrcPath.SetValue(goSrcDir)
|
||||||
rs.realPath.SetValue(realpath)
|
rs.realPath.SetValue(realpath)
|
||||||
|
|
||||||
|
// add all the tags
|
||||||
|
rs.makeTagBox(box2)
|
||||||
|
|
||||||
rs.readGitConfig()
|
rs.readGitConfig()
|
||||||
|
|
||||||
rs.readOnly.SetValue("true")
|
rs.readOnly.SetValue("true")
|
||||||
|
// ignore everything else for now
|
||||||
|
// todo: move this logic to cfgfile.go
|
||||||
if strings.HasPrefix(path, "go.wit.com") {
|
if strings.HasPrefix(path, "go.wit.com") {
|
||||||
rs.readOnly.SetValue("false")
|
rs.readOnly.SetValue("false")
|
||||||
}
|
}
|
||||||
|
@ -62,32 +105,17 @@ func NewRepoStatusWindow(path string) *RepoStatus {
|
||||||
rs.readOnly.SetValue("false")
|
rs.readOnly.SetValue("false")
|
||||||
}
|
}
|
||||||
|
|
||||||
windowMap[path] = rs
|
// tries 'master', 'main', etc.
|
||||||
|
rs.guessMainWorkingName()
|
||||||
|
// tries 'devel', etc
|
||||||
|
rs.guessDevelWorkingName()
|
||||||
|
// sets this to os.Username
|
||||||
|
rs.setUserWorkingName()
|
||||||
|
|
||||||
// todo check if a window already exists for this path
|
if isGoLang {
|
||||||
return rs
|
rs.isGoLang.SetText("true")
|
||||||
}
|
rs.goPath.SetText(path)
|
||||||
|
|
||||||
func New(p *gui.Node, path string) *RepoStatus {
|
|
||||||
rs := &RepoStatus{
|
|
||||||
hidden: true,
|
|
||||||
ready: false,
|
|
||||||
parent: p,
|
|
||||||
}
|
|
||||||
rs.tags = make(map[string]string)
|
|
||||||
rs.window = gadgets.NewBasicWindow(p, "GO Repo Details "+path)
|
|
||||||
rs.window.Horizontal()
|
|
||||||
rs.window.Make()
|
|
||||||
rs.ready = true
|
|
||||||
rs.window.Custom = func() {
|
|
||||||
// rs.hidden = true
|
|
||||||
rs.Hide()
|
|
||||||
log.Warn("repostatus user closed the window()")
|
|
||||||
}
|
}
|
||||||
windowMap[path] = rs
|
windowMap[path] = rs
|
||||||
return rs
|
return nil, rs
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
windowMap = make(map[string]*RepoStatus)
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
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
|
||||||
|
}
|
71
structs.go
71
structs.go
|
@ -7,47 +7,57 @@ import (
|
||||||
|
|
||||||
type RepoStatus struct {
|
type RepoStatus struct {
|
||||||
ready bool
|
ready bool
|
||||||
hidden bool
|
changed bool // keeps track of changes that might have happened
|
||||||
changed bool
|
changes string
|
||||||
|
tags map[string]string
|
||||||
|
InitOk bool // it takes a second or so to init these
|
||||||
|
|
||||||
// lasttagrev string
|
// used to temporarily tell the automation tools to
|
||||||
tags map[string]string
|
// 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
|
||||||
|
|
||||||
parent *gui.Node
|
window *gadgets.BasicWindow // the main window for this repo
|
||||||
|
Tags *GitTagBox // a box of all the git tags
|
||||||
window *gadgets.BasicWindow
|
|
||||||
|
|
||||||
dirtyLabel *gadgets.OneLiner
|
dirtyLabel *gadgets.OneLiner
|
||||||
|
dirtyList string // the output from git status --porcelain
|
||||||
readOnly *gadgets.OneLiner
|
readOnly *gadgets.OneLiner
|
||||||
|
gitState *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
|
path *gadgets.OneLiner
|
||||||
goSrcPath *gadgets.OneLiner
|
goSrcPath *gadgets.OneLiner
|
||||||
|
goPath *gadgets.OneLiner
|
||||||
realPath *gadgets.OneLiner
|
realPath *gadgets.OneLiner
|
||||||
|
isGoLang *gadgets.OneLiner
|
||||||
|
|
||||||
currentBranch *gadgets.OneLiner
|
currentBranch *gadgets.OneLiner
|
||||||
currentVersion *gadgets.OneLiner
|
currentVersion *gadgets.OneLiner
|
||||||
tagsDrop *gadgets.BasicDropdown
|
|
||||||
|
|
||||||
lasttag *gadgets.OneLiner
|
mainWorkingName *gadgets.OneLiner // the actual name of the primary branch
|
||||||
masterBranchVersion *gadgets.OneLiner
|
develWorkingName *gadgets.OneLiner // the actual name of the devel branch
|
||||||
develBranchVersion *gadgets.OneLiner
|
userWorkingName *gadgets.OneLiner // the actual name of the user branch
|
||||||
userBranchVersion *gadgets.OneLiner
|
develMergeB *gui.Node // button to merge from user to devel
|
||||||
|
mainMergeB *gui.Node // button to merge from devel to master
|
||||||
|
releaseVersion *gui.Node // the release version
|
||||||
|
minor *gadgets.BasicCombobox // the '3' in version v3.1.4
|
||||||
|
major *gadgets.BasicCombobox // the '1' in version v3.1.4
|
||||||
|
revision *gadgets.BasicCombobox // the '4' in version v3.1.4
|
||||||
|
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
|
||||||
|
|
||||||
mainWorkingName *gadgets.OneLiner
|
versionMessage *gadgets.BasicEntry
|
||||||
develWorkingName *gadgets.OneLiner
|
versionCmds [][]string
|
||||||
userWorkingName *gadgets.OneLiner
|
versionCmdOutput *gadgets.OneLiner
|
||||||
|
targetReleaseVersion *gadgets.OneLiner
|
||||||
develMerge *gui.Node
|
|
||||||
releaseVersion *gui.Node
|
|
||||||
|
|
||||||
// vgroup *gui.Node
|
|
||||||
minor *gadgets.BasicCombobox
|
|
||||||
major *gadgets.BasicCombobox
|
|
||||||
revision *gadgets.BasicCombobox
|
|
||||||
|
|
||||||
versionMessage *gadgets.BasicEntry
|
|
||||||
versionCmds [][]string
|
|
||||||
versionCmdOutput *gadgets.OneLiner
|
|
||||||
|
|
||||||
newversion *gui.Node
|
newversion *gui.Node
|
||||||
|
|
||||||
|
@ -55,10 +65,6 @@ type RepoStatus struct {
|
||||||
gitStatusGroup *gui.Node
|
gitStatusGroup *gui.Node
|
||||||
gitCommandsGroup *gui.Node
|
gitCommandsGroup *gui.Node
|
||||||
|
|
||||||
masterDrop *gadgets.BasicDropdown
|
|
||||||
develDrop *gadgets.BasicDropdown
|
|
||||||
userDrop *gadgets.BasicDropdown
|
|
||||||
|
|
||||||
showBranchesButton *gui.Node
|
showBranchesButton *gui.Node
|
||||||
checkBranchesButton *gui.Node
|
checkBranchesButton *gui.Node
|
||||||
|
|
||||||
|
@ -67,4 +73,7 @@ type RepoStatus struct {
|
||||||
|
|
||||||
gitConfig *GitConfig
|
gitConfig *GitConfig
|
||||||
goConfig GoConfig
|
goConfig GoConfig
|
||||||
|
|
||||||
|
switchBranchB *gui.Node
|
||||||
|
targetBranch *gui.Node
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,410 @@
|
||||||
|
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"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Tag struct {
|
||||||
|
// tracks if the tag is displayed
|
||||||
|
hidden bool
|
||||||
|
|
||||||
|
// the tag "v0.1.3"
|
||||||
|
tag *gui.Node
|
||||||
|
|
||||||
|
// the .git/ref hash
|
||||||
|
ref *gui.Node
|
||||||
|
|
||||||
|
// the .git/ref date
|
||||||
|
date *gui.Node
|
||||||
|
duration *gui.Node
|
||||||
|
|
||||||
|
// the tag comment
|
||||||
|
subject *gui.Node
|
||||||
|
|
||||||
|
// a button to delete the tag
|
||||||
|
deleteB *gui.Node
|
||||||
|
}
|
||||||
|
|
||||||
|
// a GUI box of all the tags in a repo
|
||||||
|
type GitTagBox struct {
|
||||||
|
// the box to list all the tags in
|
||||||
|
box *gui.Node
|
||||||
|
group *gui.Node
|
||||||
|
grid *gui.Node
|
||||||
|
|
||||||
|
// all the tags
|
||||||
|
tags []*Tag
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rs *RepoStatus) makeTagBox(box *gui.Node) error {
|
||||||
|
if rs.Tags != nil {
|
||||||
|
log.Log(WARN, "already scanned tags")
|
||||||
|
return errors.New("already scanned tags")
|
||||||
|
}
|
||||||
|
tagB := new(GitTagBox)
|
||||||
|
rs.Tags = tagB
|
||||||
|
tagB.group = box.NewGroup(".git tags for " + rs.String())
|
||||||
|
|
||||||
|
// tagB.group.NewButton("prune tags", func() {
|
||||||
|
// tagB.Prune()
|
||||||
|
// })
|
||||||
|
var dups *gui.Node
|
||||||
|
|
||||||
|
dups = tagB.group.NewCheckbox("Show duplicate tags").SetChecked(false)
|
||||||
|
dups.Custom = func() {
|
||||||
|
if dups.Checked() {
|
||||||
|
tagB.Prune()
|
||||||
|
} else {
|
||||||
|
for _, t := range tagB.tags {
|
||||||
|
t.Show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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
|
||||||
|
}
|
||||||
|
log.Info("tag is shown", i, t.tag.String())
|
||||||
|
rs.DeleteTag(t)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
grid := tagB.group.NewGrid("tags", 0, 0)
|
||||||
|
tagB.grid = grid
|
||||||
|
|
||||||
|
grid.NewLabel("version")
|
||||||
|
grid.NewLabel("ref")
|
||||||
|
grid.NewLabel("date")
|
||||||
|
grid.NewLabel("release subject")
|
||||||
|
// works like a typerwriter
|
||||||
|
grid.NextRow()
|
||||||
|
|
||||||
|
// 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
|
||||||
|
|
||||||
|
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, " "))
|
||||||
|
r := shell.PathRunQuiet(rs.Path(), cmd)
|
||||||
|
if r.Error != nil {
|
||||||
|
log.Warn("git for-each-ref error:", r.Error)
|
||||||
|
return r.Error
|
||||||
|
}
|
||||||
|
|
||||||
|
lines := r.Stdout
|
||||||
|
// 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])
|
||||||
|
|
||||||
|
_, stamp, dur := getGitDateStamp(parts[1])
|
||||||
|
rTag.date = grid.NewLabel(stamp)
|
||||||
|
rTag.duration = grid.NewLabel(dur)
|
||||||
|
|
||||||
|
rTag.subject = grid.NewLabel(parts[4])
|
||||||
|
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})
|
||||||
|
|
||||||
|
if rs.DoAll(all) {
|
||||||
|
log.Info("TAG DELETED", rs.String(), tagversion)
|
||||||
|
} else {
|
||||||
|
log.Info("TAG DELETE FAILED", rs.String(), 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 {
|
||||||
|
var tags []*Tag
|
||||||
|
for _, t := range rtags.tags {
|
||||||
|
tags = append(tags, t)
|
||||||
|
}
|
||||||
|
return tags
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rtags *GitTagBox) List() []*Tag {
|
||||||
|
var tags []*Tag
|
||||||
|
for _, t := range rtags.tags {
|
||||||
|
if t.hidden {
|
||||||
|
// log.Info("tag is hidden", i, t.tag.String())
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// log.Info("tag is shown", t.tag.String(), rtags.rs.String())
|
||||||
|
tags = append(tags, t)
|
||||||
|
}
|
||||||
|
return tags
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rtags *GitTagBox) Prune() {
|
||||||
|
dups := make(map[string]*Tag)
|
||||||
|
for i, t := range rtags.tags {
|
||||||
|
if t == nil {
|
||||||
|
log.Info("tag empty:", i)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
ref := t.ref.String()
|
||||||
|
_, ok := dups[ref]
|
||||||
|
if ok {
|
||||||
|
log.Info("tag is duplicate:", i, t.tag.String())
|
||||||
|
} else {
|
||||||
|
log.Info("new tag", i, t.tag.String())
|
||||||
|
dups[ref] = t
|
||||||
|
t.Hide()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// hide tags worth keeping
|
||||||
|
func (rtags *GitTagBox) PruneSmart() {
|
||||||
|
// always keep the first tag
|
||||||
|
var first bool = true
|
||||||
|
|
||||||
|
dups := make(map[string]*Tag)
|
||||||
|
for i, t := range rtags.tags {
|
||||||
|
if t == nil {
|
||||||
|
log.Info("tag empty:", i)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// check for duplicate tags
|
||||||
|
ref := t.ref.String()
|
||||||
|
_, ok := dups[ref]
|
||||||
|
if ok {
|
||||||
|
log.Info("tag is duplicate:", i, t.tag.String())
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
dups[ref] = t
|
||||||
|
|
||||||
|
// dump any tags that don't start with 'v'
|
||||||
|
//if !strings.HasPrefix(t.tag.String(), "v") {
|
||||||
|
// log.Info("tag does not start with v", i, t.tag.String())
|
||||||
|
// continue
|
||||||
|
//}
|
||||||
|
|
||||||
|
isVersion := regexp.MustCompile("v[0-9]+.[0-9]+.[0-9]+").MatchString
|
||||||
|
if isVersion(t.tag.String()) {
|
||||||
|
if first {
|
||||||
|
log.Info("keep first tag", i, t.tag.String())
|
||||||
|
t.Hide()
|
||||||
|
first = false
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
log.Info("valid tag", i, t.tag.String())
|
||||||
|
t.Hide()
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if first {
|
||||||
|
log.Info("keep first tag", i, t.tag.String())
|
||||||
|
t.Hide()
|
||||||
|
first = false
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Info("keep tag", i, t.tag.String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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)
|
||||||
|
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)
|
||||||
|
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()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rt *Tag) Hide() {
|
||||||
|
rt.hidden = true
|
||||||
|
rt.tag.Hide()
|
||||||
|
rt.ref.Hide()
|
||||||
|
rt.date.Hide()
|
||||||
|
rt.duration.Hide()
|
||||||
|
rt.subject.Hide()
|
||||||
|
rt.deleteB.Hide()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rt *Tag) Show() {
|
||||||
|
rt.hidden = false
|
||||||
|
rt.tag.Show()
|
||||||
|
rt.ref.Show()
|
||||||
|
rt.date.Show()
|
||||||
|
rt.duration.Show()
|
||||||
|
rt.subject.Show()
|
||||||
|
rt.deleteB.Show()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rs *RepoStatus) TagExists(findname string) bool {
|
||||||
|
allTags := rs.Tags.ListAll()
|
||||||
|
for _, t := range allTags {
|
||||||
|
tagname := t.TagString()
|
||||||
|
_, filename := filepath.Split(tagname)
|
||||||
|
if filename == findname {
|
||||||
|
// log.Info("found tag:", path, filename, "from", rs.Path())
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rs *RepoStatus) LocalTagExists(findname string) bool {
|
||||||
|
allTags := rs.Tags.ListAll()
|
||||||
|
for _, t := range allTags {
|
||||||
|
tagname := t.TagString()
|
||||||
|
if strings.HasPrefix(tagname, "refs/remotes") {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
path, filename := filepath.Split(tagname)
|
||||||
|
log.Log(INFO, "tag:", path, filename, "from", rs.Path())
|
||||||
|
if filename == findname {
|
||||||
|
log.Log(INFO, "found tag:", path, filename, "from", rs.Path())
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// returns true if 'taggy' is _ONLY_ a local tag
|
||||||
|
// this means you can not do a git pull or git push on it
|
||||||
|
func (rs *RepoStatus) IsOnlyLocalTag(taggy string) bool {
|
||||||
|
// first make sure the tag is actually even local
|
||||||
|
if !rs.LocalTagExists(taggy) {
|
||||||
|
// this means it's not even local now.
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
// okay, taggy exists, does it exist in a remote repo?
|
||||||
|
for _, t := range rs.Tags.ListAll() {
|
||||||
|
tagname := t.TagString()
|
||||||
|
if strings.HasPrefix(tagname, "refs/remotes") {
|
||||||
|
path, filename := filepath.Split(tagname)
|
||||||
|
if filename == taggy {
|
||||||
|
log.Log(REPOWARN, "found tag:", path, filename, "from", rs.Path())
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// we couldn't find the local tag anywhere remote, so it's probably only local
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Tag) Age() time.Duration {
|
||||||
|
const gitLayout = "Mon Jan 2 15:04:05 2006 -0700"
|
||||||
|
tagTime, _ := time.Parse(gitLayout, t.date.String())
|
||||||
|
return time.Since(tagTime)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Tag) Name() string {
|
||||||
|
return t.tag.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
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())
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Log(REPOWARN, "tag date err", t.ref.String(), t.tag.String(), err)
|
||||||
|
return time.Now(), err
|
||||||
|
}
|
||||||
|
return tagTime, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rs *RepoStatus) NewestTag() *Tag {
|
||||||
|
var newest *Tag
|
||||||
|
var newestTime time.Time
|
||||||
|
var tagTime time.Time
|
||||||
|
var err error
|
||||||
|
var allTags []*Tag
|
||||||
|
var mu sync.Mutex
|
||||||
|
|
||||||
|
allTags = make([]*Tag, 0, 0)
|
||||||
|
junk := rs.Tags.ListAll()
|
||||||
|
allTags = append(allTags, junk...)
|
||||||
|
for _, t := range allTags {
|
||||||
|
mu.Lock()
|
||||||
|
if tagTime, err = t.GetDate(); err != nil {
|
||||||
|
mu.Unlock()
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// log.Log(REPOWARN, "tag", t.ref.String(), t.date.String(), t.tag.String())
|
||||||
|
// if this is the first tag, use it
|
||||||
|
if newest == nil {
|
||||||
|
newestTime = tagTime
|
||||||
|
newest = t
|
||||||
|
}
|
||||||
|
|
||||||
|
// if the tag date is after the newest date, it's newer so use this tag
|
||||||
|
if tagTime.After(newestTime) {
|
||||||
|
newestTime = tagTime
|
||||||
|
newest = t
|
||||||
|
}
|
||||||
|
mu.Unlock()
|
||||||
|
}
|
||||||
|
return newest
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rs *RepoStatus) DumpTags() {
|
||||||
|
for _, t := range rs.Tags.ListAll() {
|
||||||
|
log.Log(REPOWARN, "tag", t.ref.String(), t.date.String(), t.tag.String())
|
||||||
|
}
|
||||||
|
}
|
342
unix.go
342
unix.go
|
@ -1,16 +1,18 @@
|
||||||
// This is a simple example
|
|
||||||
package repostatus
|
package repostatus
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"os/user"
|
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/go-cmd/cmd"
|
||||||
|
"go.wit.com/lib/gui/shell"
|
||||||
"go.wit.com/log"
|
"go.wit.com/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -115,60 +117,16 @@ func splitVersion(version string) (a, b, c string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// temp hack. fix this
|
func (rs *RepoStatus) Run(cmd []string) cmd.Status {
|
||||||
func runCmd(path string, parts []string) (error, bool, string) {
|
path := rs.realPath.String()
|
||||||
return RunCmd(path, parts)
|
r := shell.PathRun(path, cmd)
|
||||||
}
|
output := strings.Join(r.Stdout, "\n")
|
||||||
|
if r.Error != nil {
|
||||||
func RunCmd(workingpath string, parts []string) (error, bool, string) {
|
log.Log(WARN, "cmd:", cmd)
|
||||||
if len(parts) == 0 {
|
log.Log(WARN, "ouptput:", output)
|
||||||
log.Warn("command line was empty")
|
log.Log(WARN, "failed with error:", r.Error)
|
||||||
return errors.New("empty"), false, ""
|
|
||||||
}
|
}
|
||||||
if parts[0] == "" {
|
return r
|
||||||
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)
|
|
||||||
}
|
|
||||||
|
|
||||||
tmp := string(output)
|
|
||||||
tmp = strings.TrimSpace(tmp)
|
|
||||||
|
|
||||||
// Print the output
|
|
||||||
return nil, true, tmp
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the path to the package
|
// Set the path to the package
|
||||||
|
@ -190,19 +148,35 @@ func IsDirectory(path string) bool {
|
||||||
return info.IsDir()
|
return info.IsDir()
|
||||||
}
|
}
|
||||||
|
|
||||||
func VerifyLocalGoRepo(gorepo string) bool {
|
func (rs *RepoStatus) Exists(filename string) bool {
|
||||||
// Get current user
|
if rs == nil {
|
||||||
usr, err := user.Current()
|
log.Warn("rs == nil for Exists()")
|
||||||
|
panic(-1)
|
||||||
|
}
|
||||||
|
testf := filepath.Join(rs.Path(), 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 {
|
if err != nil {
|
||||||
log.Error(err, "VerifyLocalGoRepo() thinks you should switch to Ultrix")
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
return true
|
||||||
// Form the path to the home Git directory
|
|
||||||
gitDir := filepath.Join(usr.HomeDir, "go/src/", gorepo, ".git")
|
|
||||||
|
|
||||||
log.Log(INFO, "go directory:", gitDir)
|
|
||||||
return IsDirectory(gitDir)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func readFileToString(filename string) (string, error) {
|
func readFileToString(filename string) (string, error) {
|
||||||
|
@ -212,3 +186,239 @@ func readFileToString(filename string) (string, error) {
|
||||||
}
|
}
|
||||||
return strings.TrimSpace(string(data)), nil
|
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)
|
||||||
|
r := rs.Run(cmd)
|
||||||
|
if r.Error != nil {
|
||||||
|
log.Log(WARN, "doAll() err =", r.Error)
|
||||||
|
log.Log(WARN, "doAll() out =", r.Stdout)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func ScanGitDirectories(srcDir string) []string {
|
||||||
|
var all []string
|
||||||
|
err := filepath.Walk(srcDir, func(path string, info os.FileInfo, err error) error {
|
||||||
|
if err != nil {
|
||||||
|
log.Log(REPOWARN, "Error accessing path:", path, err)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the path is a directory and has a .git subdirectory
|
||||||
|
if info.IsDir() && IsGitDir(path) {
|
||||||
|
all = append(all, path)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Log(REPOWARN, "Error walking the path:", srcDir, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return all
|
||||||
|
}
|
||||||
|
|
||||||
|
func ScanForProtobuf(srcDir string) ([]string, []string, error) {
|
||||||
|
var protofiles []string
|
||||||
|
var compiled []string
|
||||||
|
err := filepath.Walk(srcDir, func(path string, info os.FileInfo, err error) error {
|
||||||
|
if err != nil {
|
||||||
|
log.Log(REPOWARN, "Error accessing path:", path, err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if strings.HasSuffix(path, ".proto") {
|
||||||
|
//
|
||||||
|
protofiles = append(protofiles, path)
|
||||||
|
}
|
||||||
|
|
||||||
|
if strings.HasSuffix(path, ".pb.go") {
|
||||||
|
compiled = append(compiled, path)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
|
return protofiles, compiled, err
|
||||||
|
}
|
||||||
|
|
111
update.go
111
update.go
|
@ -8,6 +8,66 @@ import (
|
||||||
"go.wit.com/log"
|
"go.wit.com/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func (rs *RepoStatus) gitBranchAll() {
|
||||||
|
r := rs.Run([]string{"git", "branch", "--all"})
|
||||||
|
if r.Error != nil {
|
||||||
|
log.Log(WARN, "git branch failed string =", rs.String())
|
||||||
|
log.Log(WARN, "git branch failed realpath =", rs.realPath.String())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for _, s := range r.Stdout {
|
||||||
|
rs.targetBranch.AddText(s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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() {
|
func (rs *RepoStatus) Update() {
|
||||||
if !rs.Ready() {
|
if !rs.Ready() {
|
||||||
log.Log(WARN, "can't update yet. ready is false")
|
log.Log(WARN, "can't update yet. ready is false")
|
||||||
|
@ -16,36 +76,7 @@ func (rs *RepoStatus) Update() {
|
||||||
}
|
}
|
||||||
log.Log(INFO, "Update() START")
|
log.Log(INFO, "Update() START")
|
||||||
duration := timeFunction(func() {
|
duration := timeFunction(func() {
|
||||||
// do things that are safe even if the git tree is dirty
|
rs.updateNew()
|
||||||
// rs.path.SetValue(rs.repopath)
|
|
||||||
rs.getCurrentBranchName()
|
|
||||||
// rs.window.SetTitle(rs.repopath + " GO repo Details")
|
|
||||||
rs.getCurrentBranchVersion()
|
|
||||||
rs.getLastTagVersion()
|
|
||||||
rs.populateTags()
|
|
||||||
rs.CheckDirty()
|
|
||||||
|
|
||||||
if rs.dirtyLabel.String() != "no" {
|
|
||||||
log.Warn("dirty label != no. actual value:", rs.dirtyLabel.String())
|
|
||||||
rs.DisableEverything()
|
|
||||||
rs.CheckBranches()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
master := rs.masterDrop.String()
|
|
||||||
devel := rs.develDrop.String()
|
|
||||||
user := rs.userDrop.String()
|
|
||||||
|
|
||||||
// rs.CheckDirty() this runs
|
|
||||||
log.Log(INFO, "checkoutBranch", master)
|
|
||||||
rs.checkoutBranch("master", master)
|
|
||||||
log.Log(INFO, "checkoutBranch", devel)
|
|
||||||
rs.checkoutBranch("devel", devel)
|
|
||||||
log.Log(INFO, "checkoutBranch", user)
|
|
||||||
rs.checkoutBranch("user", user)
|
|
||||||
|
|
||||||
rs.recommend()
|
|
||||||
rs.CheckBranches()
|
|
||||||
})
|
})
|
||||||
rs.setSpeed(duration)
|
rs.setSpeed(duration)
|
||||||
log.Log(INFO, "Update() END")
|
log.Log(INFO, "Update() END")
|
||||||
|
@ -59,9 +90,9 @@ func (rs *RepoStatus) setSpeed(duration time.Duration) {
|
||||||
}
|
}
|
||||||
rs.speedActual.SetValue(s)
|
rs.speedActual.SetValue(s)
|
||||||
|
|
||||||
if duration > 500*time.Millisecond {
|
if duration > 200*time.Millisecond {
|
||||||
rs.speed.SetValue("SLOW")
|
rs.speed.SetValue("SLOW")
|
||||||
} else if duration > 100*time.Millisecond {
|
} else if duration > 50*time.Millisecond {
|
||||||
rs.speed.SetValue("OK")
|
rs.speed.SetValue("OK")
|
||||||
} else {
|
} else {
|
||||||
rs.speed.SetValue("FAST")
|
rs.speed.SetValue("FAST")
|
||||||
|
@ -81,7 +112,7 @@ func (rs *RepoStatus) DisableEverything() {
|
||||||
rs.versionMessage.Disable()
|
rs.versionMessage.Disable()
|
||||||
|
|
||||||
// disable the merge devel to master button
|
// disable the merge devel to master button
|
||||||
rs.develMerge.Disable()
|
rs.develMergeB.Disable()
|
||||||
|
|
||||||
// disable the tag a new version button
|
// disable the tag a new version button
|
||||||
rs.releaseVersion.Disable()
|
rs.releaseVersion.Disable()
|
||||||
|
@ -91,7 +122,7 @@ func (rs *RepoStatus) DisableEverything() {
|
||||||
func (rs *RepoStatus) EnableMergeDevel() {
|
func (rs *RepoStatus) EnableMergeDevel() {
|
||||||
rs.DisableEverything()
|
rs.DisableEverything()
|
||||||
|
|
||||||
rs.develMerge.Enable()
|
rs.develMergeB.Enable()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rs *RepoStatus) Disable() {
|
func (rs *RepoStatus) Disable() {
|
||||||
|
@ -113,10 +144,14 @@ func (rs *RepoStatus) EnableSelectTag() {
|
||||||
|
|
||||||
// disable adding a tag message
|
// disable adding a tag message
|
||||||
rs.versionMessage.Enable()
|
rs.versionMessage.Enable()
|
||||||
rs.versionMessage.SetText("")
|
|
||||||
|
|
||||||
rs.develMerge.SetLabel("ready to release")
|
rs.develMergeB.SetLabel("ready to release")
|
||||||
|
|
||||||
// force there to be a commit message
|
if len(rs.versionMessage.String()) == 0 {
|
||||||
rs.releaseVersion.Disable()
|
// force there to be a commit message
|
||||||
|
rs.releaseVersion.Disable()
|
||||||
|
} else {
|
||||||
|
rs.generateCmd()
|
||||||
|
rs.releaseVersion.Enable()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue