Compare commits

..

No commits in common. "master" and "v0.16.4" have entirely different histories.

25 changed files with 1691 additions and 1440 deletions

3
.gitignore vendored
View File

@ -4,5 +4,4 @@ go.sum
/resources/*.so
myrepos
autotypist
guireleaser
files/
guireleases

125
Makefile
View File

@ -1,125 +1,32 @@
VERSION = $(shell git describe --tags)
BUILDTIME = $(shell date +%Y.%m.%d)
all: build
reset
./autotypist
all: install
stderr: build
echo "writing to /tmp/autotypist.stderr"
./autotypist >/tmp/autotypist.stderr 2>&1
goimports:
reset
goimports -w *.go
# // to globally reset paths:
# // gofmt -w -r "go.wit.com/gui -> go.wit.com/gui/gui" .
vet:
GO111MODULE=off go vet
build:
echo "build it!"
touch resources/blank.so
-rm resources/*.so
-mkdir resources/
-cp -a ~/go/src/go.wit.com/toolkits/*/*.so resources/
touch resources/blank.so
GO111MODULE=off go build \
-ldflags "-X main.VERSION=${VERSION} -X main.BUILDTIME=${BUILDTIME} -X gui.GUIVERSION=${VERSION}"
cp -a ~/go/src/go.wit.com/toolkits/*.so resources/
go build -v -x
clean:
rm -f go.*
-rm resources/*.so
touch resources/blank.so
install: goimports
touch resources/blank.so
-rm resources/*.so
# -cp -a ~/go/src/go.wit.com/toolkits/*/*.so resources/
touch resources/blank.so
GO111MODULE=off go install \
-ldflags "-X main.VERSION=${VERSION} -X main.BUILDTIME=${BUILDTIME} -X gui.GUIVERSION=${VERSION}"
install:
rm -f ~/go/src/go.wit.com/toolkits/*.so
go install -v -x
autotypist
check-git-clean:
@git diff-index --quiet HEAD -- || (echo "Git repository is dirty, please commit your changes first"; exit 1)
curl-help:
curl --silent http://localhost:9419/help
redomod:
rm -f go.*
GO111MODULE= go mod init
GO111MODULE= go mod tidy
curl-rescan-All:
curl --silent http://localhost:9419/rescanAll
curl-whitelist-stuff:
curl --silent http://localhost:9419/whitelist?repo=go.wit.com/dev/test/gogit2
curl --silent http://localhost:9419/whitelist?repo=git.wit.org/jcarr/clone-gitea
curl-setBranchesToMasterB:
curl --silent http://localhost:9419/setBranchesToMasterB
# report on the release
findNext:
curl --silent http://localhost:9419/findNext
showNext:
curl --silent http://localhost:9419/showNext
doRelease:
reset
make showNext
sleep 10
curl --silent http://localhost:9419/doRelease
curl-setCurrent-go-wit-com-gui:
curl --silent http://localhost:9419/setCurrentRepo?repo=go.wit.com/gui
curl-setCurrent-go-clone:
curl --silent http://localhost:9419/setCurrentRepo?repo=go.wit.com/apps/go-clone
make showNext
curl-setTargetVersion-virtigo-v0.1.1:
curl --silent http://localhost:9419/setTargetVersion?version=v0.1.1
# CAN NOT HAVE v0.6 -- MUST BE v0.6.0
curl-setTargetVersion-go-clone-v0.6.0:
curl --silent "http://localhost:9419/setTargetVersion?repo=go-clone&version=v0.6.0"
curl-incrementAllTargetVersions:
curl --silent http://localhost:9419/setAllTargetVersions
# report on the release
list-release-notdone:
curl --silent http://localhost:9419/releaseList?readonly=true
safe-build: install
# forge list --private
wit-test install --verbose
# cd ~/go/src/go.wit.com/lib/xgb/ && time GUIRELEASE_REASON="safe-build" guireleaser --gui gocui --gui-verbose --gui-file ../../toolkits/gocui/gocui.so >/tmp/forge.log 2>&1
rm -f go.* ; git checkout go.mod ; cd ~/go/src/go.wit.com/lib/xgb/ && time GUIRELEASE_REASON="safe-build" guireleaser --gui andlabs
build-quick: install
wit-test install --verbose
# rm -f go.* ; git checkout go.mod ;cd ~/go/src/go.wit.com/lib/xgb/ && time GUIRELEASE_REASON="safe-build" guireleaser --gui andlabs quick
sudo "wit update"
autocomplete:
guireleaser --bash > ~/.local/share/bash-completion/completions/guireleaser
test-build-force:
GUIRELEASE_REASON="safe-build" guireleaser --gui andlabs --force
# time GUIRELEASE_REASON="safe-build" make test-build
test-build:
wit-test install --verbose
rm ~/go/bin/forged
cd ~/go/src/go.wit.com/lib/xgb/ && rm -f go.*
cd ~/go/src/go.wit.com/lib/xgb/ && git checkout go.mod
cd ~/go/src/go.wit.com/lib/xgb/ && time guireleaser --gui andlabs
cd ~/go/src/go.wit.com/apps/guireleaser
wit-test debian --verbose
do-aptly
# time GUIRELEASE_REASON="safe-build" make test-build-quick
test-build-quick:
wit-test install --verbose
rm ~/go/bin/forged
cd ~/go/src/go.wit.com/lib/xgb/ && rm -f go.*
cd ~/go/src/go.wit.com/lib/xgb/ && git checkout go.mod
cd ~/go/src/go.wit.com/lib/xgb/ && time guireleaser --gui andlabs quick
cd ~/go/src/go.wit.com/apps/guireleaser
wit-test debian --verbose
do-aptly

8
TODO
View File

@ -1,8 +0,0 @@
notes on what to fix next
go-args make patches for alexflint
go-mod-clean --restore *.pb.go files
go-mod-clean set ctime on files
guireleaser change "title small" to the package being updated"

85
argv.go
View File

@ -1,85 +0,0 @@
package main
import (
"fmt"
"os"
"os/user"
)
/*
this parses the command line arguements
this enables command line options from other packages like 'gui' and 'log'
*/
type args struct {
Quick *QuickCmd `arg:"subcommand:quick" help:"only do repos with patches"`
DryRun bool `arg:"--dry-run,env:DRYRUN" help:"don't actually do the release"`
Minor bool `arg:"--minor" help:"increment minor verion numbers"`
Protobuf bool `arg:"--protobuf" help:"increment protobuf repos"`
Verbose bool `arg:"--verbose" help:"talk alot"`
Full bool `arg:"--full" help:"build every package"`
Reason string `arg:"--reason" help:"tag message"`
Force bool `arg:"--force" help:"try harder than normal"`
Port int `arg:"--port" default:"9419" help:"do fun stuff with curl"`
Bash bool `arg:"--bash" help:"generate bash completion"`
BashAuto []string `arg:"--auto-complete" help:"does the actual autocompletion"`
}
type QuickCmd struct {
List *EmptyCmd `arg:"subcommand:list" help:"list available patches"`
Show *EmptyCmd `arg:"subcommand:show" help:"show a specific patch"`
NoLibs *EmptyCmd `arg:"subcommand:show" help:"skip libraries that aren't changed"`
}
type EmptyCmd struct {
}
func (a args) Description() string {
return `
Example usage:
guireleaser go.wit.com/apps/go-clone --increment --release --dry-run --reason "blerg"
This will pull down the go sources and
the repositories in the go.sum file using git clone`
}
func (args) Version() string {
return "guireleaser " + VERSION
}
/*
handles shell autocomplete
*/
func (a args) DoAutoComplete(argv []string) {
switch argv[0] {
case "checkout":
usr, _ := user.Current()
fmt.Println("user devel master " + usr.Username)
case "commit":
fmt.Println("--all")
case "config":
fmt.Println("add fix list delete")
case "list":
fmt.Println("--all --mine --favorites --private")
case "pull":
fmt.Println("--all --mine --favorites --private")
case "patch":
fmt.Println("--list --submit --show")
case "dirty":
fmt.Println("--show-files")
case "user":
fmt.Println("--force")
case "devel":
fmt.Println("--force")
case "master":
fmt.Println("--force")
default:
if argv[0] == ARGNAME {
// list the subcommands here
fmt.Println("--bash quick")
}
}
os.Exit(0)
}

View File

@ -1,259 +0,0 @@
// This is a simple example
package main
import (
"errors"
"fmt"
"os"
"strings"
"time"
"go.wit.com/lib/gui/shell"
"go.wit.com/log"
)
func doRelease() error {
check := me.current
log.Info("doRelease() on", me.current.GetGoPath())
if !findOk {
log.Info("doRelease() immediately end something went wrong last time. findOk == false")
return fmt.Errorf("findOK = false %s", check.GetGoPath())
}
// double check release version logic
if me.release.releaseVersionB.String() != "release version "+me.release.version.String() {
log.Warn("something went wrong with the release.version:", me.release.version.String())
return fmt.Errorf("GUI lied %s", check.GetGoPath())
}
if strings.HasPrefix(me.release.version.String(), "v") {
log.Warn("everything is ok. version starts with v.", me.release.version.String())
} else {
log.Warn("version does not start with v.", me.release.version.String())
return fmt.Errorf("release does not start with a v %s", check.GetGoPath())
}
if shell.Exists("go.mod") {
log.Info("go.mod exists ok")
} else {
pwd, _ := os.Getwd()
log.Info("go.mod missing in working dir", pwd)
return fmt.Errorf("go.mod missing %s", check.GetGoPath())
}
curName := me.current.GetCurrentBranchName()
mName := me.current.GetMasterBranchName()
if curName != mName {
log.Info("\trepo is not working from main branch", curName, "!=", mName)
return fmt.Errorf("not on main branch %s", check.GetGoPath())
}
if alreadyDone(check) {
// means it was already published
// protects against logic errors that might result
// in an infinite loop
log.Info("doRelease() WARNING. should have never gotten here. return true. already done", check.GetGoPath())
log.Info("doRelease() WARNING. should have never gotten here. return true. already done", check.GetGoPath())
log.Info("doRelease() WARNING. should have never gotten here. return true. already done", check.GetGoPath())
check.ReloadCheck()
return fmt.Errorf("already released %s", check.GetGoPath())
}
// check if the git tag already exists somehow
testtag := me.release.version.String()
if check.LocalTagExists(testtag) {
log.Info("TAG ALREADY EXISTS", testtag)
return log.Errorf("%s TAG ALREADY EXISTS %s", check.FullPath, testtag)
} else {
log.Info("TAG IS NEW", testtag)
}
if me.forge.Config.IsPrivate(me.current.GetGoPath()) {
// do not self update private repos
log.Info("This is a private repo.")
var retag [][]string
retag = append(retag, []string{"git", "tag", "-m", me.releaseReasonS, me.release.version.String()})
retag = append(retag, []string{"git", "push", "origin", me.release.version.String()})
if !me.current.RunAll(retag) {
log.Info("retag failed")
findOk = false
return fmt.Errorf("RETAG FAILED %s", check.GetGoPath())
}
return skipToNext()
}
me.done = append(me.done, me.current.GetGoPath())
if err := me.forge.FinalGoDepsCheckOk(check, true); err != nil {
msg := fmt.Sprint("the go.mod file is wrong. fix it here?", check.GetGoPath())
badExit(errors.New(msg))
return fmt.Errorf("FinalGoDeps %s err %v", check.GetGoPath(), err)
}
if check.GetGoPath() == me.startRepo.GetGoPath() {
log.Info("CAN NOT SELF UPDATE.", check.GetGoPath(), "is the same as os.Getwd()")
log.Info("go get must be run from somewhere else other than startRepo")
log.Info("chdir to autotypist if it exists")
msg := fmt.Sprint("CAN NOT SELF UPDATE.", check.GetGoPath(), "is the same as os.Getwd()")
badExit(errors.New(msg))
}
if !me.startRepo.Exists("go.mod") {
log.Info("go.sum missing in", me.startRepo.GetGoPath())
log.Info("pick a different repo here")
log.Info("todo: error out earlier knowing this will upgrade")
log.Info("versions", me.startRepo.GetTargetVersion(), me.startRepo.GetMasterVersion())
panic("redo go.sum")
}
log.Info("\ttag and push", curName, me.release.version.String(), me.releaseReasonS)
if err := check.ValidGoSum(); err != nil {
log.Info("ValidGoSum() error", check.GetGoPath(), err)
msg := fmt.Sprint("ValidGoSum() error", check.GetGoPath(), err)
badExit(errors.New(msg))
}
// this is the final check. even here, just to be a total asshole
// I rerun go mod init and go mod tidy
// the re-parse all the results
// this is the last and final check.
// believe it or not, I've seen this fail. It's not worth being careful here
// or liberal about it. if it doesn't work, yep, you are stuck here you bastard
// (bastard being me. I designed this to be so annoying that if it makes it
// past this point it always works. that is the whole point of this code. NEVER
// EVER FAIL PAST THIS POINT
// )
// so let's do it: let's run go-mod-clean strict
// then reparse everything
_, err := check.RunVerboseOnError([]string{"go-mod-clean", "strict"})
if err != nil {
badExit(err)
}
var all [][]string
var autogen []string
all = append(all, []string{"git", "add", "-f", "go.mod"})
autogen = append(autogen, "go.mod")
if check.GoInfo.GoPrimitive {
// don't add go.sum here. TODO: check for go.sum file and fail
} else {
all = append(all, []string{"git", "add", "-f", "go.sum"})
autogen = append(autogen, "go.sum")
}
if ok, compiled, err := me.current.IsProtobuf(); ok {
log.Info("\tIsProtobuf() == true")
if err != nil {
log.Info("\tERROR: There are protobuf files, but they are not compiled")
log.Info("\tERROR: can not continue")
msg := fmt.Sprint("ERROR: There are protobuf files, but they are not compiled")
badExit(errors.New(msg))
}
log.Info("\tshould add the protobuf files here")
log.Info("\tcompiled files found:", compiled)
for _, s := range compiled {
log.Info("\tcompiled file found:", s)
all = append(all, []string{"git", "add", "-f", s})
autogen = append(autogen, s)
}
} else {
log.Info("\tIsProtobuf() == false")
}
all = append(all, []string{"git", "commit", "-m", me.releaseReasonS})
all = append(all, []string{"git", "push"})
all = append(all, []string{"git", "tag", "-m", me.releaseReasonS, me.release.version.String()})
all = append(all, []string{"git", "push", "origin", me.release.version.String()})
// save the autogenerated files in git metadata (aka: notes)
cname := check.GetCurrentBranchName()
if err := check.AutogenSave(autogen, cname, true); err != nil {
log.Info("AutogenSave() error", err)
msg := fmt.Sprint("AutogenSave() error", err)
badExit(errors.New(msg))
}
if !me.current.RunAll(all) {
log.Info("failed to make new release", me.release.version.String())
findOk = false
return fmt.Errorf("setting findOK = false %s", check.GetGoPath())
}
log.Info("RELEASE OK")
// 'publish' the version to the golang package versioning system
if !doPublishVersion() {
time.Sleep(3 * time.Second)
// this can fail to update, try it again after sleep(3s)
if !doPublishVersion() {
log.Info("PUBLISH FAILED gopath=%s", check.GetGoPath())
findOk = false
return fmt.Errorf("PUBLISH FAILED gopath=%s", check.GetGoPath())
}
}
log.Info("PUBLISH OK")
// me.current.SetGoState("RELEASED")
// unwind and re-tag. Now that the go.mod and go.sum are published, revert
// to the development branch
if !me.current.RevertMasterToDevel() {
log.Info("Revert Failed")
findOk = false
return fmt.Errorf("REVERT FAILED %s", check.GetGoPath())
}
// update tag
var retag [][]string
retag = append(retag, []string{"git", "tag", "--delete", me.release.version.String()})
retag = append(retag, []string{"git", "push", "--delete", "origin", me.release.version.String()})
retag = append(retag, []string{"git", "tag", "-m", me.releaseReasonS, me.release.version.String()})
retag = append(retag, []string{"git", "push", "origin", me.release.version.String()})
if !me.current.RunAll(retag) {
log.Info("retag failed")
findOk = false
return fmt.Errorf("RETAG FAILED %s", check.GetGoPath())
}
log.Info("EVERYTHING OK. RERELEASED", me.current.GetGoPath())
return nil
}
// this pulls the new tag from the golang package repository
// to insert the new version
func doPublishVersion() bool {
gopath := me.current.GetGoPath()
docmd := []string{"go", "get", "-v", gopath + "@" + me.release.version.String()}
log.Info("SHOULD RUN cmd HERE:", docmd)
if me.forge.Config.IsPrivate(me.current.GetGoPath()) {
// do not self update private repos
log.Info("This is a private repo and can not be self checked")
return true
}
// try to pull from google
if gopath == me.startRepo.GetGoPath() {
log.Info("CAN NOT SELF UPDATE. cmd =", docmd)
log.Info("go get must be run from somewhere else other than startRepo")
log.Info("chdir to autotypist if it exists")
msg := fmt.Sprint("CAN NOT SELF UPDATE. cmd =", docmd)
badExit(errors.New(msg))
}
// publish go.mod & go.sum for use with go
os.Unsetenv("GO111MODULE")
log.Info("TRYING TO SELF UPDATE HERE. cmd =", docmd)
result := me.startRepo.Run(docmd)
if result.Error != nil {
log.Info("SELF UPDATE FAILED. error =", result.Error)
log.Info("SELF UPDATE FAILED. exit =", result.Exit)
log.Info("SELF UPDATE FAILED. out =", result.Stdout)
log.Info("SELF UPDATE FAILED")
return false
}
if result.Exit != 0 {
log.Info("SELF UPDATE FAILED. error =", result.Error)
log.Info("SELF UPDATE FAILED. exit =", result.Exit)
log.Info("SELF UPDATE FAILED. out =", result.Stdout)
log.Info("SELF UPDATE FAILED")
return false
}
log.Info("SELF UPDATE OK. out =", strings.Join(result.Stdout, "\n"))
log.Info("SELF UPDATE WORKED")
return true
}

19
exit.go
View File

@ -1,19 +0,0 @@
package main
import (
"os"
"go.wit.com/log"
)
func okExit(thing string) {
log.Info(thing, "ok")
// log.Info("Finished go-clean on", check.GetNamespace(), "ok")
me.forge.Exit()
os.Exit(0)
}
func badExit(err error) {
log.Info("forge failed: ", err, me.forge.Config.ReposDir)
os.Exit(-1)
}

View File

@ -1,167 +0,0 @@
package main
import (
"errors"
"fmt"
"os"
"path/filepath"
"go.wit.com/log"
"go.wit.com/lib/protobuf/gitpb"
)
var findCounter int
var findFix bool = false
var findOk bool = true
func checkDeps(repo *gitpb.Repo) error {
if repo.GoDeps == nil {
return fmt.Errorf("%s has GoDeps == nil", repo.GetNamespace())
}
for dep := range repo.GoDeps.IterAll() {
// log.Info(repo.GetNamespace(), dep.GoPath, dep.Version)
// check if the package in question is waiting for another package to publish
found := me.forge.FindByGoPath(dep.GoPath)
if found == nil {
return fmt.Errorf("%s has dep == nil", repo.GetNamespace(), dep.GoPath)
}
// loop through all the repos that need to be published with new go versions
all := me.found.SortByFullPath()
for all.Scan() {
check := all.Next()
if found.GetNamespace() == check.GetNamespace() {
// this package is waiting on other packages to publish
return fmt.Errorf("%s is waiting on %s", repo.GetNamespace(), found.GetNamespace())
}
}
// found package isn't being published. is the version correct?
// never check this? we are done?
/*
if found.GetLastTag() == dep.Version {
// everything is normal
} else {
return fmt.Errorf("%s version mismatch on %s (%s vs %s)", repo.GetNamespace(), found.GetNamespace(), found.GetLastTag(), dep.Version)
}
*/
}
// everything might be cool?
return nil
}
// trys to figure out if there is still something to update
// todo: redo this logic as it is terrible
// rename this findNext()
func findNext() bool {
findCounter = 0
all := me.found.SortByFullPath()
for all.Scan() {
check := all.Next()
if check.GetMasterBranchName() != check.GetCurrentBranchName() {
log.Info("YOU MUST BE ON THE MASTER BRANCH", check.GetNamespace())
continue
}
if check.IsDirty() {
log.Info("CAN NOT RELEASE DIRTY REPO", check.GetNamespace())
continue
}
if alreadyDone(check) {
log.Info("findNext() alreadyDone. WHY IS THIS STILL CHECKING?", check.GetNamespace())
continue
}
log.Info("CHECKING START:", check.GetNamespace())
if me.forge.Config.IsPrivate(check.GetNamespace()) {
log.Info("GOOD TO GO ON PRIVATE REPO", check.GetNamespace())
setCurrentRepo(check, "should be good to release", "pretty sure")
return true
}
godepsNew, err := check.GoSumFromRepo()
if err != nil {
log.Info("CHECKING go deps from repo failed", err)
continue
}
if godepsNew == nil {
// don't check godepsNew, but check to make sure go mod tidy actually ran without error
os.Unsetenv("GO111MODULE")
cmd := []string{"go", "mod", "tidy"}
err := check.RunVerbose(cmd)
if err != nil {
log.Info("go mod tidy failed. this go package needs to be examined by hand as it doesn't appear to be primitive")
os.Exit(-1)
}
// if godepsNew == nil, then this go package is a primitive and there is no go.sum file
} else {
if err := testGoDepsCheckOk(godepsNew, argv.Verbose); err != nil {
log.Info("CHECKING current repo deps failed", err)
continue
}
}
if err := me.forge.FinalGoDepsCheckOk(check, argv.Verbose); err != nil {
// if err := me.forge.FinalGoDepsCheckOk(check, false); err != nil {
log.Info("FinalGoDepsCheckOk() repo=", check.GetNamespace(), "err:", err)
log.Info("CHECKING END:", check.GetNamespace())
log.Info("")
continue
}
log.Info("GOOD TO GO ON", check.GetNamespace())
setCurrentRepo(check, "should be good to release", "pretty sure")
return true
}
if findCounter == 0 {
log.Info("NOTHING TO UPDATE. findCounter =", findCounter, "found len =", me.found.Len())
if me.found.Len() == 0 {
printDone()
okExit("")
}
} else {
log.Info("me.current is nil findCounter =", findCounter, "so set findFix =", findFix)
}
log.Info("tried to findNext() but not sure what to do next counter =", findCounter, "findFix =", findFix)
setCurrentRepo(nil, "findNext found nothing", "crap")
me.release.status.SetText("ALL DONE?")
return false
}
func setCurrentRepo(check *gitpb.Repo, s string, note string) bool {
me.current = check
if check == nil {
me.release.repo.SetText("")
me.release.version.SetText("")
me.release.releaseVersionB.SetText("nope")
me.release.version.SetText("badver")
} else {
me.release.repo.SetText(check.GetNamespace())
me.release.version.SetText(check.GetTargetVersion())
me.release.releaseVersionB.SetText("release version " + check.GetTargetVersion())
me.release.version.SetText(check.GetTargetVersion())
}
me.release.status.SetText(s)
me.release.notes.SetText(note)
// me.release.openrepo.Enable()
return true
}
func testGoDepsCheckOk(godeps *gitpb.GoDeps, verbose bool) error {
if godeps == nil {
return errors.New("testGoDepsCheckOk() godeps == nil")
}
all := godeps.SortByGoPath()
for all.Scan() {
depRepo := all.Next()
fullpath := filepath.Join(me.forge.Config.ReposDir, depRepo.GoPath)
found := me.found.FindByFullPath(fullpath)
if found == nil {
continue
}
return fmt.Errorf("dep is being upgraded %s", depRepo.GoPath)
}
return nil
}

164
globalBuildOptions.go Normal file
View File

@ -0,0 +1,164 @@
// This is a simple example
package main
import (
"os"
"path/filepath"
"go.wit.com/log"
"go.wit.com/gui"
"go.wit.com/lib/gadgets"
"go.wit.com/lib/gui/repostatus"
)
func doesExist(path string) bool {
if _, err := os.Stat(path); err != nil {
if os.IsNotExist(err) {
return false
}
}
return true
}
// only errors on bad errors
func quickCmd(fullpath string, cmd []string) bool {
var err error
var b bool
var output string
if me.autoWorkingPwd.String() != fullpath {
me.autoWorkingPwd.SetValue(fullpath)
}
if me.autoDryRun.Checked() {
log.Warn("RUN --dry-run", fullpath, cmd)
return false
} else {
log.Warn("RUN:", fullpath, cmd)
}
err, b, output = repostatus.RunCmd(fullpath, cmd)
if err != nil {
log.Warn("cmd =", cmd)
log.Warn("err =", err)
log.Warn("b =", b)
log.Warn("output =", string(output))
return false
} else if !b {
log.Warn("b =", b)
log.Warn("output =", string(output))
return true
}
log.Warn("output = ", string(output))
return true
}
func globalBuildOptions(box *gui.Node) {
vbox := box.NewVerticalBox("DISPLAYVBOX")
group1 := vbox.NewGroup("Global Build Options")
grid := group1.NewGrid("buildOptions", 2, 1)
me.mainBranch = gadgets.NewBasicCombobox(grid, "default main branch")
me.mainBranch.AddText("gitea server default")
me.mainBranch.Disable()
me.develBranch = gadgets.NewBasicCombobox(grid, "default devel branch")
me.develBranch.AddText("devel")
me.userBranch = gadgets.NewBasicCombobox(grid, "default user branch")
me.userBranch.AddText("jcarr")
grid.NewLabel("<nil>")
grid.NewButton("set working branches", func() {
log.Warn("set working branches here")
})
// gadgets.OneLiner(grid, "default user branch")
// select the branch you want to test, build and develop against
// this lets you select your user branch, but, when you are happy
// you can merge everything into the devel branch and make sure it actually
// works. Then, when that is good, merge and version everything in master
var newBranch *gui.Node
grid.NewButton("set current branch to:", func() {
log.Warn("set current branch to:", newBranch.String())
/*
me.toMoveToBranch = guiBranch.String()
setCurrentBranch.SetLabel("set all branches to " + me.toMoveToBranch)
me.mainBranch.Disable()
*/
})
newBranch = grid.NewCombobox()
newBranch.AddText("guimaster")
newBranch.AddText("master")
newBranch.AddText("main")
newBranch.AddText("guidevel")
newBranch.AddText("jcarr")
newBranch.SetText("jcarr")
me.autoWorkingPwd = gadgets.NewOneLiner(grid, "working directory (pwd)")
me.userHomePwd = gadgets.NewOneLiner(grid, "user home")
me.goSrcPwd = gadgets.NewOneLiner(grid, "go src home")
homeDir, err := os.UserHomeDir()
if err != nil {
log.Warn("Error getting home directory:", err)
homeDir = "/home/autotypist"
}
me.userHomePwd.SetText(homeDir)
srcDir := filepath.Join(homeDir, "go/src")
me.goSrcPwd.SetText(srcDir)
group2 := vbox.NewGroup("Run in every git repository")
me.stopOnErrors = group2.NewCheckbox("Stop on errors")
me.stopOnErrors.SetChecked(true)
me.autoDryRun = group2.NewCheckbox("autotypist --dry-run")
me.autoDryRun.SetChecked(true)
group2.NewButton("parse .git/config ScanGitConfig()", func() {
repostatus.ScanGitConfig()
})
group2.NewButton("parse go.sum ScanGoSrc()", func() {
repostatus.ScanGoSrc()
})
group2.NewButton("run git status", func() {
me.autoWorkingPwd.SetValue("~/go/src")
log.Warn("scanning allrepos")
for path, _ := range me.allrepos {
fullpath := "/home/jcarr/go/src/" + path
quickCmd(fullpath, []string{"git", "status"})
}
})
me.rerunGoMod = group2.NewButton("remove go.mod & go.sum", func() {
for path, _ := range me.allrepos {
fullpath := "/home/jcarr/go/src/" + path
if quickCmd(fullpath, []string{"rm", "-f", "go.mod", "go.sum"}) {
log.Info("rm go.mod FAILED in repo", fullpath, me.stopOnErrors.Bool())
if me.stopOnErrors.Bool() {
return
}
}
}
})
me.rerunGoMod = group2.NewButton("run go mod & go tidy", func() {
os.Unsetenv("GO111MODULE")
for path, _ := range me.allrepos {
fullpath := "/home/jcarr/go/src/" + path
quickCmd(fullpath, []string{"go", "mod", "init"})
quickCmd(fullpath, []string{"go", "mod", "tidy"})
}
})
me.rerunGoMod = group2.NewButton("git checkout go.mod & go.sum", func() {
for path, _ := range me.allrepos {
fullpath := "/home/jcarr/go/src/" + path
quickCmd(fullpath, []string{"git", "checkout", "go.mod"})
quickCmd(fullpath, []string{"git", "checkout", "go.sum"})
}
})
}

View File

@ -1,43 +1,155 @@
// This is a simple example
package main
import (
"go.wit.com/gui"
"go.wit.com/lib/debugger"
"go.wit.com/lib/gui/logsettings"
"go.wit.com/log"
// "go.wit.com/gui/gadgets"
)
func globalDisplaySetRepoState() {
for _, repo := range me.allrepos {
if me.autoHideReadOnly.Checked() {
if repo.status.ReadOnly() {
repo.Hide()
continue
}
}
if me.autoHidePerfect.Checked() {
if repo.dirtyLabel.String() == "PERFECT" {
repo.Hide()
continue
}
}
repo.Show()
}
}
func globalDisplayShow() {
for _, repo := range me.allrepos {
if me.autoHideReadOnly.Checked() {
if repo.status.ReadOnly() {
continue
}
}
if me.autoHidePerfect.Checked() {
if repo.dirtyLabel.String() == "PERFECT" {
continue
}
}
repo.Show()
}
}
func globalDisplayOptions(box *gui.Node) {
vbox := box.NewVerticalBox("DISPLAYVBOX")
group1 := vbox.NewGroup("Global Display Options")
group1.NewButton("Show Repository Window", func() {
globalDisplaySetRepoState()
reposwin.Toggle()
})
group1.NewButton("Create Release Window", func() {
if release.win == nil {
log.Info("Creating the Release Window")
createReleaseWindow()
log.Info("Toggling the Release Window")
release.win.Toggle()
}
log.Info("Toggling the Release Window")
release.openrepo.Disable()
for _, repo := range me.allrepos {
repo.newScan()
}
reposwin.Toggle()
release.win.Toggle()
})
group1.NewButton("Create Release Window (fullscan)", func() {
if release.win == nil {
log.Info("Creating the Release Window")
createReleaseWindow()
for _, repo := range me.allrepos {
repo.status.Update()
repo.newScan()
}
globalDisplaySetRepoState()
// open the repo window
reposwin.Toggle()
log.Info("Toggling the Release Window")
release.win.Toggle()
}
log.Info("Toggling the Release Window")
release.win.Toggle()
release.openrepo.Disable()
for _, repo := range me.allrepos {
repo.newScan()
}
})
/*
hidegrid := group1.NewGrid("hidecfg", 0, 0)
hidegrid.NewButton("Show Repository Window", func() {
if me.repos.Hidden() {
me.repos.Show()
} else {
me.repos.Hide()
}
log.Info("showing reposwin")
})
hidegrid.NextRow()
group1.NewButton("hide all", func() {
for _, repo := range me.allrepos {
repo.Hide()
}
})
group1.NewButton("show all", func() {
for repo := range me.allrepos {
repo.Show()
}
})
*/
group1 = vbox.NewGroup("prep for release")
grid := group1.RawGrid()
me.autoHideReadOnly = group1.NewCheckbox("Hide read-only repos").SetChecked(true)
me.autoHideReadOnly.Custom = func() {
if me.autoHideReadOnly.Checked() {
globalDisplaySetRepoState()
} else {
globalDisplayShow()
}
}
grid.NewButton("make prepare-release", func() {
rePrepareRelease()
me.autoHidePerfect = group1.NewCheckbox("Hide Perfectly clean repos").SetChecked(false)
me.autoHidePerfect.Custom = func() {
if me.autoHidePerfect.Checked() {
globalDisplaySetRepoState()
} else {
globalDisplayShow()
}
}
me.scanEveryMinute = group1.NewCheckbox("Scan every minute").SetChecked(false)
group1.NewButton("status.Update() all", func() {
for _, repo := range me.allrepos {
repo.status.Update()
}
})
grid.NextRow()
grid.NewButton("logging Window", func() {
group1.NewButton("rescan all", func() {
for _, repo := range me.allrepos {
repo.newScan()
}
})
group2 := vbox.NewGroup("Debugger")
group2.NewButton("logging Window", func() {
logsettings.LogWindow()
})
grid.NextRow()
grid.NewButton("Debugger Window", func() {
group2.NewButton("Debugger Window", func() {
debugger.DebugWindow()
})
}
func hidePerfect() {
for _, repo := range me.allrepos {
if repo.dirtyLabel.String() == "PERFECT" {
if repo.hidden {
continue
}
repo.Hide()
// return
}
}
}

33
globalResetOptions.go Normal file
View File

@ -0,0 +1,33 @@
package main
import (
"go.wit.com/gui"
"go.wit.com/log"
)
func globalResetOptions(box *gui.Node) {
group2 := box.NewGroup("Global Destructive Options")
buildOptions := group2.NewGrid("buildOptions", 2, 1)
buildOptions.NewLabel("start over")
me.deleteGoSrcPkgB = buildOptions.NewButton("rm ~/go/src & ~/go/pkg", func() {
for _, repo := range me.allrepos {
// status := repo.getStatus()
if repo.checkDirty() {
log.Warn("repo is dirty. commit your changes first", repo.String())
me.deleteGoSrcPkgB.SetLabel("rm ~/go/src (can't. dirty repos)")
return
}
}
log.Warn("no repos have uncommited changes")
log.Warn("TODO: check things are pushed and check every dir in go/src/")
me.deleteGoSrcPkgB.SetLabel("ARE YOU SURE?")
if me.deleteGoSrcPkgB.String() == "ARE YOU SURE?" {
fullpath := "/home/jcarr/go/"
quickCmd(fullpath, []string{"rm", "-rf", "/home/jcarr/go/src/"})
quickCmd(fullpath, []string{"chmod", "700", "-R", "/home/jcarr/go/pkg/"})
quickCmd(fullpath, []string{"rm", "-rf", "/home/jcarr/go/pkg/"})
}
})
}

101
globalTestingOptions.go Normal file
View File

@ -0,0 +1,101 @@
package main
import (
"os"
"go.wit.com/lib/gui/repostatus"
"go.wit.com/gui"
)
// things being testing
func globalTestingOptions(box *gui.Node) {
test1 := box.NewGroup("testing build")
me.autoRebuildButton = test1.NewButton("rebuild autotypist", func() {
me.autoRebuildButton.Disable()
me.autoRebuildButton.SetLabel("running....")
attemptAutoRebuild()
me.autoRebuildButton.Enable()
me.autoRebuildButton.SetLabel("rebuild autotypist")
})
/*
me.downloadEverythingButton = test1.NewButton("go get go.wit.com", func() {
me.downloadEverythingButton.Disable()
me.autoWorkingPwd.SetValue("/home/jcarr/go/src")
var perfect bool = true
repos := myrepolist()
for _, line := range repos {
log.Verbose("repo =", line)
path, _, _, _ := splitLine(line)
path = strings.TrimSpace(path)
if path == "#" {
// skip comment lines
continue
}
if doesExist("/home/jcarr/go/src/" + path) {
continue
}
// attempt to download it
quickCmd("/home/jcarr/go/src/go.wit.com", []string{"go", "get", "-v", path})
perfect = false
}
if perfect {
var notes string
notes = "you have already downloaded\neverything on go.wit.com"
me.autoWorkingPwd.SetValue(notes)
me.downloadEverythingButton.Disable()
return
} else {
var notes string
notes = "download everything failed"
me.autoWorkingPwd.SetValue(notes)
me.downloadEverythingButton.Enable()
}
})
*/
var listallB *gui.Node
listallB = test1.NewButton("go.wit.com/list", func() {
listallB.Disable()
listWindow()
listallB.Enable()
})
test1.NewButton("repostatus.ListAll()", func() {
repostatus.ListAll()
})
test1.NewButton("repostatus.ScanGoSrc()", func() {
repostatus.ScanGoSrc()
})
}
func attemptAutoRebuild() {
os.Setenv("GO111MODULE", "off")
fullpath := "/home/jcarr/go/"
quickCmd(fullpath, []string{"mkdir", "-p", "/home/jcarr/go/src/go.wit.com/apps/"})
fullpath = "/home/jcarr/go/src/go.wit.com/apps/"
quickCmd(fullpath, []string{"go", "get", "-v", "go.wit.com/apps/autotypist"})
quickCmd(fullpath, []string{"go", "get", "-v", "go.wit.com/toolkits/debian"})
quickCmd(fullpath, []string{"go", "get", "-v", "go.wit.com/toolkits/tree"})
quickCmd(fullpath, []string{"go", "get", "-v", "go.wit.com/toolkits/nocui"})
quickCmd(fullpath, []string{"go", "get", "-v", "go.wit.com/toolkits/gocui"})
quickCmd(fullpath, []string{"go", "get", "-v", "go.wit.com/toolkits/andlabs"})
fullpath = "/home/jcarr/go/src/go.wit.com/toolkits/nocui/"
quickCmd(fullpath, []string{"go", "get", "-v", "-u", "."})
quickCmd(fullpath, []string{"go", "build", "-v", "-x", "-buildmode=plugin", "-o", "../nocui.so"})
fullpath = "/home/jcarr/go/src/go.wit.com/toolkits/gocui/"
quickCmd(fullpath, []string{"go", "get", "-v", "-u", "."})
quickCmd(fullpath, []string{"go", "build", "-v", "-x", "-buildmode=plugin", "-o", "../gocui.so"})
fullpath = "/home/jcarr/go/src/go.wit.com/toolkits/andlabs/"
quickCmd(fullpath, []string{"go", "get", "-v", "-u", "."})
quickCmd(fullpath, []string{"go", "build", "-v", "-x", "-buildmode=plugin", "-o", "../andlabs.so"})
fullpath = "/home/jcarr/go/src/go.wit.com/apps/autotypist"
quickCmd(fullpath, []string{"go", "get", "-v", "-u", "."})
quickCmd(fullpath, []string{"go", "build", "-v", "-x"})
}

19
go.mod Normal file
View File

@ -0,0 +1,19 @@
module go.wit.com/apps/guireleaser
go 1.21.4
require (
go.wit.com/gui v0.14.0
go.wit.com/lib/debugger v0.13.18
go.wit.com/lib/gadgets v0.14.0
go.wit.com/lib/gui/logsettings v0.13.18
go.wit.com/lib/gui/repostatus v0.16.0
go.wit.com/log v0.13.18
)
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
go.wit.com/widget v1.1.10 // indirect
)

22
go.sum Normal file
View File

@ -0,0 +1,22 @@
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.14.0 h1:MNxWgCdLXbAf4+r0/UtItL9WE6uoAtceEX2TqCXqTzg=
go.wit.com/gui v0.14.0/go.mod h1:v4tLhOESMrt9s2kjNb0QEYz29odpIusMITmVzPJme+E=
go.wit.com/lib/debugger v0.13.18 h1:uPVehvDSNnvY5tDyIt2kbHtjFsV5Lz9witNCpTxgUc8=
go.wit.com/lib/debugger v0.13.18/go.mod h1:3DXsRIR7egiuBB9iP2o8k0nNuPOHE/AHjj7sWu40lSI=
go.wit.com/lib/gadgets v0.14.0 h1:h/8VIcJ4882Oa169uTtIsvLGnxH8UQsWbw/mE88vRjM=
go.wit.com/lib/gadgets v0.14.0/go.mod h1:lFxjMHjvOTC46Q7if1d11lhXIuFML4/xlqJUl+ehzbQ=
go.wit.com/lib/gui/logsettings v0.13.18 h1:NbhoM0h6dTMRarkWj8BSqnBGi5oAf92FkvE1NA7SpAI=
go.wit.com/lib/gui/logsettings v0.13.18/go.mod h1:mBQmNFKoeenjoYH2l1+2Wdk/I0urSD7CKTHT5qMCogE=
go.wit.com/lib/gui/repostatus v0.13.18 h1:ANypsZYTtYR8yYngR1fFvrBBOoYD9eGa59ucy31dpBY=
go.wit.com/lib/gui/repostatus v0.13.18/go.mod h1:3PoFsx/jVPpi7Yg7+Df+EBH7jddPsXSm0ETyY61qI5A=
go.wit.com/lib/gui/repostatus v0.16.0 h1:3m9Ot94mG6KMFv5fTqhkdDZsDap/Xv3oFplHfqc+DSY=
go.wit.com/lib/gui/repostatus v0.16.0/go.mod h1:pXoFZD7esRwwW7LRE+j4aFlLc7YL5k1USktPPLhl6kA=
go.wit.com/log v0.13.18 h1:XJNaQWX+8m12p3mH+kYih3zNjb0kScZDFpJa4c2TvKE=
go.wit.com/log v0.13.18/go.mod h1:BaJBfHFqcJSJLXGQ9RHi3XVhPgsStxSMZRlaRxW4kAo=
go.wit.com/widget v1.1.10 h1:bdEqqNZMlLc+T4dHKlkQG1c1N5I+x2RUewOlrn2GWng=
go.wit.com/widget v1.1.10/go.mod h1:I8tnD3x3ECbB/CRNnLCdC+uoyk7rK0AEkzK1bQYSqoQ=

132
http.go
View File

@ -1,132 +0,0 @@
package main
import (
"fmt"
"net/http"
"os"
"path/filepath"
"strings"
"go.wit.com/lib/protobuf/gitpb"
"go.wit.com/log"
)
// remove '?' part and trailing '/'
func cleanURL(url string) string {
url = "/" + strings.Trim(url, "/")
return url
}
func okHandler(w http.ResponseWriter, r *http.Request) {
var route string
route = cleanURL(r.URL.Path)
log.HttpMode(w)
defer log.HttpMode(nil)
// common http args that can be set
repoName := r.URL.Query().Get("repo")
version := r.URL.Query().Get("version")
comment := r.URL.Query().Get("comment")
switch route {
case "/help":
log.Info("list/ list modified repos")
log.Info("list?readonly=true shows every repo")
log.Info("")
log.Info("doRelease runs doRelease()")
log.Info("findNext runs findNext()")
log.Info("showNext shows the repo for doRelease()")
log.Info("setTargetVersion set the target version for findNext()")
log.Info("setAllTargetVersions?version=v0.12.4 set ever repo to target version")
log.Info("setCurrentRepo?repo=go.wit.com/gui runs setCurrentRepo(repo)")
log.Info("")
log.Info("setAllBranchesToMaster git checkout master on every repo")
log.Info("")
log.Info("setVersion?repo=go.wit.com/gui?target=0.2 attempts to set the target version to 0.2")
log.Info("")
case "/doRelease":
buttonDisable()
if err := doRelease(); err == nil {
buttonEnable()
log.Info("doRelease() worked")
} else {
log.Info("doRelease() failed")
}
case "/findNext":
me.Disable()
defer me.Enable()
if findNext() {
log.Info("findNext() found a repo")
} else {
log.Info("findNext() did not find a repo. You might be finished?")
}
log.Info("repo: " + me.release.repo.String())
log.Info("name: " + me.release.version.String())
log.Info("notes: " + me.release.notes.String())
log.Info("status: " + me.release.status.String())
if me.current == nil {
log.Info("findNext() == nil")
return
}
// log.Info(me.current.StandardHeader())
log.Info(me.forge.StandardReleaseHeader(me.current, "todoing"))
case "/setCurrentRepo":
log.Info("repo: " + repoName)
log.Info("version: " + version)
log.Info("comment: " + comment)
repo := me.forge.FindByGoPath(repoName)
if repo == nil {
log.Info("FindRepoByName() returned nil")
return
}
setCurrentRepo(repo, "HTTP", "doRelease() ?")
return
case "/showNext":
check := me.forge.FindByGoPath(me.current.GetGoPath())
if check == nil {
log.Info("boo, current is missing", me.current.GetGoPath())
return
}
testGoRepo(check)
me.forge.HumanPrintRepo(check)
log.Info("upgrade reason:", me.reason[check])
return
case "/list":
me.forge.PrintHumanTable(me.found)
return
case "/releaseList":
me.forge.PrintHumanTable(me.found)
return
default:
log.Info("BAD URL = " + route)
}
}
func testGoRepo(check *gitpb.Repo) {
data, _ := os.ReadFile(filepath.Join(check.FullPath, "go.mod"))
log.Info(string(data))
if err := me.forge.FinalGoDepsCheckOk(check, true); err == nil {
log.Info("forge.FinalGoDepsCheck(check) worked!")
} else {
log.Info("forge.FinalGoDepsCheck(check) failed. boo.")
}
}
// starts and sits waiting for HTTP requests
func startHTTP() {
http.HandleFunc("/", okHandler)
p := fmt.Sprintf(":%d", argv.Port)
log.Println("Running on port", p)
err := http.ListenAndServe(p, nil)
if err != nil {
log.Println("Error starting server:", err)
}
}

232
listWindow.go Normal file
View File

@ -0,0 +1,232 @@
// This is a simple example
package main
import (
"io/ioutil"
"net/http"
"os"
"path/filepath"
"strings"
"go.wit.com/gui"
"go.wit.com/log"
"go.wit.com/lib/gadgets"
"go.wit.com/lib/gui/repostatus"
)
var lw *gadgets.BasicWindow
var allsections []*section
type witRepo struct {
sec *section
path *gui.Node
downloadB *gui.Node
}
type section struct {
name string
hidden bool
parent *gui.Node
box *gui.Node
group *gui.Node
grid *gui.Node // where the repos are listed
hideCB *gui.Node
downloadAllB *gui.Node
witRepos []*witRepo
}
func listWindow() {
if lw != nil {
lw.Toggle()
return
}
lw = gadgets.NewBasicWindow(me.myGui, "go.wit.com repositories")
lw.Custom = func() {
log.Warn("got to close")
}
lw.Make()
lw.StandardClose()
lw.Draw()
box := lw.Box()
group := box.NewGroup("list")
group.NewButton("blah", func() {})
var lines []string
var curs *section
lines = dumpURL("https://go.wit.com/list")
for i, line := range lines {
if line == "" {
continue
}
if line[0] == '#' {
curs = NewSection(group, line)
log.Warn("new group:", line)
continue
}
log.Warn(i, line)
parts := strings.Split(line, " ")
if curs != nil {
curs.add(parts[0])
}
}
for i, sec := range allsections {
log.Info("section name:", sec.name, "hidden:", sec.hidden, i)
parts := strings.Split(sec.name, " ")
if len(parts) > 1 {
if parts[1] != "Applications" {
sec.Hide()
}
}
}
// lw.Toggle()
}
func downloadRepo(path string) bool {
log.Info("downloading", path, "here")
os.Setenv("GO111MODULE", "off")
goSrcDir := me.goSrcPwd.String()
if !quickCmd(goSrcDir, []string{"go", "get", "-v", path}) {
log.Info("go get failed")
return false
}
fullpath := filepath.Join(goSrcDir, path)
if !quickCmd(fullpath, []string{"go", "get", "-v", "-u", "."}) {
log.Info("go get depends failed")
return false
}
if me.autoDryRun.Checked() {
return false
}
return true
}
func (r *witRepo) doDownload() bool {
if me.autoDryRun.Checked() {
r.downloadB.SetLabel("uncheck --dry-run")
return false
}
if r.downloadB.String() == "downloaded" {
log.Info("skipping already downloaded", r.path.String())
return true
}
if downloadRepo(r.path.String()) {
log.Info("download", r.path.String(), "worked")
r.downloadB.SetLabel("downloaded")
r.downloadB.Disable()
} else {
r.downloadB.SetLabel("failed")
log.Info("download", r.path.String(), "failed")
return false
}
return true
}
func (s *section) add(path string) {
if s == nil {
return
}
tmp := new(witRepo)
tmp.sec = s
tmp.path = s.grid.NewLabel(path)
tmp.downloadB = s.grid.NewButton("download", func() {
lw.Disable()
tmp.doDownload()
lw.Enable()
})
if repostatus.VerifyLocalGoRepo(path) {
log.Verbose("newRepo actually exists", path)
tmp.downloadB.SetLabel("downloaded")
tmp.downloadB.Disable()
}
s.witRepos = append(s.witRepos, tmp)
}
func NewSection(parent *gui.Node, desc string) *section {
news := new(section)
news.name = desc
news.parent = parent
news.box = news.parent.NewBox("bw vbox", true)
news.group = news.box.NewGroup(desc)
news.hideCB = news.box.NewCheckbox("hide")
news.hideCB.Custom = func() {
news.toggle()
}
news.downloadAllB = news.box.NewButton("download all", func() {
lw.Disable()
log.Warn("Download all here")
for i, wrepo := range news.witRepos {
log.Warn("download:", i, wrepo.path.String())
wrepo.doDownload()
//wrepo.path.Show()
//wrepo.downloadB.Show()
}
lw.Enable()
})
news.grid = news.parent.NewGrid("sections", 2, 1)
allsections = append(allsections, news)
return news
}
func (s *section) toggle() {
log.Warn(s.name)
if s.hidden {
s.hidden = false
for i, wrepo := range s.witRepos {
log.Warn(i, wrepo.path.String())
wrepo.path.Show()
wrepo.downloadB.Show()
}
} else {
s.Hide()
}
}
func (s *section) Hide() {
s.hidden = true
s.hideCB.SetChecked(true)
for i, wrepo := range s.witRepos {
log.Warn(i, wrepo.path.String())
wrepo.path.Hide()
wrepo.downloadB.Hide()
}
}
/*
func dumpURL(url string) string {
resp, err := http.Get(url)
if err != nil {
return ""
}
defer resp.Body.Close()
return resp.Body.String()
_, err = io.Copy(os.Stdout, resp.Body)
if err != nil {
return ""
}
}
*/
func dumpURL(url string) []string {
resp, err := http.Get(url)
if err != nil {
return nil
}
defer resp.Body.Close()
bodyBytes, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil
}
return strings.Split(string(bodyBytes), "\n")
}

283
main.go
View File

@ -1,131 +1,190 @@
// This is a simple example
package main
import (
"embed"
"errors"
"fmt"
"os"
"path/filepath"
"os/user"
"strings"
"time"
"go.wit.com/dev/alexflint/arg"
"go.wit.com/lib/fhelp"
"go.wit.com/lib/gadgets"
"go.wit.com/lib/gui/prep"
"go.wit.com/lib/gui/shell"
"go.wit.com/lib/protobuf/forgepb"
"go.wit.com/lib/protobuf/gitpb"
"go.wit.com/log"
"go.wit.com/gui"
"go.wit.com/lib/gadgets"
"go.wit.com/lib/gui/repostatus"
)
var VERSION string
var ARGNAME string = "guireleaser"
//go:embed resources/*
var resources embed.FS
var argv args
var resToolkit embed.FS
func main() {
me = new(autoType)
prep.Bash(ARGNAME, argv.DoAutoComplete) // this line should be: prep.Bash(argv)
me.myGui = prep.Gui() // prepares the GUI package for go-args
me.pp = arg.MustParse(&argv)
me.allrepos = make(map[string]*repo)
me.forge = forgepb.Init()
me.forge.ScanRepoDir() // looks for new dirs, checks existing repos for changes
me.found = new(gitpb.Repos)
me.myGui = gui.New()
me.myGui.InitEmbed(resToolkit)
// me.myGui.LoadToolkit("nocui")
me.myGui.Default()
fhelp.CheckGoModCleanExit()
autotypistWindow()
repoworld()
// me.forge.ConfigPrintTable()
os.Setenv("REPO_WORK_PATH", me.forge.Config.ReposDir)
// save the ENV var here
me.releaseReasonS = os.Getenv("GUIRELEASE_REASON")
if me.releaseReasonS == "" {
badExit(errors.New("shell ENV GUIRELEASE_REASON not set"))
}
// unset the go development ENV var to generate release files
// this is required for go mod init & tidy. Also, if the
// user drops to a shell or xterm, then they shouldn't be set there either
os.Unsetenv("GO111MODULE")
me.myGui.Start() // loads the GUI toolkit
// our main window
me.mainWindow = gadgets.RawBasicWindow("GUI release manager " + VERSION)
me.mainWindow.Custom = func() {
log.Warn("Window closed. forge configsave")
// sets the hidden flag to false so Toggle() works
me.forge.ConfigSave()
okExit("")
}
me.mainWindow.Make()
me.mainWindow.Show()
me.mainBox = me.mainWindow.Box()
// sanity check of things that might be around that mess
// up things later
// if you have a go.work file, you must delete it
// TODO: check for go.work files anywhere
homeDir, _ := os.UserHomeDir()
gowork := filepath.Join(homeDir, "go/src/go.work")
if shell.Exists(gowork) {
badExit(errors.New("go.work must be deleted"))
}
log.Info("Creating the Release Window")
// the left side of the window options
globalDisplayOptions(me.mainBox)
// create the right side of the main window
createReleaseBox(me.mainBox)
// disable the gui until the repos are scanned
me.release.box.Disable()
me.Disable()
// todo: add this to forgepb
me.startRepo = me.forge.FindWorkingDirRepo()
if _, count, _, err := me.forge.IsEverythingOnMaster(); err != nil {
log.Info("not everything is on the master branch (", count, "repos)")
if argv.Quick != nil {
// quick also means ignore the master branch check
argv.Force = true
// scan repos every 30 seconds
// check every second for the checkbox changing
var i int = 60
myTicker(1*time.Second, "newScan()", func() {
i += 1
if !me.scanEveryMinute.Checked() {
if i < 60 {
i = 60
}
// print every 13 seconds
if i%13 == 0 {
log.Info("Not auto scanning", i)
}
return
}
if !argv.Force {
os.Exit(-1)
if i < 60 {
return
}
}
if me.startRepo == nil {
pwd, _ := os.Getwd()
msg := fmt.Sprint("Can not run if pwd is not a repo", pwd)
badExit(errors.New(msg))
}
me.forge.RillFuncError(rillPurge)
// run this each time something gets published successfully
rePrepareRelease()
if findNext() {
log.Info("prepare release findNext() returned true")
} else {
// check if nothing is found an exit?
if me.found.Len() == 0 {
log.Info("nothing found to publish")
okExit("found nothing")
}
}
me.Enable()
me.release.box.Enable()
// start the http server for polling status
startHTTP()
i = 0
duration := timeFunction(func() {
scanGoSum()
for _, repo := range me.allrepos {
repo.newScan()
}
})
s := fmt.Sprint(duration)
me.autoWorkingPwd.SetText(s)
})
}
func addRepo(grid *gui.Node, path string, master string, devel string, user string) {
_, ok := me.allrepos[path]
if ok {
log.Info("addRepo() already had path", path)
return
}
newRepo := new(repo)
path = strings.Trim(path, "/") // trim any extranous '/' chars put in the config file by the user
if path == "" {
log.Warn("addRepo() got empty path", path, master, devel, user)
return
}
if repostatus.VerifyLocalGoRepo(path) {
log.Verbose("newRepo actually exists", newRepo.getPath())
} else {
log.Warn("repostatus.VerifyLocalGoRepo() failed for for", path, master, devel, user)
return
}
newRepo.path = path
newRepo.pLabel = grid.NewLabel(path).SetProgName("path")
newRepo.lastTag = grid.NewLabel("").SetProgName("lastTag")
newRepo.masterVersion = grid.NewLabel("").SetProgName("masterVersion")
newRepo.develVersion = grid.NewLabel("").SetProgName("develVersion")
newRepo.userVersion = grid.NewLabel("").SetProgName("userVersion")
newRepo.dirtyLabel = grid.NewLabel("")
newRepo.goSumStatus = grid.NewLabel("?")
newRepo.vLabel = grid.NewLabel("").SetProgName("current")
newRepo.statusButton = grid.NewButton("Configure", func() {
if newRepo.status == nil {
log.Warn("status window doesn't exist")
return
}
log.Warn("status window exists. trying TestDraw() here")
newRepo.status.Toggle()
/// newRepo.status.Update()
})
// newRepo.status = repostatus.New(me.myGui, newRepo.path)
newRepo.status = repostatus.NewRepoStatusWindow(newRepo.path)
newRepo.hidden = false
newRepo.status.SetMainWorkingName(master)
newRepo.status.SetDevelWorkingName(devel)
newRepo.status.SetUserWorkingName(user)
/*
newRepo.status.SetDevelBranchName(devel)
newRepo.status.SetUserBranchName(user)
newRepo.status.Update()
newRepo.newScan()
*/
me.allrepos[path] = newRepo
}
func autotypistWindow() {
win := me.myGui.NewWindow("autotypist for GO & git. it types faster than you can.")
box := win.NewBox("bw hbox", true)
globalDisplayOptions(box)
globalBuildOptions(box)
globalTestingOptions(box)
globalResetOptions(box)
}
// This creates a window
func repoworld() {
reposwin = gadgets.NewBasicWindow(me.myGui, "All git repositories in ~/go/src/")
reposwin.Make()
reposbox = reposwin.Box().NewBox("bw vbox", false)
reposwin.Draw()
reposwin.Custom = func() {
log.Warn("GOT HERE: main() gadgets.NewBasicWindow() close")
log.Warn("Should I do something special here?")
}
reposgroup = reposbox.NewGroup("go repositories (read from ~/.config/myrepolist)")
reposgrid = reposgroup.NewGrid("test", 9, 1)
reposgrid.NewLabel("") // path goes here
reposgrid.NewLabel("last tag").SetProgName("last tag")
reposgrid.NewLabel("master version")
reposgrid.NewLabel("devel version")
reposgrid.NewLabel("user version")
reposgrid.NewLabel("Status")
reposgrid.NewLabel("go.sum")
reposgrid.NewLabel("Current Version").SetProgName("Current Version")
reposgrid.NewLabel("Show()")
repos := myrepolist()
for _, line := range repos {
log.Verbose("repo =", line)
path, mbranch, dbranch, ubranch := splitLine(line)
if mbranch == "" {
mbranch = "master"
}
if dbranch == "" {
dbranch = "devel"
}
usr, _ := user.Current()
if ubranch == "" {
ubranch = usr.Username
}
addRepo(reposgrid, path, mbranch, dbranch, ubranch)
}
for i, path := range repostatus.ListGitDirectories() {
// log.Info("addRepo()", i, path)
tmp := strings.TrimPrefix(path, "/home/jcarr/go/src/")
log.Info("addRepo()", i, tmp)
addRepo(reposgrid, tmp, "master", "master", "master")
}
reposwin.Toggle()
}

View File

@ -1,297 +0,0 @@
package main
import (
"errors"
"fmt"
"os"
"path/filepath"
"time"
"go.wit.com/lib/gui/shell"
"go.wit.com/lib/protobuf/forgepb"
"go.wit.com/lib/protobuf/gitpb"
"go.wit.com/log"
)
func forceReleaseVersion(repo *gitpb.Repo) {
if argv.Minor {
// if v1.2.3 change to v.1.3.0
repo.IncrementTargetMinor()
} else {
// if v1.2.3 change to v.1.2.4
repo.IncrementTargetRevision()
}
}
func checkpkgcache(repo *gitpb.Repo) error {
homedir, err := os.UserHomeDir()
if err != nil {
return err
}
rver := repo.GetLastTag()
if rver == "" {
return errors.New("could not get master version")
}
moddir := filepath.Join(homedir, "go/pkg/mod", repo.GetGoPath()+"@"+rver)
if shell.IsDir(moddir) {
return nil
}
getpath := repo.GetGoPath() + "@" + repo.GetLastTag()
log.Infof("~/go/pkg/mod/ IS MISSING %s so I'm running go get here.", getpath)
_, err = me.startRepo.RunVerboseOnError([]string{"go", "get", getpath})
return err
}
var rillcount int
func rillPurge(repo *gitpb.Repo) error {
if me.forge.Config.IsReadOnly(repo.GetGoPath()) {
return nil
}
if me.forge.Config.IsPrivate(repo.GetGoPath()) {
return nil
}
_, err := repo.RunQuiet([]string{"go-mod-clean", "purge"})
rillcount += 1
if err != nil {
log.Info("go-mod-clean purge failed", repo.GetGoPath(), err)
return err
}
return nil
}
func rillRestore(repo *gitpb.Repo) error {
if me.forge.Config.IsReadOnly(repo.GetGoPath()) {
return nil
}
if me.forge.Config.IsPrivate(repo.GetGoPath()) {
return nil
}
var err error
if argv.Verbose {
log.Info("go-mod-clean lax START", repo.GetGoPath())
result := repo.RunRealtime([]string{"go-mod-clean", "lax"})
log.Info("go-mod-clean lax END", repo.GetGoPath())
if result.Exit != 0 {
err = fmt.Errorf("repo %s failed %d", repo.GetGoPath(), result.Exit)
}
} else {
_, err = repo.RunQuiet([]string{"go-mod-clean", "lax"})
}
rillcount += 1
if err != nil {
log.Info("go-mod-clean lax failed", repo.GetGoPath(), err)
return err
}
return nil
}
func rePrepareRelease() {
me.forge.ScanRepoDir() // looks for new dirs, checks existing repos for changes
me.found = new(gitpb.Repos)
me.reason = make(map[*gitpb.Repo]string) // stores the reason repos need to be versioned & released
log.Printf("rePrepareRelease() START rill go-mod-clean lax (11 seconds?)")
rillcount = 0
forgepb.RillX = 2
forgepb.RillY = 2
now := time.Now()
me.forge.RillFuncError(rillRestore)
log.Printf("showRestore() (%d total repos) took:%s\n", rillcount, shell.FormatDuration(time.Since(now)))
log.Sleep(1)
all2 := me.forge.Repos.SortByFullPath()
for all2.Scan() {
check := all2.Next()
if me.forge.Config.IsReadOnly(check.GetGoPath()) {
continue
}
if me.forge.Config.IsPrivate(check.GetGoPath()) {
continue
}
// this should be rare? nonexistant?
if err := checkpkgcache(check); err != nil {
log.Info("go get checks failed here.", err, check.GetGoPath())
}
}
all := me.forge.Repos.SortByFullPath()
for all.Scan() {
check := all.Next()
if alreadyDone(check) {
// means it was already published
// protects against logic errors that might result
// in an infinite loop
log.Info("WARNING alreadyDone rePrepareRelease()", check.GetGoPath())
continue
}
if me.forge.Config.IsReadOnly(check.GetGoPath()) {
// can't release readonly repos
continue
}
master := check.GetMasterVersion()
lastTag := check.GetLastTag()
if argv.Quick != nil {
// if argv has 'quick' don't do anything
// that doesn't actually have a patch
if master == lastTag {
continue
}
}
log.Info("LAST TAG", check.FullPath, master, lastTag)
// this is detailed. It makes sure the go.* files are absolutely perfect
if !me.forge.Config.IsPrivate(check.GetGoPath()) {
if err := checkPublishedGodeps(check); err != nil {
// this means the published godeps are no longer up to date
forceReleaseVersion(check)
me.found.AppendByFullPath(check)
log.Info("checkPublishedGodeps failed with err", check.GetGoPath(), err)
continue
} else {
// log.Info("checkPublishedGodeps is ok", check.GetGoPath())
}
}
// if master != lastTag, always increment
if master != lastTag {
newmhash := check.GetTagHash(master)
oldlhash := check.GetTagHash(lastTag)
if newmhash == oldlhash {
// they are actually equal
continue
}
b1 := check.CountDiffObjects(oldlhash, newmhash)
b2 := check.CountDiffObjects(newmhash, oldlhash)
if b1 != 0 {
log.Printf("HASH ERROR %-50s tag %s < %s\n", check.GetGoPath(), newmhash, oldlhash)
log.Info("old vs new count", b1, b2, "git merge", oldlhash)
}
if b1 == 0 && b2 == 0 {
log.Info("got to identical repo", check.GetGoPath(), b1, b2)
log.Info("got to identical repo", check.GetGoPath(), oldlhash, newmhash)
// actually identical. do nothing
continue
}
if gitpb.IsGoTagVersionGreater(lastTag, master) {
// this function is not right really. the hash error above should catch it correctly
// log.Printf("PROBABLY NOT NEE %-50s tag %s < %s\n", check.GetGoPath(), lastTag, master)
}
log.Printf("NEED RELEASE FOR %-50s tag %s != %s\n", check.GetGoPath(), master, lastTag)
forceReleaseVersion(check)
me.found.AppendByFullPath(check)
me.reason[check] = "master != lastTag"
continue
}
if me.forge.Config.IsPrivate(check.GetGoPath()) {
// only checks after this are GO dep related which don't matter for private repos
continue
}
if argv.Protobuf && check.GetRepoType() == "protobuf" {
log.Printf("NEED RELEASE FOR %s err: %v\n", check.GetGoPath(), "because --protobuf")
// if --protobuf, this will force upgrade each one
forceReleaseVersion(check)
me.found.AppendByFullPath(check)
me.reason[check] = "protobuf repo deps changed"
continue
}
// if the repo is a go binary or plugin for a new release for
// any library version change
// if check.GetRepoType() == "binary" || check.GetRepoType() == "plugin" {
// check if the package dependancies changed, if so, re-publish
if err := me.forge.FinalGoDepsCheckOk(check, false); err == nil {
// log.Printf("go.sum is perfect! %s\n", check.GetGoPath())
continue
} else {
log.Printf("NEED RELEASE FOR %-50s err: %v\n", check.GetGoPath(), err)
forceReleaseVersion(check)
me.found.AppendByFullPath(check)
me.reason[check] = "FinalGoDepsCheckOk() failed even though master tag == last tag"
}
}
me.forge.PrintHumanTable(me.found)
// todo: verify each found repo is on the master branch
for repo := range me.found.IterAll() {
if repo.CurrentBranchName != repo.MasterBranchName {
log.Info("repo not on master branch", repo.FullPath)
if !argv.Force {
os.Exit(-1)
}
}
}
}
func printDone() {
for _, gopath := range me.done {
log.Info("printDone() THESE WERE PUBLISHED", gopath)
}
log.Info("printDone() total finished so far:", len(me.done))
time.Sleep(time.Second)
}
func alreadyDone(repo *gitpb.Repo) bool {
for _, gopath := range me.done {
// log.Info("WARNING already done", gopath, repo.GetGoPath())
// log.Info("WARNING already done", gopath, repo.GetGoPath())
// log.Info("WARNING already done", gopath, repo.GetGoPath())
if repo.GetGoPath() == gopath {
log.Info("FOUND. RETURN TRUE. already done", gopath, repo.GetGoPath())
return true
}
}
return false
}
/*
func upgradeReason(repo *gitpb.Repo) string {
for _, gopath := range me.reason {
// log.Info("WARNING already done", gopath, repo.GetGoPath())
// log.Info("WARNING already done", gopath, repo.GetGoPath())
// log.Info("WARNING already done", gopath, repo.GetGoPath())
if repo.GetGoPath() == gopath {
log.Info("FOUND. RETURN TRUE. already done", gopath, repo.GetGoPath())
return true
}
}
return false
}
*/
func checkPublishedGodeps(repo *gitpb.Repo) error {
godepsOld, err := repo.GoSumFromPkgDir()
if err != nil {
return err
}
if godepsOld != nil {
if err := me.forge.TestGoDepsCheckOk(godepsOld, argv.Verbose); err != nil {
return err
}
}
godepsNew, err := repo.GoSumFromRepo()
if err != nil {
return err
}
if godepsOld == nil {
if godepsNew == nil {
log.Printf("%s published godeps == nil && real == nil\n", repo.GetGoPath())
return nil
} else {
return fmt.Errorf("published godeps == nil vs real != nil")
}
}
if err := me.forge.TestGoDepsCheckOk(godepsNew, argv.Verbose); err != nil {
return err
}
return nil
}

View File

@ -1,179 +0,0 @@
// This is a simple example
package main
import (
"fmt"
"time"
"go.wit.com/gui"
"go.wit.com/log"
"go.wit.com/lib/gadgets"
"go.wit.com/lib/gui/shell"
"go.wit.com/lib/protobuf/gitpb"
)
type releaseStruct struct {
box *gui.Node
group *gui.Node
grid *gui.Node
repo *gadgets.OneLiner
status *gadgets.OneLiner
readOnly *gadgets.OneLiner
notes *gadgets.OneLiner
version *gadgets.OneLiner
releaseVersionB *gui.Node
reason *gadgets.BasicEntry
// openrepo *gui.Node
goGetB *gui.Node
checkGoSumB *gui.Node
checkDirtyB *gui.Node
sendVersionB *gui.Node
checkSafeB *gui.Node
// whitelist map[string]*repolist.RepoRow
}
func (w *autoType) Disable() {
me.mainBox.Disable()
}
func (w *autoType) Enable() {
me.mainBox.Enable()
}
func createReleaseBox(box *gui.Node) {
me.release.box = box.NewVerticalBox("vbox")
me.release.group = me.release.box.NewGroup("Current Repo")
me.release.grid = me.release.group.NewGrid("buildOptions", 0, 0)
me.release.grid.NextRow()
me.release.releaseVersionB = me.release.grid.NewButton("release version", func() {
buttonDisable()
fpath := me.current.FullPath
if err := doRelease(); err == nil {
buttonEnable()
log.Info("doRelease() worked", fpath)
} else {
log.Info("doRelease() failed", err, fpath)
log.Info("doRelease() FAILED", err, fpath)
log.Info("doRelease() FAILED", err, fpath)
log.Info("doRelease() FAILED", err, fpath)
}
skipToNext()
me.forge.PrintHumanTable(me.found)
})
me.release.grid.NewButton("Find Next", func() {
me.Disable()
defer me.Enable()
if findNext() {
log.Info("findNext() found a repo")
return
}
})
me.release.grid.NewButton("Show Next", func() {
check := me.current
if check == nil {
log.Info("boo, current is missing", me.current.GetGoPath())
return
}
testGoRepo(check)
me.forge.HumanPrintRepo(check)
})
me.release.grid.NextRow()
me.release.repo = gadgets.NewOneLiner(me.release.grid, "repo")
me.release.grid.NextRow()
me.release.status = gadgets.NewOneLiner(me.release.grid, "status")
me.release.grid.NextRow()
me.release.readOnly = gadgets.NewOneLiner(me.release.grid, "read-only")
me.release.grid.NextRow()
me.release.notes = gadgets.NewOneLiner(me.release.grid, "notes")
me.release.grid.NextRow()
me.release.version = gadgets.NewOneLiner(me.release.grid, "version")
me.release.grid.NextRow()
me.release.reason = gadgets.NewBasicEntry(me.release.grid, "release reason")
me.release.reason.SetText(me.releaseReasonS)
me.release.grid.NextRow()
me.autoWorkingPwd = gadgets.NewOneLiner(me.release.grid, "working directory (pwd)")
me.release.grid.NextRow()
me.goSrcPwd = gadgets.NewOneLiner(me.release.grid, "go src home")
me.release.grid.NextRow()
// me.userHomePwd.SetText(homeDir)
me.goSrcPwd.SetText(me.forge.Config.ReposDir)
group := me.release.box.NewGroup("Run on Current Repo")
grid := group.NewGrid("buildOptions", 0, 0)
grid.NextRow()
group = me.release.box.NewGroup("Publish until done")
grid = group.NewGrid("buildOptions", 0, 0)
grid.NewButton("doRelease() all", func() {
buttonDisable()
doReleaseAll()
buttonEnable()
})
grid.NextRow()
}
func doReleaseAll() {
count := 0
for {
log.Info("START doRelease() LOOP count =", count, "len me.done =", len(me.done))
if err := doRelease(); err != nil {
break
}
if err := skipToNext(); err != nil {
break
}
count += 1
if count > me.forge.Repos.Len() {
// never allow a loop longer than all the known repos
// this probably doesn't matter, but often this code is wrong
// so this is a safety check. never remove this check.
break
}
}
}
func skipToNext() error {
shell.RunVerbose([]string{"forge", "dirty"})
log.Info("Sleeping for 2 seconds for no reason.")
time.Sleep(1)
me.forge.ScanRepoDir() // looks for new dirs, checks existing repos for changes
me.found = new(gitpb.Repos)
me.current.ReloadCheck()
me.forge.SetConfigSave(true)
me.forge.ConfigSave()
log.Info("sleep 2")
time.Sleep(2 * time.Second)
printDone()
rePrepareRelease()
findNext()
if me.current == nil {
log.Info("NOT GOOD TO RUN ANOTHER DAY")
log.Info("took out all the loop code")
setCurrentRepo(nil, "loop by hand motherfucker", "fucknuts")
return fmt.Errorf("findNext returned next repo == nil")
}
log.Info("GOOD TO RUN ANOTHER DAY ON:", me.current.GetGoPath())
return nil
}
func buttonDisable() {
me.Disable()
me.release.box.Disable()
}
func buttonEnable() {
me.Enable()
me.release.box.Enable()
}

471
releaseWindow.go Normal file
View File

@ -0,0 +1,471 @@
// This is a simple example
package main
import (
"os"
"sort"
"strings"
"go.wit.com/gui"
"go.wit.com/log"
"go.wit.com/lib/gadgets"
"go.wit.com/lib/gui/repostatus"
)
var release releaseStruct
type releaseStruct struct {
current *repo
win *gadgets.BasicWindow
box *gui.Node
group *gui.Node
grid *gui.Node
repo *gadgets.OneLiner
status *gadgets.OneLiner
readOnly *gadgets.OneLiner
notes *gadgets.OneLiner
version *gadgets.OneLiner
reason *gadgets.BasicEntry
openrepo *gui.Node
goGetB *gui.Node
checkGoSumB *gui.Node
checkDirtyB *gui.Node
makeRedomodB *gui.Node
sendVersionB *gui.Node
checkSafeB *gui.Node
}
func createReleaseWindow() {
if release.win != nil {
release.win.Toggle()
return
}
versionS := "0.14.0"
reasonS := "gocui"
partS := strings.Split(versionS, ".")
release.win = gadgets.NewBasicWindow(me.myGui, "Make a new release")
release.win.Custom = func() {
log.Info("Release Window close")
}
release.win.Make()
release.win.StandardClose()
release.win.Draw()
release.box = release.win.Box()
release.group = release.box.NewGroup("things")
release.grid = release.group.NewGrid("buildOptions", 2, 1)
// do an initial scan of all the repos
scanGoSum()
release.grid.NewButton("findNextDirty()", func() {
release.win.Disable()
if findNextDirty() {
log.Info("findNextDirty() found a repo")
release.win.Enable()
return
}
release.win.Enable()
})
release.grid.NewButton("nil", func() {
log.Info("just filling the grid")
})
release.grid.NewButton("next repo", func() {
buttonDisable()
defer buttonEnable()
// allrepos map[string]*repo
keys := make([]string, 0, len(me.allrepos))
for key := range me.allrepos {
keys = append(keys, key)
}
sort.Strings(keys)
for _, path := range keys {
repo := me.allrepos[path]
// mt.Printf("%s: %s\n", key, myMap[key])
//// for _, repo := range me.allrepos {
// goSumS := repo.getGoSumStatus()
// dirtyS := repo.dirtyLabel.String()
if repo.status.ReadOnly() {
log.Info("skipping repo:", path, repo.String())
} else {
log.Info("searching on repo:", path, repo.String())
tmp := repo.status.GetGoDeps()
for path, version := range tmp {
r, ok := me.allrepos[path]
if ok {
log.Info("\tfound path", path, r, version)
} else {
log.Info("\tdid not find path", path, r, version)
}
}
}
}
return
if findNextRepo() {
log.Info("findNextRepo() found a repo")
return
}
if findDirty2() {
log.Info("findDirty2() found a repo")
return
}
})
release.openrepo = release.grid.NewButton("open repo", func() {
if release.current == nil {
log.Info("find the next repo first")
return
}
// make sure read only is set
if release.current.status.ReadOnly() {
release.readOnly.SetValue("true")
} else {
release.readOnly.SetValue("false")
}
// do a new scan
release.current.newScan()
// only continue if the go.sum & go.mod files are clean
if ok, missing := release.current.status.CheckGoSum(); ok {
log.Info("repo has go.sum requirements that are clean")
release.status.SetValue("CLEAN")
release.current.setGoSumStatus("CLEAN")
} else {
log.Info("BAD repo has go.sum requirements that are screwed up. missing:", missing)
release.status.SetValue("BAD")
release.current.setGoSumStatus("BAD")
return
}
if release.current.dirtyLabel.String() == "PERFECT" {
log.Info("REPO IS STILL DIRTY")
return
}
// open the status window to commit the release
release.current.status.Toggle()
release.current.status.SetVersion(partS[0], partS[1], partS[2], release.reason.String())
release.current.status.Update()
})
release.openrepo.Disable()
release.repo = gadgets.NewOneLiner(release.grid, "repo")
release.status = gadgets.NewOneLiner(release.grid, "status")
release.readOnly = gadgets.NewOneLiner(release.grid, "read-only")
release.notes = gadgets.NewOneLiner(release.grid, "notes")
release.version = gadgets.NewOneLiner(release.grid, "version")
release.version.SetText(versionS)
release.reason = gadgets.NewBasicEntry(release.grid, "release reason")
release.reason.SetText(reasonS)
release.sendVersionB = release.grid.NewButton("send version", func() {
log.Info("set version()")
release.current.status.SetVersion(partS[0], partS[1], partS[2], release.reason.String())
})
release.grid.NewButton("set ignore", func() {
tmp := release.current.getGoSumStatus()
log.Info("trying to set repo IGNORE is now =", tmp)
release.current.setGoSumStatus("IGNORE")
})
release.checkDirtyB = release.grid.NewButton("checkDirty()", func() {
buttonDisable()
if release.current.checkDirty() {
log.Info("repo is dirty")
} else {
log.Info("repo is not dirty")
}
buttonEnable()
})
release.checkSafeB = release.grid.NewButton("checkSafeGoSumRemake()", func() {
buttonDisable()
release.current.checkSafeGoSumRemake()
buttonEnable()
})
release.checkGoSumB = release.grid.NewButton("CheckGoSum()", func() {
buttonDisable()
tmp := release.current.String()
log.Info("Run CheckGoSum on repo:", tmp)
if ok, missing := release.current.status.CheckGoSum(); ok {
log.Info("repo has go.sum requirements that are clean")
release.current.setGoSumStatus("CLEAN")
} else {
if missing == "" {
log.Info("BAD VERSION repo has go.sum requirements that are screwed up.", tmp)
if release.current.getGoSumStatus() == "BAD" {
release.current.setGoSumStatus("BAD VERSION")
}
if release.current.getGoSumStatus() == "CLEAN" {
release.current.setGoSumStatus("BAD VERSION")
}
} else {
log.Info("BAD VERSION repo has go.sum requirements that are screwed up.", tmp)
log.Info("BAD VERSION need to addRepo() the missing repo", missing)
if repostatus.VerifyLocalGoRepo(missing) {
log.Info("BAD VERSION local directory exists", missing)
addRepo(reposgrid, missing, "master", "master", "master")
} else {
log.Info("BAD VERSION local directory does not exist", missing)
log.Info("START download of:", missing)
os.Setenv("GO111MODULE", "off")
err, output := release.current.status.RunCmd([]string{"go", "get", "-v", "-u", missing})
log.Warn(output)
log.Info("END download of:", missing)
if err == nil {
log.Warn("go get worked. recheck go.sum")
} else {
log.Warn("go get failed")
}
}
// addRepo(reposgrid, missing, "master", "master", "master")
}
}
buttonEnable()
})
release.grid.NewButton("CheckPrimativeGoMod()", func() {
tmp := release.current.String()
log.Info("Run CheckGoSum on repo:", tmp)
if release.current.status.CheckPrimativeGoMod() {
log.Info("repo has PRIMATIVE go.mod")
} else {
log.Info("repo go.mod requies checking for a go.sum")
}
})
release.grid.NewButton("reset with scanGoSum()", func() {
buttonDisable()
// do an initial scan of all the repos
scanGoSum()
buttonEnable()
})
release.makeRedomodB = release.grid.NewButton("make redomod", func() {
buttonDisable()
release.current.status.MakeRedomod()
buttonEnable()
})
release.goGetB = release.grid.NewButton("go get -v -u .", func() {
buttonDisable()
err, output := release.current.status.RunCmd([]string{"go", "get", "-v", "-u", "."})
log.Warn(output)
if err == nil {
log.Warn("go get worked. recheck go.sum")
} else {
log.Warn("go get failed")
}
buttonEnable()
})
release.goGetB = release.grid.NewButton("SetMainWorkingName(guimaster)", func() {
buttonDisable()
release.current.status.SetMainWorkingName("guimaster")
buttonEnable()
})
}
func buttonDisable() {
release.win.Disable()
/*
release.nextRepoB.Disable()
release.openRepoB.Disable()
release.goGetB.Disable()
release.makeRedomodB.Disable()
release.checkGoSumB.Disable()
release.openrepo.Disable()
release.checkDirtyB.Disable()
release.sendVersionB.Disable()
release.checkSafeB.Disable()
*/
}
func buttonEnable() {
release.win.Enable()
/*
release.nextRepoB.Enable()
release.openRepoB.Enable()
release.goGetB.Enable()
release.makeRedomodB.Enable()
release.checkGoSumB.Enable()
release.openrepo.Enable()
release.checkDirtyB.Enable()
release.sendVersionB.Enable()
release.checkSafeB.Enable()
*/
}
func findDirty2() bool {
log.Info("findDirty2() START")
for _, repo := range me.allrepos {
goSumS := repo.getGoSumStatus()
dirtyS := repo.dirtyLabel.String()
if goSumS == "IGNORE" {
continue
}
if goSumS == "DIRTY 2" {
log.Info("repo DIRTY 2", repo.String(), goSumS, dirtyS)
if setCurrentRepo(repo, "dirty 2", "check manually I guess") {
return true
}
return true
} else {
log.Info("repo not DIRTY 2", repo.String(), goSumS, dirtyS)
}
}
log.Info("findDirty2() END")
return false
}
func setCurrentRepo(newcur *repo, s string, note string) bool {
if newcur.status.ReadOnly() {
return false
}
release.repo.SetValue(newcur.status.String())
release.status.SetValue(s)
release.notes.SetValue(note)
release.current = newcur
release.openrepo.Enable()
if newcur.status.ReadOnly() {
release.readOnly.SetValue("true ro")
} else {
release.readOnly.SetValue("false ro")
}
return true
}
func findNextDirty() bool {
for _, repo := range me.allrepos {
goSumS := repo.getGoSumStatus()
dirtyS := repo.dirtyLabel.String()
log.Info("findNextDirty()", repo.String(), goSumS, dirtyS)
if goSumS == "PRIMATIVE" {
if dirtyS != "PERFECT" {
if setCurrentRepo(repo, "primative not committed", "release new version") {
return true
}
continue
}
continue
}
if goSumS == "IGNORE" {
continue
}
if goSumS == "DIRTY 2" {
continue
}
if goSumS == "BAD DEP" {
// find out what kind of BAD DEP?
continue
}
// latestversion := repo.status.GetLastTagVersion()
if goSumS == "CLEAN" {
// if it's clean here, then check and remake the go.sum file
// then stop to commit the release version
repo.checkSafeGoSumRemake()
if repo.checkDirty() {
dirtyS = repo.dirtyLabel.String()
}
if dirtyS == "PERFECT" {
continue
}
if setCurrentRepo(repo, "clean", "check manually") {
return true
}
}
if goSumS == "DIRTY" {
if ok, missing := repo.status.CheckGoSum(); ok {
log.Info("repo has go.sum requirements that are clean")
// repo.setGoSumStatus("CLEAN")
} else {
log.Info("DIRTY 2 repo has go.sum requirements that are screwed up. missing:", missing)
repo.setGoSumStatus("DIRTY 2")
continue
}
if setCurrentRepo(repo, "dirty", "commit changes") {
return true
}
}
}
log.Info("tried to findNextDirty() but not sure what to do next")
return false
}
func findNextRepo() bool {
for _, repo := range me.allrepos {
goSumS := repo.getGoSumStatus()
dirtyS := repo.dirtyLabel.String()
log.Info("findNextRepo()", repo.String(), goSumS, dirtyS)
if goSumS == "IGNORE" {
continue
}
if goSumS == "DIRTY 2" {
continue
}
if goSumS == "BAD VERSION" {
continue
}
if goSumS == "BAD DEP" {
// find out what kind of BAD DEP?
continue
}
// latestversion := repo.status.GetLastTagVersion()
if goSumS == "CLEAN" {
// if it's clean here, then check and remake the go.sum file
// then stop to commit the release version
repo.checkSafeGoSumRemake()
if repo.checkDirty() {
dirtyS = repo.dirtyLabel.String()
}
if dirtyS == "PERFECT" {
continue
}
if setCurrentRepo(repo, "clean round 2", "check manually") {
return true
}
}
if goSumS == "DIRTY" {
if ok, missing := repo.status.CheckGoSum(); ok {
log.Info("repo has go.sum requirements that are clean")
// repo.setGoSumStatus("CLEAN")
} else {
log.Info("DIRTY 3 repo has go.sum requirements that are screwed up. missing:", missing)
repo.setGoSumStatus("DIRTY 3")
continue
}
if setCurrentRepo(repo, "dirty", "commit changes") {
return true
}
}
if goSumS == "BAD" {
// if it's clean here, then check and remake the go.sum file
// then stop to commit the release version
repo.checkSafeGoSumRemake()
if repo.checkDirty() {
dirtyS = repo.dirtyLabel.String()
}
if setCurrentRepo(repo, "bad", "redo go.sum") {
return true
}
}
}
log.Info("tried to findNextRepo() but not sure what to do next")
return false
}

72
repolist.go Normal file
View File

@ -0,0 +1,72 @@
// This is a simple example
package main
import (
"io/ioutil"
"strings"
)
func (r *repo) String() string {
return r.status.String()
}
func (r *repo) getPath() string {
return r.path
}
func RemoveFirstElement(slice []string) (string, []string) {
if len(slice) == 0 {
return "", slice // Return the original slice if it's empty
}
return slice[0], slice[1:] // Return the slice without the first element
}
// returns path, master branch name, devel branch name, user branch name
func splitLine(line string) (string, string, string, string) {
var path, master, devel, user string
parts := strings.Split(line, " ")
path, parts = RemoveFirstElement(parts)
master, parts = RemoveFirstElement(parts)
devel, parts = RemoveFirstElement(parts)
user, parts = RemoveFirstElement(parts)
// path, master, devel, user := strings.Split(line, " ")
return path, master, devel, user
}
func myrepolist() []string {
content, _ := ioutil.ReadFile("/home/jcarr/.config/myrepolist")
out := string(content)
out = strings.TrimSpace(out)
lines := strings.Split(out, "\n")
return lines
}
func (r *repo) Hide() {
r.pLabel.Hide()
r.lastTag.Hide()
r.vLabel.Hide()
r.masterVersion.Hide()
r.develVersion.Hide()
r.userVersion.Hide()
r.dirtyLabel.Hide()
r.goSumStatus.Hide()
r.statusButton.Hide()
r.hidden = true
}
func (r *repo) Show() {
r.pLabel.Show()
r.lastTag.Show()
r.vLabel.Show()
r.masterVersion.Show()
r.develVersion.Show()
r.userVersion.Show()
r.dirtyLabel.Show()
r.goSumStatus.Show()
r.statusButton.Show()
r.hidden = false
}

View File

@ -1 +0,0 @@
* you can put toolkit .so binaries here

15
resources/myrepolist Normal file
View File

@ -0,0 +1,15 @@
go.wit.com/log
go.wit.com/gui/widget
go.wit.com/gui/gui
go.wit.com/gui/toolkits
go.wit.com/gui/debugger
go.wit.com/gui/gadgets
go.wit.com/gui/gadgets/repostatus
go.wit.com/gui/digitalocean
go.wit.com/gui/cloudflare
go.wit.com/apps/control-panel-dns
go.wit.com/apps/control-panel-vpn
go.wit.com/apps/autotypist

175
scan.go Normal file
View File

@ -0,0 +1,175 @@
// This is a simple example
package main
import (
"fmt"
"time"
"go.wit.com/log"
"go.wit.com/lib/gui/repostatus"
)
func (r *repo) newScan() bool {
if r.status == nil {
log.Warn("repo.status = nil. not initialized for some reason")
return false
}
// r.scan()
if repostatus.VerifyLocalGoRepo(r.getPath()) {
log.Verbose("repo actually exists", r.getPath())
} else {
log.Warn("repo does not exist", r.getPath())
return false
}
mname := r.status.GetMasterBranchName()
mver := r.status.GetMasterVersion()
if mname != "guimaster" {
mver = mver + " (" + mname + ")"
}
r.masterVersion.SetLabel(mver)
dname := r.status.GetDevelBranchName()
dver := r.status.GetDevelVersion()
if dname != "devel" {
dver = dver + " (" + dname + ")"
}
r.develVersion.SetLabel(dver)
uname := r.status.GetUserBranchName()
uver := r.status.GetUserVersion()
if uname != "jcarr" {
uver = uver + " (" + uname + ")"
}
r.userVersion.SetLabel(uver)
cbname := r.status.GetCurrentBranchName()
cbversion := r.status.GetCurrentBranchVersion()
lasttag := r.status.GetLastTagVersion()
r.lastTag.SetLabel(lasttag)
r.vLabel.SetLabel(cbname + " " + cbversion)
if r.status.Changed() {
log.Warn("should scan here")
}
status := r.status.GetStatus()
r.dirtyLabel.SetLabel(status)
if status == "PERFECT" {
if me.autoHidePerfect.Checked() {
r.Hide()
}
return true
}
return false
}
func (r *repo) getGoSumStatus() string {
return r.goSumStatus.String()
}
func (r *repo) setGoSumStatus(s string) {
r.goSumStatus.SetLabel(s)
r.status.SetGoSumStatus(s)
}
func (r *repo) checkDirty() bool {
if r.status.CheckDirty() {
log.Info("dirty repo:", r.status.String(), r.getGoSumStatus())
r.setGoSumStatus("DIRTY")
return true
}
return false
}
func (r *repo) checkSafeGoSumRemake() {
if ok, bad := r.status.CheckSafeGoSumRemake(); ok {
log.Info("checkSafeGoSumRemake() is safe to redo")
r.setGoSumStatus("SAFE")
r.status.MakeRedomod()
} else {
log.Info("checkSafeGoSumRemake() is not safe. problems:", bad)
r.setGoSumStatus("BAD DEP")
}
}
func scanGoSum() {
for _, repo := range me.allrepos {
latestversion := repo.status.GetLastTagVersion()
if repo.getGoSumStatus() == "BAD" {
continue
}
if repo.getGoSumStatus() == "DIRTY" {
continue
}
if repo.status.CheckPrimativeGoMod() {
log.Info("PRIMATIVE repo:", latestversion, repo.status.String())
repo.setGoSumStatus("PRIMATIVE")
continue
}
if repo.checkDirty() {
log.Info("dirty repo:", latestversion, repo.status.String())
log.Info("dirty repo.getGoSumStatus =", repo.getGoSumStatus())
repo.setGoSumStatus("DIRTY")
// release.repo.SetValue(repo.status.String())
// release.status.SetValue("dirty")
// release.notes.SetValue("You must commit your changes\nbefore you can continue")
// release.current = repo
// release.openrepo.Enable()
continue
}
if ok, missing := repo.status.CheckGoSum(); ok {
log.Info("repo has go.sum requirements that are clean")
repo.setGoSumStatus("CLEAN")
} else {
log.Info("repo has go.sum requirements that are screwed up. missing:", missing)
repo.setGoSumStatus("BAD")
// release.repo.SetValue(repo.status.String())
// release.status.SetValue("bad")
// release.notes.SetValue("the go.sum file is wrong")
// release.current = repo
// release.openrepo.Enable()
continue
}
status := repo.dirtyLabel.String()
if status == "PERFECT" {
continue
} else {
repo.status.Update()
repo.newScan()
}
log.Info("repo:", latestversion, status, repo.status.String())
}
log.Info("scanGoSum() did everything, not sure what to do next")
}
// timeFunction takes a function as an argument and returns the execution time.
func timeFunction(f func()) time.Duration {
startTime := time.Now() // Record the start time
f() // Execute the function
return time.Since(startTime) // Calculate the elapsed time
}
func myTicker(t time.Duration, name string, f func()) {
ticker := time.NewTicker(t)
defer ticker.Stop()
done := make(chan bool)
/*
go func() {
time.Sleep(10 * time.Second)
done <- true
}()
*/
for {
select {
case <-done:
fmt.Println("Done!")
return
case t := <-ticker.C:
log.Verbose(name, "Current time: ", t)
f()
}
}
}

View File

@ -2,39 +2,49 @@
package main
import (
"go.wit.com/dev/alexflint/arg"
"go.wit.com/gui"
"go.wit.com/lib/gadgets"
"go.wit.com/lib/gui/prep"
"go.wit.com/lib/protobuf/forgepb"
"go.wit.com/lib/protobuf/gitpb"
"go.wit.com/lib/gui/repostatus"
)
// the main window nodes
var reposwin *gadgets.BasicWindow
var reposbox *gui.Node
var reposgrid *gui.Node
var reposgroup *gui.Node
var me *autoType
type autoType struct {
pp *arg.Parser // for parsing the command line args. Yay to alexf lint!
myGui *prep.GuiPrep // the gui handle itself
releaseReasonS string // = "gocui dropdown select"
release releaseStruct // notsure
reposbox *gui.Node // notsure
reposgrid *gui.Node // notsure
reposgroup *gui.Node // notsure
current *gitpb.Repo // tracks the next repo to publish
found *gitpb.Repos // stores the list of repos to process things on
done []string // gopaths for repos already published
reason map[*gitpb.Repo]string // the reason this package is going to be updated
allrepos map[string]*repo
myGui *gui.Node
// this is the repo we are starting in
// make sure it never changes so go.mod and go.sum are always there
// 'go get' is called from here
startRepo *gitpb.Repo
autotypistWindow *gadgets.BasicWindow
// guireleaser window
mainWindow *gadgets.BasicWindow
mainBox *gui.Node
// #### autotypist Global Display Options
autoHidePerfect *gui.Node
autoHideReadOnly *gui.Node
forge *forgepb.Forge // your customized repo preferences and settings
// #### autotypist Global Build Options
// what to change all the branches to
// so, as a developer, you can move all the repos
// to the 'devel' branch and then test a devel branch build
// then switch back to your 'username' branch and do a build there
toMoveToBranch string
// displays the preferred names used for the repo tree state
mainBranch *gadgets.BasicCombobox
develBranch *gadgets.BasicCombobox
userBranch *gadgets.BasicCombobox
// this button will regenerate everyones go.mod & go.sum
rerunGoMod *gui.Node
// if checked, will stop trying to os.Exec() things after failure
stopOnErrors *gui.Node
// button to attempt to autorebuild
autoRebuildButton *gui.Node
// checkbox for --dry-run
autoDryRun *gui.Node
@ -45,18 +55,45 @@ type autoType struct {
// The current working directory
autoWorkingPwd *gadgets.OneLiner
// shows what directory being used as ~/go/src
// what is being used as your home dir
userHomePwd *gadgets.OneLiner
// what is being used as ~/go/src
goSrcPwd *gadgets.OneLiner
// button to download everything
downloadEverythingButton *gui.Node
// button to delete everythign ~/go/src & ~/go/pkg
// delete ~/go/src & ~/go/pkg buttons
deleteGoSrcPkgB *gui.Node
// button to set all repo branches to master
setBranchesToMasterB *gui.Node
// show the time it took to do a scan
duration *gui.Node
}
/*
var cmds *gui.Node
var doit *gui.Node
var dryrun *gui.Node
*/
type repo struct {
hidden bool
path string
lasttagrev string
lasttag string
pLabel *gui.Node // path label
// bLabel *gui.Node // branch label
lastTag *gui.Node // last tagged version label
vLabel *gui.Node // version label
dirtyLabel *gui.Node // git state (dirty or not?)
goSumStatus *gui.Node // what is the state of the go.sum file
// masterName *gui.Node // the master branch name
masterVersion *gui.Node // the master branch version
// develName *gui.Node // the devel branch name
develVersion *gui.Node // the devel branch version
// userName *gui.Node // the jcarr branch name
userVersion *gui.Node // the jcarr branch version
statusButton *gui.Node // opens up the status window
status *repostatus.RepoStatus
}

View File

@ -1,20 +0,0 @@
#!/bin/bash -x
if [ "$1" == "guimaster" ]; then
git checkout devel
git branch -D guimaster
git branch guimaster
git checkout guimaster
git push --set-upstream --force origin guimaster
exit
fi
if [ "$1" == "master" ]; then
git checkout devel
git branch -D master
git branch master
git checkout master
git push --set-upstream --force origin master
exit
fi