summaryrefslogtreecommitdiff
path: root/tagWindow.go
diff options
context:
space:
mode:
Diffstat (limited to 'tagWindow.go')
-rw-r--r--tagWindow.go266
1 files changed, 266 insertions, 0 deletions
diff --git a/tagWindow.go b/tagWindow.go
new file mode 100644
index 0000000..fcf1d56
--- /dev/null
+++ b/tagWindow.go
@@ -0,0 +1,266 @@
+package repostatus
+
+import (
+ "regexp"
+ "slices"
+ "strings"
+
+ "go.wit.com/gui"
+ "go.wit.com/lib/gadgets"
+ "go.wit.com/log"
+)
+
+type repoTag struct {
+ // tracks if the tag is displayed
+ hidden bool
+
+ // the tag "v0.1.3"
+ tag *gui.Node
+
+ // the .git/ref hash
+ ref *gui.Node
+
+ // the .git/ref date
+ date *gui.Node
+
+ // a button to delete the tag
+ deleteB *gui.Node
+}
+
+type repoTags struct {
+ // the originating repository
+ rs *RepoStatus
+
+ // the window for the tags
+ window *gadgets.BasicWindow
+
+ // the box to list all the tags in
+ box *gui.Node
+ group *gui.Node
+ grid *gui.Node
+
+ // all the tags
+ tags []*repoTag
+}
+
+func (rs *RepoStatus) TagWindow() *repoTags {
+ // return the window if it was already created
+ if rs.TagsW != nil {
+ rs.TagsW.window.Toggle()
+ return rs.TagsW
+ }
+ tags := new(repoTags)
+ rs.TagsW = tags
+ tags.rs = rs
+
+ tags.window = gadgets.RawBasicWindow("tags " + rs.String())
+ vbox := tags.window.Box()
+
+ tags.newTagBox(vbox)
+ return tags
+}
+
+func (tagW *repoTags) newTagBox(box *gui.Node) {
+ tagW.group = box.NewGroup(".git tags for " + tagW.rs.String())
+
+ tagW.group.NewButton("prune tags", func() {
+ tagW.Prune()
+ })
+ tagW.group.NewButton("show all", func() {
+ for _, t := range tagW.tags {
+ t.Show()
+ }
+ })
+ tagW.group.NewButton("delete all", func() {
+ for i, t := range tagW.tags {
+ if t.hidden {
+ // log.Info("tag is hidden", i, t.tag.String())
+ continue
+ }
+ log.Info("tag is shown", i, t.tag.String())
+ tagW.Delete(t)
+ }
+ })
+
+ grid := tagW.group.NewGrid("tags", 4, 1)
+ tagW.grid = grid
+
+ grid.NewLabel("version")
+ grid.NewLabel("ref")
+ grid.NewLabel("date")
+ grid.NewLabel("delete")
+ // works like a typerwriter
+ // grid.NextRow()
+
+ // git tag --list --sort=taggerdate
+ // git for-each-ref --sort=taggerdate --format '%(tag) %(*objectname) %(taggerdate)'
+ // git rev-parse HEAD
+ // if last tag == HEAD, then remove it
+
+ tags := []string{"%(tag)", "%(*objectname)", "%(taggerdate:raw)"}
+ format := strings.Join(tags, "_,,,_")
+ err, output := tagW.rs.RunCmd([]string{"git", "for-each-ref", "--sort=taggerdate", "--format", format})
+ if err != nil {
+ output = "git error_,,,_a_,,,_b_,,,c"
+ }
+
+ lines := strings.Split(output, "\n")
+ // reverse the git order
+ slices.Reverse(lines)
+ tagW.tags = make([]*repoTag, 0)
+
+ for i, line := range lines {
+ var parts []string
+ parts = make([]string, 6)
+ parts = strings.Split(line, "_,,,_")
+ log.Info("found tag:", i, parts)
+ if parts[0] == "" {
+ continue
+ }
+ rTag := new(repoTag)
+ rTag.tag = grid.NewLabel(parts[0])
+ rTag.ref = grid.NewEntrybox(parts[1])
+ rTag.date = grid.NewLabel(parts[2])
+ rTag.deleteB = grid.NewButton("delete", func() {
+ log.Info("remove tag")
+ })
+
+ tagW.tags = append(tagW.tags, rTag)
+ // works like a typerwriter
+ // grid.NextRow()
+ }
+ // reverse the git order
+ // slices.Reverse(rtags.tags)
+}
+
+func (rtags *repoTags) ListAll() []*repoTag {
+ var tags []*repoTag
+ for _, t := range rtags.tags {
+ tags = append(tags, t)
+ }
+ return tags
+}
+
+func (rtags *repoTags) List() []*repoTag {
+ var tags []*repoTag
+ for _, t := range rtags.tags {
+ if t.hidden {
+ // log.Info("tag is hidden", i, t.tag.String())
+ continue
+ }
+ // log.Info("tag is shown", t.tag.String(), rtags.rs.String())
+ tags = append(tags, t)
+ }
+ return tags
+}
+
+func (rtags *repoTags) Prune() {
+ dups := make(map[string]*repoTag)
+ for i, t := range rtags.tags {
+ if t == nil {
+ log.Info("tag empty:", i)
+ continue
+ }
+ ref := t.ref.String()
+ _, ok := dups[ref]
+ if ok {
+ log.Info("tag is duplicate:", i, t.tag.String())
+ } else {
+ log.Info("new tag", i, t.tag.String())
+ dups[ref] = t
+ t.Hide()
+ }
+
+ }
+}
+
+// hide tags worth keeping
+func (rtags *repoTags) PruneSmart() {
+ // always keep the first tag
+ var first bool = true
+
+ dups := make(map[string]*repoTag)
+ for i, t := range rtags.tags {
+ if t == nil {
+ log.Info("tag empty:", i)
+ continue
+ }
+
+ // check for duplicate tags
+ ref := t.ref.String()
+ _, ok := dups[ref]
+ if ok {
+ log.Info("tag is duplicate:", i, t.tag.String())
+ continue
+ }
+ dups[ref] = t
+
+ // dump any tags that don't start with 'v'
+ //if !strings.HasPrefix(t.tag.String(), "v") {
+ // log.Info("tag does not start with v", i, t.tag.String())
+ // continue
+ //}
+
+ isVersion := regexp.MustCompile("v[0-9]+.[0-9]+.[0-9]+").MatchString
+ if isVersion(t.tag.String()) {
+ log.Info("valid tag", i, t.tag.String())
+ t.Hide()
+ continue
+ }
+
+ if first {
+ log.Info("keep first tag", i, t.tag.String())
+ t.Hide()
+ first = false
+ continue
+ }
+
+ log.Info("keep tag", i, t.tag.String())
+ }
+}
+
+// deleting it locally triggers some but when
+// the git server was uncontactable (over IPv6 if that matters, probably it doesn't)
+// and then the local delete re-added it into the tag
+func (rtags *repoTags) Delete(rt *repoTag) {
+ rs := rtags.rs
+
+ cmd := []string{"git", "push", "--delete", "origin", rt.tag.String()}
+ log.Info("RUN:", cmd)
+ err, output := rs.RunCmd(cmd)
+ if err != nil {
+ log.Info("cmd failed", err)
+ log.Info("output:", output)
+ }
+ log.Info("output:", output)
+
+ cmd = []string{"git", "tag", "--delete", rt.tag.String()}
+ log.Info("RUN:", cmd)
+ err, output = rs.RunCmd(cmd)
+ if err != nil {
+ log.Info("cmd failed", err)
+ log.Info("output:", output)
+ }
+ log.Info("output:", output)
+
+}
+
+func (rt *repoTag) TagString() string {
+ return rt.tag.String()
+}
+
+func (rt *repoTag) Hide() {
+ rt.hidden = true
+ rt.tag.Hide()
+ rt.ref.Hide()
+ rt.date.Hide()
+ rt.deleteB.Hide()
+}
+
+func (rt *repoTag) Show() {
+ rt.hidden = false
+ rt.tag.Show()
+ rt.ref.Show()
+ rt.date.Show()
+ rt.deleteB.Show()
+}