check devel branches
This commit is contained in:
parent
4c38b052fd
commit
835c000aef
9
argv.go
9
argv.go
|
@ -45,8 +45,13 @@ type ExamineCmd struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type CleanCmd struct {
|
type CleanCmd struct {
|
||||||
Force *EmptyCmd `arg:"subcommand:force" help:"dangerously delete things that are not pushed upstream"`
|
Force *EmptyCmd `arg:"subcommand:force" help:"dangerously delete things that are not pushed upstream"`
|
||||||
User *EmptyCmd `arg:"subcommand:user" help:"dump all the user branches"`
|
User *EmptyCmd `arg:"subcommand:user" help:"clean the user branches"`
|
||||||
|
Devel *CleanDevelCmd `arg:"subcommand:devel" help:"clean and verify the devel branches"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type CleanDevelCmd struct {
|
||||||
|
Force bool `arg:"--force" help:"try to strong arm things"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type PatchCmd struct {
|
type PatchCmd struct {
|
||||||
|
|
|
@ -24,7 +24,7 @@ func (args) doBashAuto() {
|
||||||
usr, _ := user.Current()
|
usr, _ := user.Current()
|
||||||
fmt.Println("user devel master " + usr.Username)
|
fmt.Println("user devel master " + usr.Username)
|
||||||
case "clean":
|
case "clean":
|
||||||
fmt.Println("force user")
|
fmt.Println("devel user force")
|
||||||
case "commit":
|
case "commit":
|
||||||
fmt.Println("--all")
|
fmt.Println("--all")
|
||||||
case "config":
|
case "config":
|
||||||
|
|
|
@ -11,7 +11,7 @@ var ErrorNotAllReposOnMaster error = fmt.Errorf("not all repos on are on the mas
|
||||||
var ErrorNotAllReposOnDevel error = fmt.Errorf("not all repos on are on the devel branch")
|
var ErrorNotAllReposOnDevel error = fmt.Errorf("not all repos on are on the devel branch")
|
||||||
var ErrorNotAllReposOnUser error = fmt.Errorf("not all repos on are on the user branch")
|
var ErrorNotAllReposOnUser error = fmt.Errorf("not all repos on are on the user branch")
|
||||||
|
|
||||||
func IsEverythingOnMaster() error {
|
func IsEverythingOnMaster() (int, int, error) {
|
||||||
var total int
|
var total int
|
||||||
var count int
|
var count int
|
||||||
var nope int
|
var nope int
|
||||||
|
@ -30,12 +30,12 @@ func IsEverythingOnMaster() error {
|
||||||
log.Printf("Master branch check. %d total repos. (%d ok) (%d not on master branch)\n", total, count, nope)
|
log.Printf("Master branch check. %d total repos. (%d ok) (%d not on master branch)\n", total, count, nope)
|
||||||
if total != count {
|
if total != count {
|
||||||
// log.Info(ErrorNotAllReposOnMaster)
|
// log.Info(ErrorNotAllReposOnMaster)
|
||||||
return ErrorNotAllReposOnMaster
|
return total, count, ErrorNotAllReposOnMaster
|
||||||
}
|
}
|
||||||
return nil
|
return total, count, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func IsEverythingOnDevel() error {
|
func IsEverythingOnDevel() (int, int, error) {
|
||||||
var total int
|
var total int
|
||||||
var count int
|
var count int
|
||||||
|
|
||||||
|
@ -50,12 +50,12 @@ func IsEverythingOnDevel() error {
|
||||||
}
|
}
|
||||||
log.Printf("Devel branch check. %d total repos. %d repos on the devel branch\n", total, count)
|
log.Printf("Devel branch check. %d total repos. %d repos on the devel branch\n", total, count)
|
||||||
if total != count {
|
if total != count {
|
||||||
return ErrorNotAllReposOnDevel
|
return total, count, ErrorNotAllReposOnDevel
|
||||||
}
|
}
|
||||||
return nil
|
return total, count, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func IsEverythingOnUser() error {
|
func IsEverythingOnUser() (int, int, error) {
|
||||||
var total int
|
var total int
|
||||||
var count int
|
var count int
|
||||||
|
|
||||||
|
@ -70,9 +70,9 @@ func IsEverythingOnUser() error {
|
||||||
}
|
}
|
||||||
log.Printf("User branch check. %d total repos. %d repos on the user branch\n", total, count)
|
log.Printf("User branch check. %d total repos. %d repos on the user branch\n", total, count)
|
||||||
if total != count {
|
if total != count {
|
||||||
return ErrorNotAllReposOnUser
|
return total, count, ErrorNotAllReposOnUser
|
||||||
}
|
}
|
||||||
return nil
|
return total, count, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func doGitReset() {
|
func doGitReset() {
|
||||||
|
@ -113,7 +113,7 @@ func doAllCheckoutUser() error {
|
||||||
if count != 0 {
|
if count != 0 {
|
||||||
me.forge.ConfigSave()
|
me.forge.ConfigSave()
|
||||||
}
|
}
|
||||||
if err := IsEverythingOnUser(); err != nil {
|
if _, _, err := IsEverythingOnUser(); err != nil {
|
||||||
// display all repos not on user
|
// display all repos not on user
|
||||||
me.found = new(gitpb.Repos)
|
me.found = new(gitpb.Repos)
|
||||||
all := me.forge.Repos.SortByFullPath()
|
all := me.forge.Repos.SortByFullPath()
|
||||||
|
@ -149,7 +149,7 @@ func doAllCheckoutDevel() error {
|
||||||
if count != 0 {
|
if count != 0 {
|
||||||
me.forge.ConfigSave()
|
me.forge.ConfigSave()
|
||||||
}
|
}
|
||||||
if err := IsEverythingOnDevel(); err != nil {
|
if _, _, err := IsEverythingOnDevel(); err != nil {
|
||||||
// display all repos not on user
|
// display all repos not on user
|
||||||
me.found = new(gitpb.Repos)
|
me.found = new(gitpb.Repos)
|
||||||
all := me.forge.Repos.SortByFullPath()
|
all := me.forge.Repos.SortByFullPath()
|
||||||
|
@ -206,7 +206,7 @@ func doAllCheckoutMaster() error {
|
||||||
me.forge.ConfigSave()
|
me.forge.ConfigSave()
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := IsEverythingOnMaster(); err != nil {
|
if _, _, err := IsEverythingOnMaster(); err != nil {
|
||||||
// display all repos not on master
|
// display all repos not on master
|
||||||
me.found = new(gitpb.Repos)
|
me.found = new(gitpb.Repos)
|
||||||
all := me.forge.Repos.SortByFullPath()
|
all := me.forge.Repos.SortByFullPath()
|
||||||
|
|
170
doClean.go
170
doClean.go
|
@ -10,41 +10,129 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
var ErrorReposHasLocalBranches error = fmt.Errorf("repo still has local branches")
|
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 {
|
func doClean() error {
|
||||||
if err := IsEverythingOnMaster(); err != nil {
|
if argv.Clean.Devel != nil {
|
||||||
log.Info("Not all repos are on the master branch")
|
if err := doCleanDevel(); err != nil {
|
||||||
// return err
|
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()
|
all := me.forge.Repos.SortByFullPath()
|
||||||
for all.Scan() {
|
for all.Scan() {
|
||||||
repo := all.Next()
|
repo := all.Next()
|
||||||
if repo.GetCurrentBranchName() != repo.GetMasterBranchName() {
|
if _, count, err := IsEverythingOnMaster(); err != nil {
|
||||||
// skip this while in devel
|
if count == 0 {
|
||||||
continue
|
log.Info("No repos are on the master branch")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
log.Info("Not all repos are on the master branch")
|
||||||
|
// return err
|
||||||
}
|
}
|
||||||
if repo.IsDirty() {
|
|
||||||
continue
|
if err := doCleanUserRepo(repo); err != nil {
|
||||||
}
|
|
||||||
if err := doCleanRepo(repo); err != nil {
|
|
||||||
log.Info(repo.GetGoPath(), err)
|
log.Info(repo.GetGoPath(), err)
|
||||||
okExit("")
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
log.Info("All repos on the master branch are clean")
|
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() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
count += 1
|
||||||
|
if err := doCleanDevelRepo(repo); err != nil {
|
||||||
|
log.Info(repo.GetGoPath(), err)
|
||||||
|
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())
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// removes all local branches
|
// removes all local branches
|
||||||
func doCleanRepo(repo *gitpb.Repo) error {
|
func doCleanUserRepo(repo *gitpb.Repo) error {
|
||||||
var hasLocal bool
|
var hasLocal bool
|
||||||
if argv.Verbose {
|
|
||||||
log.Info("Cleaning:", repo.GetGoPath())
|
|
||||||
}
|
|
||||||
if repo.GitConfig == nil {
|
if repo.GitConfig == nil {
|
||||||
return fmt.Errorf("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 {
|
for _, l := range repo.GitConfig.Local {
|
||||||
log.Info("\tlocal branch name:", l.Name)
|
log.Info("\tlocal branch name:", l.Name)
|
||||||
|
@ -83,13 +171,9 @@ func doCleanRepo(repo *gitpb.Repo) error {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if name == repo.GetDevelBranchName() {
|
if name == repo.GetDevelBranchName() {
|
||||||
/*
|
continue
|
||||||
if err := doCleanDevelBranch(repo, b); err != nil {
|
}
|
||||||
log.Info("\tLOCAL BRANCH ERROR devel")
|
if name == repo.GetMasterBranchName() {
|
||||||
return err
|
|
||||||
}
|
|
||||||
log.Info("\tLOCAL BRANCH devel")
|
|
||||||
*/
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if err := verifyLocalBranchIsMerged(repo, b); err != nil {
|
if err := verifyLocalBranchIsMerged(repo, b); err != nil {
|
||||||
|
@ -150,11 +234,6 @@ func verifyLocalBranchIsMerged(repo *gitpb.Repo, branch *gitpb.GitBranch) error
|
||||||
return err
|
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 {
|
func doCleanUserBranch(repo *gitpb.Repo, branch *gitpb.GitBranch) error {
|
||||||
if branch.Name != repo.GetUserBranchName() {
|
if branch.Name != repo.GetUserBranchName() {
|
||||||
return fmt.Errorf("repo %s was not user branch %s", repo.GetGoPath(), branch.Name)
|
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 fmt.Errorf("one at a time %s", repo.GetGoPath())
|
||||||
return nil
|
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)
|
||||||
|
}
|
||||||
|
|
20
doPull.go
20
doPull.go
|
@ -29,3 +29,23 @@ func doGitPull() {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// git fetch origin master:master
|
||||||
|
func rillFetchMaster(repo *gitpb.Repo) error {
|
||||||
|
if repo.GetCurrentBranchName() != repo.GetUserBranchName() {
|
||||||
|
// only fetch when branch is on the user branch
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
branch := repo.GetMasterBranchName()
|
||||||
|
cmd := []string{"git", "fetch", "origin", branch + ":" + branch}
|
||||||
|
_, err := repo.RunVerbose(cmd)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func doGitFetch() {
|
||||||
|
me.forge.RillFuncError(rillFetchMaster)
|
||||||
|
count := me.forge.RillReload()
|
||||||
|
if count != 0 {
|
||||||
|
me.forge.ConfigSave()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
4
main.go
4
main.go
|
@ -136,8 +136,8 @@ func main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if argv.GitPull != nil {
|
if argv.GitPull != nil {
|
||||||
argv.GitPull.findRepos()
|
// argv.GitPull.findRepos()
|
||||||
doGitPull()
|
doGitFetch()
|
||||||
okExit("")
|
okExit("")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -104,7 +104,7 @@ func submitPatchesBox(box *gui.Node) *patchSummary {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if err := IsEverythingOnDevel(); err != nil {
|
if _, _, err := IsEverythingOnDevel(); err != nil {
|
||||||
log.Info("You can only apply patches to the devel branch")
|
log.Info("You can only apply patches to the devel branch")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue