diff options
Diffstat (limited to 'doClean.go')
| -rw-r--r-- | doClean.go | 166 |
1 files changed, 140 insertions, 26 deletions
@@ -10,41 +10,129 @@ import ( ) var ErrorReposHasLocalBranches error = fmt.Errorf("repo still has local branches") +var ErrorMergeBranch error = fmt.Errorf("trunk has things not in the branch") +var ErrorMergeTrunk error = fmt.Errorf("branch has things not in trunk") func doClean() error { - if err := IsEverythingOnMaster(); err != nil { - log.Info("Not all repos are on the master branch") - // return err + if argv.Clean.Devel != nil { + if err := doCleanDevel(); err != nil { + badExit(err) + } + log.Info("finished attempt at cleaning devel branches") + return nil + } + if argv.Clean.User != nil { + if err := doCleanUser(); err != nil { + log.Info(err) + okExit("") + } + return nil } + return nil +} +func doCleanUser() error { all := me.forge.Repos.SortByFullPath() for all.Scan() { repo := all.Next() - if repo.GetCurrentBranchName() != repo.GetMasterBranchName() { - // skip this while in devel - continue + if _, count, err := IsEverythingOnMaster(); err != nil { + if count == 0 { + log.Info("No repos are on the master branch") + return nil + } + log.Info("Not all repos are on the master branch") + // return err + } + + if err := doCleanUserRepo(repo); err != nil { + log.Info(repo.GetGoPath(), err) + return err + } + } + return nil +} + +func doCleanDevel() error { + var total int + var count int + all := me.forge.Repos.SortByFullPath() + for all.Scan() { + repo := all.Next() + if argv.Verbose { + log.Info("Cleaning:", repo.GetGoPath()) + } + total += 1 + if repo.GetCurrentBranchName() != repo.GetDevelBranchName() { + // only process branches in devel + // return nil } if repo.IsDirty() { - continue + return nil } - if err := doCleanRepo(repo); err != nil { + count += 1 + if err := doCleanDevelRepo(repo); err != nil { log.Info(repo.GetGoPath(), err) - okExit("") + return err + } + } + log.Printf("attempted cleaning %d branches of %d total branches\n", count, total) + return nil +} + +func doCleanDevelRepo(repo *gitpb.Repo) error { + devel := repo.GetDevelBranchName() + // log.Printf("%s Start verify devel branch: %s\n", repo.GetGoPath(), devel) + + // check if devel branch exists in remote repo + if repo.Exists(filepath.Join(".git/refs/remotes/origin", devel)) { + remote := filepath.Join("origin", devel) + if err := isBranchSubsetOfTrunk(repo, devel, remote); err != nil { + if err == ErrorMergeBranch { + log.Info("can not do this yet. need push to upstream", repo.GetGoPath()) + return nil + } + return err } + // log.Info("todo: verify against remote devel branch", repo.GetGoPath()) } - log.Info("All repos on the master branch are clean") + + // verify devel branch is subset of master branch + master := repo.GetMasterBranchName() + if err := isBranchSubsetOfTrunk(repo, devel, master); err != nil { + if err == ErrorMergeBranch { + if argv.Force { + if repo.GetCurrentBranchName() == devel { + cmd := []string{"git", "merge", master} + // only run this if branch is local + _, err := repo.RunVerbose(cmd) + return err + } else { + cmd := []string{"git", "merge", master} + log.Info("can't run. on wrong branch.", cmd, repo.GetGoPath(), "current branch =", repo.GetCurrentBranchName()) + } + } + return nil + } + return err + } + // log.Info("todo: verify against remote devel branch", repo.GetGoPath()) + return nil } // removes all local branches -func doCleanRepo(repo *gitpb.Repo) error { +func doCleanUserRepo(repo *gitpb.Repo) error { var hasLocal bool - if argv.Verbose { - log.Info("Cleaning:", repo.GetGoPath()) - } if repo.GitConfig == nil { return fmt.Errorf("GitConfig == nil") } + if repo.GetCurrentBranchName() != repo.GetMasterBranchName() { + // skip this while in devel + return nil + } + if repo.IsDirty() { + return nil + } for _, l := range repo.GitConfig.Local { log.Info("\tlocal branch name:", l.Name) @@ -83,13 +171,9 @@ func doCleanRepo(repo *gitpb.Repo) error { continue } if name == repo.GetDevelBranchName() { - /* - if err := doCleanDevelBranch(repo, b); err != nil { - log.Info("\tLOCAL BRANCH ERROR devel") - return err - } - log.Info("\tLOCAL BRANCH devel") - */ + continue + } + if name == repo.GetMasterBranchName() { continue } if err := verifyLocalBranchIsMerged(repo, b); err != nil { @@ -150,11 +234,6 @@ func verifyLocalBranchIsMerged(repo *gitpb.Repo, branch *gitpb.GitBranch) error return err } -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) @@ -364,3 +443,38 @@ func BADforceDeleteBranch(repo *gitpb.Repo, branch string) error { // return fmt.Errorf("one at a time %s", repo.GetGoPath()) return nil } + +// verifies that the branch is a pure subset of the other branch +// sorry about the 'master' 'slave' nameing thing. I guess that isn't +// 'cool' to use anymore. I can't think of other terms that aren't reserved words. +func isBranchSubsetOfTrunk(repo *gitpb.Repo, branch string, trunk string) error { + b1 := countGitDiffLog(repo, branch, trunk) // should be zero + b2 := countGitDiffLog(repo, trunk, branch) // can be greater than 1 + // log.Info(branch, "vs", trunk, "count", b1, b2) + if b1 == 0 && b2 == 0 { + // log.Info("branch and trunk are identical ==", branch, b1, trunk, b2) + return nil + } + if b1 == 0 { + cmd := []string{"git", "merge", trunk} + log.Printf("%-40s branch %s needs merge with trunk %s len(%d) %s\n", repo.GetGoPath(), branch, trunk, b2, cmd) + return ErrorMergeBranch + } + if b2 == 0 { + log.Printf("%-40s trunk %s needs merge with branch %s len(%d)\n", repo.GetGoPath(), branch, trunk, b2) + return ErrorMergeTrunk + } + return fmt.Errorf("branch not clean to delete. needs merge %d %d", b1, b2) +} + +// count all objects only in branch1 +// if zero, that means branch1 is entirely contained in branch2 and can be safely deleted +func countGitDiffLog(repo *gitpb.Repo, branch1, branch2 string) int { + cmd := repo.ConstructGitDiffLog(branch1, branch2) + r, err := repo.RunStrictNew(cmd) + if err != nil { + return -1 + } + // log.Info("countDiffObjects()", cmd, len(r.Stdout), strings.Join(r.Stdout, " ")) + return len(r.Stdout) +} |
