diff --git a/Makefile b/Makefile index a23dbf5..fa6edc9 100644 --- a/Makefile +++ b/Makefile @@ -28,7 +28,8 @@ goimports: # // to globally reset paths: # // gofmt -w -r '"go.wit.com/gui/gadgets" -> "go.wit.com/lib/gadgets"' *.go -gocui: build +# build then run with gui in libcurses +console: build reset ./autotypist --gui gocui >/tmp/autotypist.log 2>&1 @@ -45,3 +46,24 @@ redomod: GO111MODULE= go mod init GO111MODULE= go mod tidy +curl-help: + curl --silent http://localhost:9419/help + +curl-list: + curl --silent http://localhost:9419/list?perfect=false + +curl-list-readonly: + curl --silent http://localhost:9419/list?readonly=true + +curl-gitpull-everypackage: + curl --silent http://localhost:9419/gitpull + +curl-gitpull-helloworld: + curl --silent http://localhost:9419/gitpull?repo=go.wit.com/apps/helloworld + +curl-gitpull-basicworld: + curl --silent http://localhost:9419/gitpull?repo=go.wit.com/apps/basicworld + +curl-file-for-go.wit.com: + curl --silent http://localhost:9419/goweblist?readonly=true + curl --silent http://localhost:9419/goweblist?readonly=true |sort > ~/go.wit.com.versions diff --git a/args.go b/args.go index af016ef..5515f88 100644 --- a/args.go +++ b/args.go @@ -14,16 +14,17 @@ import ( "go.wit.com/log" ) -var args struct { - DownloadAll bool `arg:"--download-all" help:"download everything from go.wit.com"` - GitPull bool `arg:"--git-pull" help:"do git pull in every repository"` - CheckoutUser bool `arg:"--switch-to-user-branch" help:"switch everything to your user branch"` - CheckoutDevel bool `arg:"--switch-to-devel-branch" help:"switch everything to the devel branch"` - OnlyMe bool `arg:"--only-me" help:"only scan repos from ~/.config/autotypist"` +var argv struct { + DownloadAll bool `arg:"--download-all" help:"download everything from go.wit.com"` + GitPull bool `arg:"--git-pull" help:"do git pull in every repository"` + CheckoutUser bool `arg:"--switch-to-user-branch" help:"switch everything to your user branch"` + CheckoutDevel bool `arg:"--switch-to-devel-branch" help:"switch everything to the devel branch"` + OnlyMe bool `arg:"--only-me" help:"only scan repos from ~/.config/autotypist"` + Port int `arg:"--port" default:"9419" help:"do fun stuff with curl"` } func init() { - arg.MustParse(&args) + arg.MustParse(&argv) if debugger.ArgDebug() { log.Info("cmd line --debugger == true") @@ -47,7 +48,7 @@ func init() { func handleCmdLine() { var doExit bool = false - if args.CheckoutDevel { + if argv.CheckoutDevel { me.autotypistWindow.Hide() me.repos.View.ArgCheckoutDevel() doExit = true @@ -55,7 +56,7 @@ func handleCmdLine() { log.Info("not switching to devel branches") } - if args.CheckoutUser { + if argv.CheckoutUser { me.autotypistWindow.Hide() me.repos.View.ArgCheckoutUser() doExit = true @@ -63,7 +64,7 @@ func handleCmdLine() { log.Info("not switching to user branches") } - if args.GitPull { + if argv.GitPull { me.autotypistWindow.Hide() if me.repos.View.ArgGitPull() { log.Info("git pull everywhere worked") diff --git a/globalBuildOptions.go b/globalBuildOptions.go index c484926..baedd06 100644 --- a/globalBuildOptions.go +++ b/globalBuildOptions.go @@ -69,34 +69,34 @@ func globalBuildOptions(vbox *gui.Node) { // 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 - /* - if repo.Status.BranchExists(targetName) { - ok := repo.Status.CheckoutBranch(targetName) - if ok { - // checkout went fine - continue - } - log.Info("couldn't set", repo.Status.Path(), "branch to", targetName) - log.Info("but branch exists so something went wrong") - continue - } - if !me.autoCreateBranches.Checked() { - log.Info("not auto creating branch", targetName) - continue - } - // branch doesn't exist. make it - // todo: make this branch from 'devel' branch if it exists - log.Info("should make the", targetName, "branch here!") - if me.autoCreateBranches.Checked() { - log.Info("going to make the branch!") - repo.Status.RunCmd([]string{"git", "branch", targetName}) - repo.Status.RunCmd([]string{"git", "checkout", targetName}) - } else { - log.Info("not auto creating branch", targetName) - } - repo.Scan() - count += 1 - */ + /* + if repo.Status.BranchExists(targetName) { + ok := repo.Status.CheckoutBranch(targetName) + if ok { + // checkout went fine + continue + } + log.Info("couldn't set", repo.Status.Path(), "branch to", targetName) + log.Info("but branch exists so something went wrong") + continue + } + if !me.autoCreateBranches.Checked() { + log.Info("not auto creating branch", targetName) + continue + } + // branch doesn't exist. make it + // todo: make this branch from 'devel' branch if it exists + log.Info("should make the", targetName, "branch here!") + if me.autoCreateBranches.Checked() { + log.Info("going to make the branch!") + repo.Status.RunCmd([]string{"git", "branch", targetName}) + repo.Status.RunCmd([]string{"git", "checkout", targetName}) + } else { + log.Info("not auto creating branch", targetName) + } + repo.Scan() + count += 1 + */ grid.NextRow() diff --git a/go.wit.com.versions b/go.wit.com.versions new file mode 100644 index 0000000..792c209 --- /dev/null +++ b/go.wit.com.versions @@ -0,0 +1,48 @@ +/home/jcarr/jcarr 1d v1.4.2 refs/remotes/origin/prod +curl --silent http://localhost:9419/goweblist?readonly=true +git.wit.org/jcarr/clone-gitea 257d v0.20.4 refs/remotes/origin/master +git.wit.org/jcarr/golang-examples 238d refs/remotes/origin/master +git.wit.org/jcarr/jcarrgitpull 244d v0.22.0 refs/tags/v0.22.0 +git.wit.org/jcarr/personal-gui 256d v0.20.8 refs/tags/v0.20.8 +git.wit.org/jcarr/wit-new-machine 253d v0.21.0 refs/tags/v0.21.0 +git.wit.org/wit/wit-debian-gui 253d v0.21.0 refs/tags/v0.21.0 +go.wit.com/apps/autotypist 240d v0.22.1 refs/tags/v0.22.1 +go.wit.com/apps/control-panel-dns 1d v0.22.0 refs/remotes/origin/jcarr +go.wit.com/apps/go-clone 1d v0.5 refs/tags/v0.5 +go.wit.com/apps/go-deb 244d v0.22.0 refs/tags/v0.22.0 +go.wit.com/apps/go-gui-toolkits 244d v0.22.0 refs/tags/v0.22.0 +go.wit.com/apps/go.wit.com 27d v0.22.1 refs/remotes/origin/jcarr +go.wit.com/apps/guireleaser 1d v0.22.2 refs/remotes/origin/jcarr +go.wit.com/apps/helloworld 253d v0.21.0 refs/tags/v0.21.0 +go.wit.com/apps/powerpaneld 27d v0.0.3 refs/remotes/origin/master +go.wit.com/apps/virtigo 18h v0.2.5 refs/tags/v0.2.5 +go.wit.com/apps/virtigoctl 1d v0.1 refs/tags/v0.1 +go.wit.com/apps/wit-packager 1d v0.22.0 refs/remotes/origin/jcarr +go.wit.com/dev/alexflint/arg 293d v1.4.5 refs/tags/v1.4.5 +go.wit.com/dev/alexflint/scalar 293d v1.2.1 refs/tags/v1.2.1 +go.wit.com/dev/andlabs/ui 293d v0.0.1 refs/tags/v0.0.1 +go.wit.com/dev/davecgh/spew 293d v1.1.4 refs/tags/v1.1.4 +go.wit.com/dev/posener/complete 1d v0.0.1 refs/tags/v0.0.1 +go.wit.com/dev/test/gogit2 262d refs/remotes/origin/master +go.wit.com/gui 240d v0.22.1 refs/tags/v0.22.1 +go.wit.com/lib/debugger 244d v0.22.0 refs/tags/v0.22.0 +go.wit.com/lib/gadgets 244d v0.22.0 refs/tags/v0.22.0 +go.wit.com/lib/gui/cloudflare 244d v0.22.0 refs/tags/v0.22.0 +go.wit.com/lib/gui/gowit 1d v0.22.1 refs/remotes/origin/jcarr +go.wit.com/lib/gui/linuxstatus 1d v0.22.0 refs/remotes/origin/jcarr +go.wit.com/lib/gui/logsettings 244d v0.22.0 refs/tags/v0.22.0 +go.wit.com/lib/gui/repolist 238d v0.22.4 refs/tags/v0.22.4 +go.wit.com/lib/gui/repostatus 1d v0.22.5 refs/remotes/origin/jcarr +go.wit.com/lib/gui/shell 1d v0.22.3 refs/remotes/origin/jcarr +go.wit.com/lib/protobuf/gitpb 3h refs/remotes/origin/master +go.wit.com/lib/protobuf/virtbuf 1d v0.2.1 refs/tags/v0.2.1 +go.wit.com/lib/virtigolib 1d v0.1.1 refs/tags/v0.1.1 +go.wit.com/log 21d v0.22.0 refs/remotes/origin/jcarr +go.wit.com/toolkits/andlabs 244d v0.22.0 refs/tags/v0.22.0 +go.wit.com/toolkits/debian 226d v0.22.1 refs/tags/v0.22.1 +go.wit.com/toolkits/fyne 247d v0.0.1 refs/tags/v0.0.1 +go.wit.com/toolkits/gocui 30d v0.22.0 refs/remotes/origin/jcarr +go.wit.com/toolkits/nocui 244d v0.22.0 refs/tags/v0.22.0 +go.wit.com/toolkits/pixelgl 253d v0.21.0 refs/tags/v0.21.0 +go.wit.com/toolkits/tree 244d v0.22.0 refs/tags/v0.22.0 +go.wit.com/widget 244d v1.1.26 refs/tags/v1.1.26 diff --git a/http.go b/http.go new file mode 100644 index 0000000..caefadb --- /dev/null +++ b/http.go @@ -0,0 +1,233 @@ +package main + +import ( + "fmt" + "net/http" + "os" + "strings" + + "go.wit.com/lib/gui/repostatus" + "go.wit.com/lib/gui/shell" + "go.wit.com/log" +) + +// remove '?' part and trailing '/' +func cleanURL(url string) string { + url = "/" + strings.Trim(url, "/") + return url +} + +// send stuff to the socket and stdout +func msg(w http.ResponseWriter, s string) { + log.Info(s) + fmt.Fprintln(w, s) +} + +func okHandler(w http.ResponseWriter, r *http.Request) { + var route string + route = cleanURL(r.URL.Path) + + if route == "/help" { + msg(w, "uptime/ uptime uptime fun!") + msg(w, "list/ list modified repos") + msg(w, "list?readonly=true shows every repo") + msg(w, "gitpull/ run a git pull in each repo") + + msg(w, "") + msg(w, "Examples:") + msg(w, "") + msg(w, "not done yet:") + + msg(w, "changes/ show latest changes") + msg(w, "repo?repo=go.wit.com/apps/autotypist show this repo") + msg(w, "clone?repo=go.wit.com/apps/virtigo go-clone a new repo") + msg(w, "build?repo=go.wit.com/apps/autotypist build the autotypist") + msg(w, "debian?repo=go.wit.com/apps/autotypist make a debian package of the autotypist") + return + } + + if route == "/uptime" { + s := "uptime uptime uptime fun!" + msg(w, s) + return + } + + if route == "/gitpull" { + repoName := r.URL.Query().Get("repo") + if repoName != "" { + // git pull (or go-clone of it doesn't exist) + repo := me.repos.View.FindRepoByName(repoName) + if repo == nil { + cmd := []string{"go-clone", repoName} + header := repo.StandardHeader() + msg(w, header+strings.Join(cmd, " ")) + shell.RunHttpOut(cmd, w, r) + } else { + cmd := []string{"git", "pull", "-v"} + header := repo.StandardHeader() + msg(w, header+strings.Join(cmd, " ")) + shell.RunPathHttpOut(repo.Status.FullPath(), cmd, w, r) + } + return + } + // git pull every repo. Ignore Dirty repos + loop := me.repos.View.ReposAll() + for loop.Scan() { + repo := loop.Repo() + cmd := []string{"git", "pull", "-v"} + header := repo.StandardHeader() + if repo.CheckDirty() { + msg(w, header+"skip dirty repo") + continue + } + msg(w, header+strings.Join(cmd, " ")) + shell.RunPathHttpOut(repo.Status.FullPath(), cmd, w, r) + } + return + } + + if route == "/list" { + readonly := r.URL.Query().Get("readonly") + perfect := r.URL.Query().Get("perfect") + var count int + + loop := me.repos.View.ReposSortByName() + for loop.Scan() { + repo := loop.Repo() + + count += 1 + header := repo.StandardHeader() + + if repo.ReadOnly() { + if readonly == "true" { + msg(w, header+"readonly") + } + continue + } + if repo.State() == "PERFECT" { + if perfect == "false" { + continue + } + } + if repo.State() != "merge to main" { + msg(w, header+"") + continue + } + if repo.CheckDirty() { + msg(w, header+"") + continue + } + msg(w, header+"") + } + msg(w, fmt.Sprintf("EVERYTHING WORKED repo count = %d", count)) + return + } + if route == "/goweblist" { + readonly := r.URL.Query().Get("readonly") + loop := me.repos.View.ReposAll() + for loop.Scan() { + repo := loop.Repo() + lastTag := repo.LastTag() + tag := repo.Status.NewestTag() + gitAge, err := tag.GetDate() + if err != nil { + msg(w, fmt.Sprintf("tag date error", repo.Name())) + } + // if lastTag == "" { + // lastTag = tag.Name() + // } + if repo.ReadOnly() { + if readonly == "true" { + continue + } + } + // dur := time.Since(gitAge) + // msg(w, fmt.Sprintf("%-60s %s %s %s", repo.Name(), lastTag, shell.FormatDuration(dur), lastTag, tag.Name())) + msg(w, fmt.Sprintf("%s %d %s", repo.Name(), gitAge.Unix(), lastTag)) + /* + for _, tag := range repo.Tags.ListAll() { + msg(w, fmt.Sprintf("%-60s %s", "", tag.Name())) + } + */ + + } + return + } + + if route == "/listGitDirectories" { + for i, path := range repostatus.ListGitDirectories() { + // log.Info("addRepo()", i, path) + path = strings.TrimPrefix(path, me.goSrcPwd.String()) + path = strings.Trim(path, "/") + msg(w, fmt.Sprintf("paths:", i, path)) + } + return + } + + if route == "/repo" { + reponame := r.URL.Query().Get("repo") + if reponame == "" { + s := "reponame is blank " + cleanURL(r.URL.Path) + msg(w, s) + return + } + s := "reponame is " + reponame + msg(w, s) + return + } + + if route == "/quit" { + log.Warn("writing out config file and exiting virtigo") + fmt.Fprintln(w, "writing out config file and exiting virtigo") + os.Exit(0) + return + } + + if route == "/favicon.ico" { + // w.Header().Set("Content-Type", "image/svg+xml") + w.Header().Set("Content-Type", "image/png") + writeFile(w, "ipv6.png") + return + } + + if route == "/goReference.svg" { + w.Header().Set("Content-Type", "image/svg+xml") + writeFile(w, "goReference.svg") + return + } + + log.Warn("BAD URL =", route) + fmt.Fprintln(w, "BAD URL =", route) +} + +// write a file out to the http socket +func writeFile(w http.ResponseWriter, filename string) { + fullname := "resources/" + filename + pfile, err := resources.ReadFile(fullname) + if err != nil { + log.Println("ERROR:", err) + // w.Write(pfile) + return + } + + var repohtml string + repohtml = string(pfile) + if filename == "goReference.svg" { + w.Header().Set("Content-Type", "image/svg+xml") + } + fmt.Fprintln(w, repohtml) + log.Println("writeFile() found internal file:", filename) +} + +// 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) + } +} diff --git a/initRepoList.go b/initRepoList.go index ef3b319..7f71719 100644 --- a/initRepoList.go +++ b/initRepoList.go @@ -12,7 +12,7 @@ import ( func (r *repoWindow) initRepoList() { r.View.InitRepoList(".config/autotypist") - if args.OnlyMe { + if argv.OnlyMe { log.Info("not scanning everything") } else { log.Info("scanning everything in ~/go/src") diff --git a/main.go b/main.go index d1950db..e76fd34 100644 --- a/main.go +++ b/main.go @@ -9,18 +9,21 @@ import ( ) //go:embed resources/* -var resToolkit embed.FS +var resources embed.FS func main() { me = new(autoType) me.myGui = gui.New() - me.myGui.InitEmbed(resToolkit) + me.myGui.InitEmbed(resources) me.myGui.Default() me.autotypistWindow = me.myGui.NewWindow("autotypist: it types faster than you can.") me.mainbox = me.autotypistWindow.NewBox("bw hbox", true) + // start the http server for polling status + go startHTTP() + vbox1 := me.mainbox.NewVerticalBox("BOX1") globalDisplayOptions(vbox1) docsBox(vbox1) diff --git a/simpleRelease.go b/simpleRelease.go new file mode 100644 index 0000000..c195301 --- /dev/null +++ b/simpleRelease.go @@ -0,0 +1,35 @@ +package main + +import ( + "net/http" + "strings" +) + +// attempts a simple release +// merge user branch -> devel; then; +// git push +// merge devel branch -> master; then; +// git push + +// increments the minor version by 1; then; +// git push --tags + +func simpleRelease(w http.ResponseWriter, r *http.Request) { + repoName := r.URL.Query().Get("repo") + if repoName == "" { + return + } + // git pull (or go-clone of it doesn't exist) + repo := me.repos.View.FindRepoByName(repoName) + if repo == nil { + return + } + header := repo.StandardHeader() + if repo.CheckDirty() { + msg(w, header+"skip dirty repo") + continue + } + cmd := []string{"git", "pull", "-v"} + msg(w, header+strings.Join(cmd, " ")) + return +}