forge/windowRepoProblems.go

254 lines
6.1 KiB
Go

// Copyright 2017-2025 WIT.COM Inc. All rights reserved.
// Use of this source code is governed by the GPL 3.0
package main
import (
"fmt"
"sync"
"go.wit.com/lib/gadgets"
"go.wit.com/lib/protobuf/forgepb"
"go.wit.com/lib/protobuf/gitpb"
"go.wit.com/log"
"go.wit.com/gui"
)
type repoProblemsWindow struct {
once sync.Once // only init() the window once
win *gadgets.BasicWindow // the patches window
stack *gui.Node // the top box set as vertical
shelf *gui.Node // the first box in the stack, set as horizontal
grid *gui.Node // the list of available patches
// summary *patchSummary // summary of current patches
setgrid *gui.Node // the list of each patchset
pset *forgepb.Patchset // the patchset in question
}
// todo: autogenerate these or make them standared 'gui' package functions
// make this an go interface somehow
// is the window hidden right now?
func (w *repoProblemsWindow) Hidden() bool {
return w.win.Hidden()
}
// switches between the window being visable or hidden on the desktop
func (w *repoProblemsWindow) Toggle() {
if w.Hidden() {
w.Show()
} else {
w.Hide()
}
}
// hides the window completely
func (w *repoProblemsWindow) Show() {
w.win.Show()
}
func (w *repoProblemsWindow) Hide() {
w.win.Hide()
}
// should be the first box/widget in the window
// greys out the window to the user
func (w *repoProblemsWindow) Disable() {
w.stack.Disable()
}
func (w *repoProblemsWindow) Enable() {
w.stack.Enable()
}
// you can only have one of these
func makeRepoProblemsWindow() *repoProblemsWindow {
pw := new(repoProblemsWindow)
// sync.Once()
pw.win = gadgets.RawBasicWindow("Potential Repo Problems")
pw.win.Make()
pw.win.Show()
pw.stack = pw.win.Box().NewBox("bw vbox", false)
pw.win.Custom = func() {
// sets the hidden flag to false so Toggle() works
pw.win.Hide()
}
pw.stack.NewGroup("things (these don't work yet)")
grid := pw.stack.RawGrid()
var found *gitpb.Repos
var txt string
found = develBehindMasterProblem()
txt = fmt.Sprintf("devel is behind master (%d)", found.Len())
grid.NewButton(txt, func() {
win := gadgets.RawBasicWindow("devel branches that are out of sync with master")
win.Make()
win.Show()
win.Custom = func() {
// sets the hidden flag to false so Toggle() works
win.Hide()
}
box := win.Box().NewBox("bw vbox", false)
found := develBehindMasterProblem()
group := box.NewGroup("test buttons")
group.NewButton("hello", func() {
log.Info("world")
})
t := makeStandardReposGrid(found)
t.SetParent(box)
t.ShowTable()
})
found = remoteUserBranchProblem()
txt = fmt.Sprintf("user branch is remote (%d)", found.Len())
grid.NewButton(txt, func() {
win := gadgets.RawBasicWindow("repos that seem to have remote user branches")
win.Make()
win.Show()
win.Custom = func() {
// sets the hidden flag to false so Toggle() works
win.Hide()
}
box := win.Box().NewBox("bw vbox", false)
found := remoteUserBranchProblem()
group := box.NewGroup("test buttons")
group.NewButton("git branch delete", func() {
win.Disable()
defer win.Enable()
all := found.SortByFullPath()
for all.Scan() {
repo := all.Next()
brname := repo.GetUserBranchName()
// git push origin --delete jcarr
cmd := []string{"git", "push", "origin", "--delete", brname}
log.Info(repo.GetGoPath(), cmd)
repo.RunVerbose(cmd)
// git branch --delete --remote origin/jcarr
cmd = []string{"git", "branch", "--delete", "--remote", "origin/" + brname}
log.Info(repo.GetGoPath(), cmd)
repo.RunVerbose(cmd)
repo.Reload()
}
me.forge.SetConfigSave(true)
me.forge.ConfigSave()
})
t := makeStandardReposGrid(found)
t.SetParent(box)
t.ShowTable()
})
grid.NewButton("unknown branches", func() {
log.Info("not done yet")
})
grid.NextRow()
found = develRemoteProblem()
txt = fmt.Sprintf("remote devel != local devel (%d)", found.Len())
grid.NewButton(txt, func() {
found := develRemoteProblem()
makeStandardReposWindow(txt, found)
})
found = masterRemoteProblem()
txt = fmt.Sprintf("remote master != local master (%d)", found.Len())
grid.NewButton(txt, func() {
found := masterRemoteProblem()
makeStandardReposWindow(txt, found)
})
grid.NextRow()
return pw
}
func develBehindMasterProblem() *gitpb.Repos {
log.Info("not done yet")
found := new(gitpb.Repos)
all := me.forge.Repos.SortByFullPath()
for all.Scan() {
repo := all.Next()
if repo.GetDevelVersion() == repo.GetMasterVersion() {
continue
}
found.AppendByGoPath(repo)
}
return found
}
func remoteUserBranchProblem() *gitpb.Repos {
found := new(gitpb.Repos)
all := me.forge.Repos.SortByFullPath()
for all.Scan() {
repo := all.Next()
username := repo.GetUserBranchName()
if repo.IsBranchRemote(username) {
found.AppendByGoPath(repo)
}
}
return found
}
func develRemoteProblem() *gitpb.Repos {
found := new(gitpb.Repos)
all := me.forge.Repos.SortByFullPath()
for all.Scan() {
repo := all.Next()
brname := repo.GetDevelBranchName()
if !repo.IsBranchRemote(brname) {
// log.Info("repo does not have remote devel branch", repo.GetGoPath())
continue
}
lhash := repo.GetLocalHash(brname)
rhash := repo.GetRemoteHash(brname)
// log.Info(lhash, rhash, repo.GetGoPath())
if lhash == "" || rhash == "" {
// something is wrong if either of these are blank
found.AppendByGoPath(repo)
continue
}
if lhash == rhash {
continue
}
found.AppendByGoPath(repo)
}
return found
}
func masterRemoteProblem() *gitpb.Repos {
found := new(gitpb.Repos)
all := me.forge.Repos.SortByFullPath()
for all.Scan() {
repo := all.Next()
brname := repo.GetMasterBranchName()
if !repo.IsBranchRemote(brname) {
// log.Info("repo does not have remote devel branch", repo.GetGoPath())
continue
}
lhash := repo.GetLocalHash(brname)
rhash := repo.GetRemoteHash(brname)
// log.Info(lhash, rhash, repo.GetGoPath())
if lhash == "" || rhash == "" {
// something is wrong if either of these are blank
found.AppendByGoPath(repo)
continue
}
if lhash == rhash {
continue
}
found.AppendByGoPath(repo)
}
return found
}