forgepb/branches.go

318 lines
7.8 KiB
Go

package forgepb
import (
"os"
"path/filepath"
"time"
"go.wit.com/lib/gui/shell"
"go.wit.com/lib/protobuf/gitpb"
"go.wit.com/log"
)
var ErrorNotAllReposOnMaster error = log.Errorf("not all repos on are on the master branch")
var ErrorNotAllReposOnDevel error = log.Errorf("not all repos on are on the devel branch")
var ErrorNotAllReposOnUser error = log.Errorf("not all repos on are on the user branch")
func (f *Forge) IsEverythingOnMaster() (int, int, int, error) {
var total int
var count int
var nope int
// first make sure every repo is on the master branch
for repo := range f.Repos.IterAll() {
total += 1
if repo.GetMasterBranchName() == repo.GetCurrentBranchName() {
count += 1
} else {
nope += 1
}
}
if total != count {
// log.Info(ErrorNotAllReposOnMaster)
return total, count, nope, ErrorNotAllReposOnMaster
}
return total, count, nope, nil
}
func (f *Forge) IsEverythingOnDevel() (int, int, int, error) {
var total int
var count int
var nope int
// first make sure every repo is on the master branch
for repo := range f.Repos.IterAll() {
total += 1
if repo.GetDevelBranchName() == repo.GetCurrentBranchName() {
count += 1
} else {
nope += 1
}
}
if total != count {
return total, count, nope, ErrorNotAllReposOnDevel
}
return total, count, nope, nil
}
func (f *Forge) IsEverythingOnUser() (int, int, int, error) {
var total int
var count int
var nope int
// first make sure every repo is on the master branch
for repo := range f.Repos.IterAll() {
total += 1
if repo.GetCurrentBranchName() == repo.GetUserBranchName() {
count += 1
} else {
nope += 1
}
}
if total != count {
return total, count, nope, ErrorNotAllReposOnUser
}
return total, count, nope, nil
}
// trys to figure out if there is still something to update
func (f *Forge) DoAllCheckoutMaster() error {
now := time.Now()
f.RillFuncError(rillCheckoutMaster)
count := f.RillReload()
if count != 0 {
f.ConfigSave()
}
total, count, nope, err := f.IsEverythingOnMaster()
log.Printf("Master branch check. %d total repos. (%d ok) (%d not on master branch) (%s)\n", total, count, nope, shell.FormatDuration(time.Since(now)))
if err != nil {
// display all repos not on master
found := new(gitpb.Repos)
all := f.Repos.SortByFullPath()
for all.Scan() {
repo := all.Next()
if repo.GetCurrentBranchName() != repo.GetMasterBranchName() {
found.Append(repo)
}
}
f.PrintHumanTable(found)
log.Printf("There are %d repos that are NOT on the master branch\n", found.Len())
return err
}
return nil
}
func rillCheckoutMaster(repo *gitpb.Repo) error {
if repo.IsDirty() {
// never do dirty repos
return nil
}
// 'giterr' means something is very wrong with this repo
if repo.GetMasterVersion() == "giterr" {
repo.CheckoutMaster()
log.Info("master == giterr. BAD REPO", repo.GetFullPath())
log.Info("master == giterr. BAD REPO", repo.GetFullPath())
log.Info("master == giterr. BAD REPO", repo.GetFullPath())
cmd := []string{"git", "checkout", "main"} // todo: figure out main
repo.RunVerbose(cmd)
os.Exit(-1)
return nil
}
if repo.GetCurrentBranchName() == repo.GetMasterBranchName() {
// repo is already on master
return nil
}
repo.CheckoutMaster()
return nil
}
func rillCheckoutUser(repo *gitpb.Repo) error {
if repo.IsDirty() {
// never do dirty repos
return nil
}
if repo.GetCurrentBranchName() == repo.GetMasterBranchName() {
// repo is already on devel branch. have to move them there first for now
// return repo.CheckoutDevel()
}
if repo.GetCurrentBranchName() == repo.GetUserBranchName() {
// repo is already on user branch
return nil
}
if err := repo.CheckoutUser(); err != nil {
log.Info(repo.GetFullPath(), err)
return err
}
return nil
}
// trys to figure out if there is still something to update
func (f *Forge) DoAllCheckoutUser(force bool) error {
now := time.Now()
if force {
log.Info("going to force create user branches")
if err := f.makeUserBranches(); err != nil {
return err
}
}
f.RillFuncError(rillCheckoutUser)
count := f.RillReload()
if count != 0 {
f.ConfigSave()
}
total, count, nope, err := f.IsEverythingOnUser()
log.Printf("User branch check. %d total repos. (%d ok) (%d not on user branch) (%s)\n", total, count, nope, shell.FormatDuration(time.Since(now)))
if err != nil {
// display all repos not on user
found := new(gitpb.Repos)
all := f.Repos.SortByFullPath()
for all.Scan() {
repo := all.Next()
if repo.GetCurrentBranchName() != repo.GetUserBranchName() {
found.Append(repo)
}
}
f.PrintHumanTable(found)
log.Printf("There are %d repos that are NOT on the user branch\n", found.Len())
return err
}
return nil
}
func (f *Forge) makeUserBranches() error {
all := f.Repos.SortByFullPath()
for all.Scan() {
repo := all.Next()
branch := repo.GetUserBranchName()
if repo.Exists(filepath.Join(".git/refs/heads", branch)) {
continue
}
if repo.Exists(filepath.Join(".git/refs/remotes/origin", branch)) {
cmd := []string{"git", "checkout", branch}
repo.RunVerbose(cmd)
continue
}
cmd := []string{"git", "branch", branch}
repo.RunVerbose(cmd)
cmd = []string{"git", "checkout", branch}
repo.RunVerbose(cmd)
}
return nil
}
func testReload(repo *gitpb.Repo) error {
if !repo.DidRepoChange() {
return nil
}
repo.Reload()
return log.Errorf("repo changed")
}
func (f *Forge) DoAllCheckoutDevelNew(force bool) error {
f.makeDevelBranches()
// first run git checkout
stats := f.RillFuncError(rillCheckoutDevel)
for path, stat := range stats {
dur := stat.End.Sub(stat.Start)
if dur > 1*time.Second {
log.Infof("%s git checkout took a long time (%s)\n", path, shell.FormatDuration(dur))
}
if stat.Err == nil {
// there was no error
continue
}
// didn't change to devel
}
var counter int
// recreate the repo protobuf
stats = f.RillFuncError(testReload)
for path, stat := range stats {
dur := stat.End.Sub(stat.Start)
if dur > 1*time.Second {
log.Infof("%s # Reload took a long time (%s)\n", path, shell.FormatDuration(dur))
}
if stat.Err == nil {
// repo didn't reload
continue
}
// repo reloaded
counter += 1
}
log.Info("reloaded", counter, "repos")
f.configSave = true
return nil
}
// is every repo on the devel branch?
func (f *Forge) DoAllCheckoutDevel(force bool) error {
now := time.Now()
if force {
log.Info("going to force create devel branches")
f.makeDevelBranches()
}
log.Info("going to rill:")
f.RillFuncError(rillCheckoutDevel)
count := f.RillReload()
if count != 0 {
f.ConfigSave()
}
total, count, nope, err := f.IsEverythingOnDevel()
log.Printf("Devel branch check. %d total repos. (%d ok) (%d not on devel branch) (%s)\n", total, count, nope, shell.FormatDuration(time.Since(now)))
if err != nil {
// display all repos not on user
found := new(gitpb.Repos)
all := f.Repos.SortByFullPath()
for all.Scan() {
repo := all.Next()
if repo.GetCurrentBranchName() != repo.GetDevelBranchName() {
found.Append(repo)
}
}
f.PrintHumanTable(found)
log.Printf("There are %d repos that are NOT on the devel branch\n", found.Len())
return err
}
return nil
}
func (f *Forge) makeDevelBranches() error {
all := f.Repos.SortByFullPath()
for all.Scan() {
repo := all.Next()
branch := repo.GetDevelBranchName()
if repo.Exists(filepath.Join(".git/refs/heads", branch)) {
continue
}
if repo.Exists(filepath.Join(".git/refs/remotes/origin", branch)) {
cmd := []string{"git", "checkout", branch}
repo.RunVerbose(cmd)
continue
}
cmd := []string{"git", "branch", branch}
repo.RunVerbose(cmd)
cmd = []string{"git", "checkout", branch}
repo.RunVerbose(cmd)
}
return nil
}
func rillCheckoutDevel(repo *gitpb.Repo) error {
if repo.IsDirty() {
// never do dirty repos
return nil
}
if repo.GetCurrentBranchName() == repo.GetDevelBranchName() {
// repo is already on devel branch
return nil
}
repo.CheckoutDevel()
return nil
}