package main import ( "fmt" "os" "path/filepath" "slices" "go.wit.com/lib/protobuf/gitpb" "go.wit.com/log" ) var ErrorReposHasLocalBranches error = fmt.Errorf("repo still has local branches") func doClean() error { if err := IsEverythingOnMaster(); err != nil { log.Info("Not all repos are on the master branch") // return err } all := me.forge.Repos.SortByFullPath() for all.Scan() { repo := all.Next() if repo.GetCurrentBranchName() != repo.GetMasterBranchName() { // skip this while in devel // continue } if err := doCleanRepo(repo); err != nil { badRepoExit(repo, err) } } log.Info("All repos on the master branch are clean") return nil } // removes all local branches func doCleanRepo(repo *gitpb.Repo) error { var hasLocal bool if argv.Verbose { log.Info("Cleaning:", repo.GetGoPath()) } if repo.GitConfig == nil { return fmt.Errorf("GitConfig == nil") } for _, l := range repo.GitConfig.Local { log.Info("\tlocal branch name:", l.Name) } for name, b := range repo.GitConfig.Branches { if b.Name == "" { b.Name = name } if name == repo.GetMasterBranchName() { // never delete the master branch // todo: make sure the master branch is in sync with remote master continue } hasLocal = true if name == repo.GetUserBranchName() { if err := doCleanUserBranch(repo, b); err != nil { return err } continue } if name == repo.GetDevelBranchName() { if err := doCleanDevelBranch(repo, b); err != nil { return err } continue } log.Info("\tlocal branch name unknown:", name, b.Merge, b.Remote) } if hasLocal { return ErrorReposHasLocalBranches } return nil } func verifyLocalBranchIsMerged(repo *gitpb.Repo, branch *gitpb.GitBranch) error { return nil } func doCleanDevelBranch(repo *gitpb.Repo, branch *gitpb.GitBranch) error { log.Printf("\tDo something %s on branch name:%s merge:%s remote:%s\n", repo.GetGoPath(), branch.Name, branch.Merge, branch.Remote) return nil } func doCleanUserBranch(repo *gitpb.Repo, branch *gitpb.GitBranch) error { if branch.Name != repo.GetUserBranchName() { return fmt.Errorf("repo %s was not user branch %s", repo.GetGoPath(), branch.Name) } /* if bran == repo.GetUserBranchName() { log.Info("The user branch also has a remote branch", repo.CurrentTag.Refname) log.Info("TODO: verify the remote branch is out of date", repo.CurrentTag.Refname) log.Info("TODO: delete the remote branch", repo.CurrentTag.Refname) return nil } */ if !repo.Exists(filepath.Join(".git/refs/heads", branch.Name)) { err := fmt.Errorf("BAD FORGE LOGIC. DELETE REPO %s", repo.GetGoPath()) log.Warn(err) me.forge.Repos.Repos = slices.DeleteFunc(me.forge.Repos.Repos, func(r *gitpb.Repo) bool { if repo.GetGoPath() == r.GetGoPath() { return true } return false }) // me.forge.Repos.Delete(repo) me.forge.ConfigSave() os.Exit(0) return err } if repo.Exists(filepath.Join(".git/refs/remotes/origin", branch.Name)) { log.Info("why is this non-localonly branch a problem?", branch.Name) repo.RunVerbose([]string{"ls", "-l", ".git/refs/remotes/origin"}) repo.RunVerbose([]string{"cat", filepath.Join(".git/refs/remotes/origin", branch.Name)}) repo.RunVerbose([]string{"cat", filepath.Join(".git/refs/heads", branch.Name)}) } else { log.Info("why is this local only branch a problem?", branch.Name) repo.RunVerbose([]string{"ls", "-l", ".git/refs/remotes/origin"}) r, err := repo.RunVerbose([]string{"cat", filepath.Join(".git/refs/heads", branch.Name)}) if err == nil { cmd := []string{"git", "show", "-s", "--format=\"%H %ae %as %s\"", r.Stdout[0]} repo.RunVerbose(cmd) log.Info(cmd) } if err := userToDevelRequiresGitPush(repo, branch.Name); err != nil { return err } log.Info("THIS USER BRANCH IS CLEAN TO DELETE", branch.Name) if argv.Clean.Force != nil { cmd := []string{"git", "branch", "-D", branch.Name} _, err := repo.RunVerbose(cmd) return err } } // return fmt.Errorf("%s repo.CurrentTag is not local: %s. Don't proceed yet", repo.GetGoPath(), repo.CurrentTag.Refname) log.Printf("Do something %s on branch name:%s merge:%s remote:%s\n", repo.GetGoPath(), branch.Name, branch.Merge, branch.Remote) return nil } func userToDevelRequiresGitPush(repo *gitpb.Repo, branchName string) error { devel := repo.GetDevelBranchName() b1 := countDiffObjects(repo, branchName, "origin/"+devel) b2 := countDiffObjects(repo, "origin/"+devel, branchName) log.Info("user vs devel count", b1, b2) if b1 == 0 && b2 == 0 { return nil } if b1 != 0 { log.Info("user vs devel count b1 != 0, b2 ==", b1, b2) log.Info("THIS MEANS THE LOCAL BRANCH NEEDS GIT PUSH TO ORIGIN BRANCH ==", b1) // if argv.Examine.Fix != nil { // return gitPushStrict(repo, branchName) // } return fmt.Errorf("user branch not clean to delete %d %d", b1, b2) } return fmt.Errorf("user branch not clean to delete. maybe it is? devel might be ahead of user branch. %d %d", b1, b2) }