commit 87346d9452b38db517e76e070f11928060bc2b99 Author: Jeff Carr Date: Tue Jan 9 15:34:53 2024 -0600 initial commit diff --git a/args.go b/args.go new file mode 100644 index 0000000..d342ac8 --- /dev/null +++ b/args.go @@ -0,0 +1,32 @@ +package repostatus + +/* + this enables command line options from other packages like 'gui' and 'log' +*/ + +import ( + "go.wit.com/log" +) + +var NOW *log.LogFlag +var INFO *log.LogFlag + +var SPEW *log.LogFlag +var WARN *log.LogFlag + +var CHANGE *log.LogFlag +var STATUS *log.LogFlag + +func init() { + full := "go.wit.com/gui/gadgets/repostatus" + short := "repostatus" + + NOW = log.NewFlag( "NOW", true, full, short, "temp debugging stuff") + INFO = log.NewFlag("INFO", false, full, short, "normal debugging stuff") + + WARN = log.NewFlag("WARN", true, full, short, "bad things") + SPEW = log.NewFlag("SPEW", false, full, short, "spew stuff") + + CHANGE = log.NewFlag("CHANGE", true, full, short, "when repo changes") + STATUS = log.NewFlag("STATUS", false, full, short, "current status") +} diff --git a/common.go b/common.go new file mode 100644 index 0000000..c70356e --- /dev/null +++ b/common.go @@ -0,0 +1,85 @@ +package repostatus + +import ( + "go.wit.com/log" + "go.wit.com/gui/gui" +) + +// reports externally if something has changed +// since the last time it was asked about it +func (ls *RepoStatus) Changed() bool { + if ! ls.Ready() {return false} + if ls.changed { + ls.changed = false + return true + } + return false +} + +func (ls *RepoStatus) Make() { + if ! ls.Ready() {return} + log.Log(CHANGE, "Make() window ready =", ls.ready) + ls.window.Make() + ls.ready = true +} +func (ls *RepoStatus) Draw() { + if ! ls.Ready() {return} + log.Log(CHANGE, "Draw() window ready =", ls.ready) + ls.window.Draw() + ls.ready = true +} +func (ls *RepoStatus) Draw2() { + if ! ls.Ready() {return} + log.Log(CHANGE, "draw(ls) ready =", ls.ready) + draw(ls) +} + +func (ls *RepoStatus) Show() { + if ! ls.Ready() {return} + log.Log(CHANGE, "Show() window ready =", ls.ready) + ls.window.Show() + ls.hidden = false +} + +func (ls *RepoStatus) Hide() { + if ! ls.Ready() {return} + log.Log(CHANGE, "Hide() window ready =", ls.ready) + ls.window.Hide() + ls.hidden = true +} + +func (ls *RepoStatus) Toggle() { + if ! ls.Ready() {return} + log.Log(CHANGE, "Toggle() window ready =", ls.ready) + if ls.hidden { + ls.Show() + } else { + ls.Hide() + } +} + +func (ls *RepoStatus) Ready() bool { + log.Log(SPEW, "Ready() maybe not ready? ls =", ls) + if ls == nil {return false} + if ls.window == nil {return false} + return ls.ready +} + +func (ls *RepoStatus) Initialized() bool { + log.Log(CHANGE, "checking Initialized()") + if ls == nil {return false} + if ls.parent == nil {return false} + return true +} + +func (ls *RepoStatus) SetParent(p *gui.Node) { + log.Log(CHANGE, "Attempting SetParent") + if ls == nil {return} + if ls.parent == nil { + log.Log(CHANGE, "SetParent =", p) + ls.parent = p + return + } else { + log.Log(CHANGE, "SetParent was already set to =", ls.parent) + } +} diff --git a/draw.go b/draw.go new file mode 100644 index 0000000..33d655f --- /dev/null +++ b/draw.go @@ -0,0 +1,48 @@ +package repostatus + +import ( + "go.wit.com/log" + "go.wit.com/gui/gadgets" +) + +// creates the actual widgets. +// it's assumed you are always passing in a box +func draw(rs *RepoStatus) { + if ! rs.Ready() {return} + rs.group = rs.window.Box().NewGroup("What GO Knows It Has") + + rs.grid = rs.group.NewGrid("gridnuts", 2, 2) + + rs.grid.SetNext(1,1) + + rs.path = gadgets.NewOneLiner(rs.grid, "path") + rs.currentBranch = gadgets.NewOneLiner(rs.grid, "branch") + rs.lasttag = gadgets.NewOneLiner(rs.grid, "last tag") + rs.currentVersion = gadgets.NewOneLiner(rs.grid, "Version") + + rs.grid.NewLabel("tags") + rs.tagsDrop = rs.grid.NewDropdown("tags") + rs.masterBranch = gadgets.NewOneLiner(rs.grid, "master") + rs.develBranch = gadgets.NewOneLiner(rs.grid, "devel") + rs.jcarrBranch = gadgets.NewOneLiner(rs.grid, "jcarr") + + rs.dirtyLabel = gadgets.NewOneLiner(rs.grid, "dirty") + + rs.speed = gadgets.NewOneLiner(rs.grid, "refresh speed =") + rs.speedActual = gadgets.NewOneLiner(rs.grid, "speed actual =") + + rs.grid.NewButton("update", func() { + rs.Update() + }) + rs.grid.NewButton("recommend", func() { + log.Warn("Is repo dirty?", rs.dirtyLabel.Get()) + log.Warn("list the known tags") + rs.populateTags() + log.Warn("Does master == devel? ") + log.Warn("Does devel == jcarr?") + log.Warn("Is repo pushed upstream? git.wit.org or github?") + }) + + rs.grid.Margin() + rs.grid.Pad() +} diff --git a/git.go b/git.go new file mode 100644 index 0000000..477e956 --- /dev/null +++ b/git.go @@ -0,0 +1,81 @@ +package repostatus + +import ( + "go.wit.com/log" +) + +func (rs *RepoStatus) getCurrentBranchName() string { + out := run(rs.repopath, "git", "branch --show-current") + log.Warn("getCurrentBranchName() =", out) + rs.currentBranch.Set(out) + return out +} + +func (rs *RepoStatus) getCurrentBranchVersion() string { + out := run(rs.repopath, "git", "describe --tags") + log.Warn("getCurrentBranchVersion()", out) + rs.currentVersion.Set(out) + return out +} + +func (rs *RepoStatus) getLastTagVersion() string { + out := run(rs.repopath, "git", "rev-list --tags --max-count=1") + log.Warn("getLastTagVersion()", out) + rs.lasttagrev = out + + lastreal := "describe --tags " + out + // out = run(r.path, "git", "describe --tags c871d5ecf051a7dc4e3a77157cdbc0a457eb9ae1") + out = run(rs.repopath, "git", lastreal) + rs.lasttag.Set(out) + // rs.lastLabel.Set(out) + return out +} + +func (rs *RepoStatus) populateTags() { + tmp := fullpath(rs.repopath + "/.git/refs/tags") + log.Warn("populateTags() path =", tmp) + for _, tag := range listFiles(tmp) { + if rs.tags[tag] == "" { + log.Warn("populateTags() Adding new tag", tag) + rs.tagsDrop.AddText(tag) + rs.tags[tag] = "origin" + } + } + rs.tagsDrop.SetText(rs.lasttagrev) +} + +func (rs *RepoStatus) checkDirty() bool { + out := run(rs.repopath, "git", "diff-index HEAD") + if out == "" { + log.Warn("checkDirty() no", rs.repopath) + rs.dirtyLabel.Set("no") + return false + } else { + log.Warn("checkDirty() true", rs.repopath) + rs.dirtyLabel.Set("dirty") + return true + } + +} + +func (rs *RepoStatus) checkoutBranch(branch string) { + if rs.checkDirty() { + log.Warn("checkoutBranch() checkDirty() == true for repo", rs.repopath, "looking for branch:", branch) + return + } + out := run(rs.repopath, "git", "checkout " + branch) + log.Warn(rs.repopath, "git checkout " + branch, "returned", out) + + realname := rs.getCurrentBranchName() + realversion := rs.getCurrentBranchVersion() + log.Warn(rs.repopath, "realname =", realname, "realversion =", realversion) + if realname == "jcarr" { + rs.jcarrBranch.Set(realversion) + } + if realname == "devel" { + rs.develBranch.Set(realversion) + } + if realname == "master" { + rs.masterBranch.Set(realversion) + } +} diff --git a/new.go b/new.go new file mode 100644 index 0000000..c18480e --- /dev/null +++ b/new.go @@ -0,0 +1,35 @@ +package repostatus + +import ( + "go.wit.com/log" + + "go.wit.com/gui/gui" + "go.wit.com/gui/gadgets" +) + +func New(p *gui.Node, path string) *RepoStatus { + rs := &RepoStatus { + hidden: true, + ready: false, + parent: p, + repopath: path, + } + rs.tags = make(map[string]string) + return rs +} + +func (rs *RepoStatus) InitWindow() { + if ! rs.Initialized() { + log.Log(WARN, "not initalized yet (no parent for the window?)") + return + } + if rs.window != nil { + log.Log(WARN, "You already have a window") + rs.ready = true + return + } + + log.Log(WARN, "Creating the Window") + rs.window = gadgets.NewBasicWindow(rs.parent, "GO Repo Details") + rs.ready = true +} diff --git a/structs.go b/structs.go new file mode 100644 index 0000000..b2b8b94 --- /dev/null +++ b/structs.go @@ -0,0 +1,38 @@ +package repostatus + +import ( + "go.wit.com/gui/gui" + "go.wit.com/gui/gadgets" +) + +type RepoStatus struct { + ready bool + hidden bool + changed bool + + repopath string + lasttagrev string + tags map[string]string + + parent *gui.Node + + window *gadgets.BasicWindow + group *gui.Node + grid *gui.Node + +// status *gadgets.OneLiner + dirtyLabel *gadgets.OneLiner + path *gadgets.OneLiner + + currentBranch *gadgets.OneLiner + currentVersion *gadgets.OneLiner + tagsDrop *gui.Node + + lasttag *gadgets.OneLiner + masterBranch *gadgets.OneLiner + develBranch *gadgets.OneLiner + jcarrBranch *gadgets.OneLiner + + speed *gadgets.OneLiner + speedActual *gadgets.OneLiner +} diff --git a/timer.go b/timer.go new file mode 100644 index 0000000..9e9e589 --- /dev/null +++ b/timer.go @@ -0,0 +1,17 @@ +package repostatus + +import ( + "time" +) + +// timeFunction takes a function as an argument and returns the execution time. +func timeFunction(f func()) time.Duration { + startTime := time.Now() // Record the start time + f() // Execute the function + return time.Since(startTime) // Calculate the elapsed time +} + +func (ls *RepoStatus) SetSpeedActual(s string) { + if ! ls.Ready() {return} + ls.speedActual.Set(s) +} diff --git a/unix.go b/unix.go new file mode 100644 index 0000000..1f31700 --- /dev/null +++ b/unix.go @@ -0,0 +1,54 @@ +// This is a simple example +package repostatus + +import ( + "os" + "os/exec" + "strings" + + "go.wit.com/log" +) + +func fullpath(repo string) string { + return "/home/jcarr/go/src/" + repo +} + +func run(path string, thing string, cmdline string) string { + parts := strings.Split(cmdline, " ") + // Create the command + cmd := exec.Command(thing, parts...) + + // Set the working directory + cmd.Dir = fullpath(path) + + // Execute the command + output, err := cmd.CombinedOutput() + if err != nil { + log.Error(err, "cmd error'd out", parts) + return "" + } + + tmp := string(output) + tmp = strings.TrimSpace(tmp) + + // Print the output + log.Log(WARN, "run()", path, thing, cmdline, "=", tmp) + return tmp +} + +func listFiles(directory string) []string { + var files []string + fileInfo, err := os.ReadDir(directory) + if err != nil { + log.Error(err) + return nil + } + + for _, file := range fileInfo { + if !file.IsDir() { + files = append(files, file.Name()) + } + } + + return files +} diff --git a/update.go b/update.go new file mode 100644 index 0000000..e7544d6 --- /dev/null +++ b/update.go @@ -0,0 +1,57 @@ +package repostatus + +import ( + "fmt" + "time" + "errors" + + "go.wit.com/log" +) + +func (rs *RepoStatus) Update() { + if ! rs.Ready() { + log.Log(WARN, "can't update yet. ready is false") + log.Error(errors.New("Update() is not ready yet")) + return + } + log.Log(WARN, "Update() START") + duration := timeFunction(func () { + rs.path.Set(rs.repopath) + rs.getCurrentBranchName() + rs.window.Title(rs.repopath + " GO repo Details") + rs.getCurrentBranchVersion() + + rs.getLastTagVersion() + rs.populateTags() + + // rs.checkDirty() this runs + log.Log(WARN, "") + log.Log(WARN, "checkoutBranch master") + rs.checkoutBranch("master") + log.Log(WARN, "") + log.Log(WARN, "checkoutBranch devel") + rs.checkoutBranch("devel") + log.Log(WARN, "") + log.Log(WARN, "checkoutBranch jcarr") + rs.checkoutBranch("jcarr") + }) + rs.setSpeed(duration) + log.Log(WARN, "Update() END") +} + +func (rs *RepoStatus) setSpeed(duration time.Duration) { + s := fmt.Sprint(duration) + if rs.speedActual == nil { + log.Log(WARN, "can't actually warn") + return + } + rs.speedActual.Set(s) + + if (duration > 500 * time.Millisecond ) { + rs.speed.Set("SLOW") + } else if (duration > 100 * time.Millisecond ) { + rs.speed.Set("OK") + } else { + rs.speed.Set("FAST") + } +}