diff --git a/doCheckout.go b/doCheckout.go index 06c36cf..fdd5edb 100644 --- a/doCheckout.go +++ b/doCheckout.go @@ -254,7 +254,7 @@ func doAllCheckoutMaster() error { // shared this with the GUI and the command line? func doCheckoutShared() error { if me.argvCheckoutUser { - log.Info("Starting git checkout user") + // log.Info("Starting git checkout user") if argv.Force { log.Info("going to force create user branches") if err := makeUserBranches(); err != nil { @@ -267,7 +267,7 @@ func doCheckoutShared() error { } if me.argvCheckoutDevel { - log.Info("Starting git checkout devel") + // log.Info("Starting git checkout devel") if argv.Force { log.Info("going to force create devel branches") makeDevelBranches() @@ -304,7 +304,7 @@ func doCheckout() error { if err := doCheckoutShared(); err != nil { badExit(err) } - okExit("git checkout done") + okExit("") return nil } diff --git a/doClean.go b/doClean.go index 2f7b901..015d007 100644 --- a/doClean.go +++ b/doClean.go @@ -6,7 +6,6 @@ package main import ( "fmt" "path/filepath" - "slices" "go.wit.com/lib/protobuf/gitpb" "go.wit.com/log" @@ -98,6 +97,7 @@ func doCleanDevel() error { return nil } +/* func exactDevelRepo(repo *gitpb.Repo) error { devel := repo.GetDevelBranchName() master := repo.GetMasterBranchName() @@ -107,6 +107,7 @@ func exactDevelRepo(repo *gitpb.Repo) error { } return nil } +*/ func checkhashes(repo *gitpb.Repo, hashes []string, refpath string) ([]string, error) { if !repo.Exists(refpath) { @@ -128,326 +129,36 @@ func checkhashes(repo *gitpb.Repo, hashes []string, refpath string) ([]string, e // removes all local branches func doCleanUserRepo(repo *gitpb.Repo) error { - var hasLocal bool - 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) - } - if argv.Clean.User != nil { - base := repo.GetUserBranchName() - if repo.Exists(filepath.Join(".git/refs/heads", base)) { - log.Info("Delete local branch:", base, repo.GetGoPath()) - err := forceDeleteUserBranch(repo, base) - repo.Reload() - if err != nil { - log.Info("Delete local branch ERROR:", err) - return err - } - // return fmt.Errorf("todo") - } + bruser := repo.GetUserBranchName() + brdevel := repo.GetDevelBranchName() + + if repo.GetUserVersion() == "uerr" { + // already deleted return nil } + log.Info("trying", bruser, repo.GetUserVersion()) - 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 - } - if name == repo.GetUserBranchName() { - hasLocal = true - if err := doCleanUserBranch(repo, b); err != nil { - log.Info("\tLOCAL BRANCH ERROR user =", name) - return err - } - log.Info("\tLOCAL BRANCH user =", name) - continue - } - if name == repo.GetDevelBranchName() { - continue - } - if name == repo.GetMasterBranchName() { - continue - } - if err := verifyLocalBranchIsMerged(repo, b); err != nil { - return err - } - } - if argv.Clean.Force == nil { - if hasLocal { - return ErrorReposHasLocalBranches - } - } - return nil -} - -func verifyLocalBranchIsMerged(repo *gitpb.Repo, branch *gitpb.GitBranch) error { - base := filepath.Base(branch.Name) - log.Info("local branch name unknown:", base, branch.Name, branch.Merge, branch.Remote, repo.GetGoPath()) - - // check if it exists in the origin - if repo.Exists(filepath.Join(".git/refs/remotes/origin", base)) { - err := fmt.Errorf("repo %s ERROR. branch is also remote %s", repo.GetGoPath(), branch.Name) - log.Info(err) - if err := isSafeToDelete(repo, base); err != nil { - log.Info(err) - return err - } - if err := requiresGitPush(repo, base); err != nil { - log.Info(err) - return err - } - err = fmt.Errorf("repo %s BRANCH AND REMOTE CAN BE DELETED %s", repo.GetGoPath(), branch.Name) - log.Info(err) - if argv.Clean.Force != nil { - err = BADforceDeleteBranch(repo, base) - repo.Reload() - } - return err + if repo.IsBranchRemote(bruser) { + log.Info("forge is designed to always have local only user branches", bruser) + return fmt.Errorf("forge is designed to always have local only user branches") } - if !repo.Exists(filepath.Join(".git/refs/heads", base)) { - log.Info("GitConfig() parse logic error. not really a local branch", base) - me.forge.Repos.Delete(repo) - configSave = true - return nil - } - - // this is only a local branch - if err := isSafeToDelete(repo, base); err != nil { - log.Info(err) - return err - } - err := fmt.Errorf("repo %s BRANCH CAN PROBABLY BE DELETED base=%s fullname=%s", repo.GetGoPath(), base, branch.Name) - log.Info(err) - if argv.Clean.Force != nil { - err = BADforceDeleteBranch(repo, base) - repo.Reload() - } - return err -} - -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 nil - } - - 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)}) - if err := userToDevelRequiresGitPush(repo, branch.Name); err != nil { - log.Info(err) - log.Info("THIS USER BRANCH MUST BE PUSHED TO DEVEL", branch.Name) - return err - } - log.Info("THIS USER BRANCH IS CLEAN TO DELETE", branch.Name) - if argv.Clean.Force != nil { - err := BADforceDeleteBranch(repo, branch.Name) - repo.Reload() - if err != nil { - return err - } - } - } 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.RunStrict([]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 { - log.Info(err) - log.Info("THIS USER BRANCH MUST BE PUSHED TO DEVEL", branch.Name) - 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} - if _, err := repo.RunStrict(cmd); err != nil { - log.Info("THE GIT BRANCH DELETE ERROR IS:", err) - return err - } - return nil - } - } - // 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() - missing := countDiffObjects(repo, branchName, "origin/"+devel) - b2 := countDiffObjects(repo, "origin/"+devel, branchName) - log.Info("user vs devel count", missing, b2) - if missing == 0 && b2 == 0 { - return nil - } - if missing != 0 { - log.Info("user vs devel count missing != 0, b2 ==", missing, b2) - log.Info("THIS MEANS THE LOCAL BRANCH NEEDS GIT PUSH TO ORIGIN BRANCH ==", missing) - // if argv.Examine.Fix != nil { - // return gitPushStrict(repo, branchName) - // } - return fmt.Errorf("user branch not clean to delete %d %d", missing, b2) - } - if missing == 0 { - // log.Info("THIS MEANS THE LOCAL BRANCH IS OK TO DELETE missing =", missing) - log.Info("THIS IS REALLY BAD RIGHT NOW. must to git push / git merge missing =", missing, b2) - } - return fmt.Errorf("user branch not clean to delete. maybe it is? devel might be ahead of user branch. %d %d", missing, b2) -} - -// checks against upstream master -func isSafeToDelete(repo *gitpb.Repo, old string) error { - var head string - head = filepath.Join("origin", repo.GetMasterBranchName()) - - if !repo.Exists(filepath.Join(".git/refs/remotes/", head)) { - head = filepath.Join("origin", "HEAD") - } - - b1 := countDiffObjects(repo, old, head) - b2 := countDiffObjects(repo, head, old) - log.Info(old, "vs origin count", b1, b2) - if b1 == 0 && b2 == 0 { - log.Info("isSafeToDelete() SAFE TO DELETE ==", old, b1, head, b2) - return nil - } + b1 := repo.CountDiffObjects(bruser, brdevel) // should be zero if b1 == 0 { - log.Info("isSafeToDelete() SAFE TO DELETE ==", old, b1, head, b2) - return nil - } - if b1 != 0 { - log.Info(old, "vs", head, " count b1 != 0, b2 ==", b2, "b1 =", b1) - log.Info("THIS MEANS THE LOCAL BRANCH NEEDS GIT PUSH TO ORIGIN BRANCH ==", b1) - cmd := repo.ConstructGitDiffLog(old, head) - log.Info("cmd", cmd) - cmd = repo.ConstructGitDiffLog(head, old) - log.Info("cmd", cmd) - if argv.Clean.Force != nil { - // return gitPushStrict(repo, branchName) - } - return fmt.Errorf("user branch not clean to delete. needs git push %d %d", b1, b2) - } - return fmt.Errorf("user branch not clean to delete. needs git push %d %d", b1, b2) -} - -// literally ignore all errors. delete everthing with no checks for now -func forceDeleteUserBranch(repo *gitpb.Repo, branch string) error { - if repo.IsDirty() { - log.Info(repo.GetGoPath(), "is dirty") - return nil - } - if repo.GetUserBranchName() != branch { - log.Info(repo.GetGoPath(), branch, "is not the user branch", repo.GetUserBranchName()) - return nil - } - if err := isSafeToDelete(repo, branch); err != nil { - log.Info(err) + cmd := []string{"git", "branch", "-D", bruser} + log.Info("USER IS IN DEVEL", repo.GetGoPath(), cmd) + err := repo.RunVerbose(cmd) return err } - if repo.Exists(filepath.Join(".git/refs/remotes/origin/", branch)) { - if err := requiresGitPush(repo, branch); err != nil { - log.Info(err) - return err - } - } - configSave = true - cmd := []string{"git", "branch", "-D", branch} - if err := repo.RunVerbose(cmd); err != nil { - log.Info("THE GIT BRANCH DELETE ERROR IS:", err) - // return err - } - log.Info("THIS USER REMOTE BRANCH MUST BE DELETED HERE", branch) - if repo.Exists(filepath.Join(".git/refs/remote/origin", branch)) { - cmd = []string{"git", "push", "origin", "--delete", branch} - if err := repo.RunVerbose(cmd); err != nil { - log.Info("THE GIT BRANCH DELETE ERROR IS:", err) - // return err - } - } - cmd = []string{"git", "branch", "-D", "--remote", "origin/" + branch} - if err := repo.RunVerbose(cmd); err != nil { - log.Info("THE GIT BRANCH DELETE ERROR IS:", err) - // return err - } - // return fmt.Errorf("one at a time %s", repo.GetGoPath()) - return nil -} - -// literally ignore all errors. delete everthing with no checks for now -func BADforceDeleteBranch(repo *gitpb.Repo, branch string) error { - if repo.IsDirty() { - log.Info(repo.GetGoPath(), "is dirty") - return nil - } - configSave = true - - cmd := []string{"git", "branch", "-D", branch} - if err := repo.RunVerbose(cmd); err != nil { - log.Info("THE GIT BRANCH DELETE ERROR IS:", err) - // return err - } - log.Info("THIS USER REMOTE BRANCH MUST BE DELETED HERE", branch) - if repo.Exists(filepath.Join(".git/refs/remote/origin", branch)) { - cmd = []string{"git", "push", "origin", "--delete", branch} - if err := repo.RunVerbose(cmd); err != nil { - log.Info("THE GIT BRANCH DELETE ERROR IS:", err) - // return err - } - } - cmd = []string{"git", "branch", "-D", "--remote", "origin/" + branch} - if err := repo.RunVerbose(cmd); err != nil { - log.Info("THE GIT BRANCH DELETE ERROR IS:", err) - // return err - } - // return fmt.Errorf("one at a time %s", repo.GetGoPath()) - return nil + return fmt.Errorf("%s branch has things not in %s count=%d", bruser, brdevel, b1) } +/* // 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. @@ -473,9 +184,12 @@ func isBranchSubsetOfTrunk(repo *gitpb.Repo, branch string, trunk string) error } 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.RunStrict(cmd) @@ -485,6 +199,7 @@ func countGitDiffLog(repo *gitpb.Repo, branch1, branch2 string) int { // log.Info("countDiffObjects()", cmd, len(r.Stdout), strings.Join(r.Stdout, " ")) return len(r.Stdout) } +*/ func doCleanPub() error { total := 0 @@ -507,9 +222,16 @@ func justDeleteTheDevelBranchAlready(repo *gitpb.Repo) error { branch := repo.GetDevelBranchName() remote := filepath.Join("origin", branch) + if me.forge.Config.IsReadOnly(repo.GetGoPath()) { + if repo.IsDevelRemote() { + // just make sure the remote & local branches are the same + return repo.DeleteLocalDevelBranch() + } + } + // check against remote if it exists if repo.IsDevelRemote() { - b1 := countGitDiffLog(repo, branch, remote) // should be zero + b1 := repo.CountDiffObjects(branch, remote) // should be zero if b1 == 0 { cmd := []string{"git", "branch", "-D", repo.GetDevelBranchName()} log.Info("DEVEL IS IN REMOTE", repo.GetGoPath(), cmd) @@ -524,7 +246,7 @@ func justDeleteTheDevelBranchAlready(repo *gitpb.Repo) error { // remote doesn't exist, check against master master := repo.GetMasterBranchName() - b1 := countGitDiffLog(repo, branch, master) // should be zero + b1 := repo.CountDiffObjects(branch, master) // should be zero if b1 == 0 { cmd := []string{"git", "branch", "-D", repo.GetDevelBranchName()} log.Info("DEVEL IS IN REMOTE", repo.GetGoPath(), cmd) @@ -532,7 +254,7 @@ func justDeleteTheDevelBranchAlready(repo *gitpb.Repo) error { return err } cmd := []string{"git", "merge something somehow"} - log.Info("DEVEL LOCAL NEEDS GIT MERGE TO MASTER", repo.GetGoPath(), cmd) + log.Info("DEVEL LOCAL NEEDS GIT MERGE TO MASTER", repo.GetGoPath(), cmd, b1) // _, err := repo.RunVerbose(cmd) return nil } diff --git a/doCommit.go b/doCommit.go index c7c854a..e7ed01c 100644 --- a/doCommit.go +++ b/doCommit.go @@ -17,6 +17,7 @@ func doCommit() { log.Info("todo: forge doesn't know how to work here yet") okExit("") } + if repo.GetCurrentBranchName() != repo.GetUserBranchName() { me.found.Append(repo) me.forge.PrintHumanTable(me.found) @@ -25,15 +26,18 @@ func doCommit() { log.Info("") okExit("") } + os.Setenv("LESS", "-XR") if err := shell.Exec([]string{"git", "diff"}); err != nil { badExit(err) } + if argv.All { if err := shell.ExecCheck([]string{"git", "add", "--all"}); err != nil { badExit(err) } } + if err := shell.ExecCheck([]string{"git", "commit", "--all"}); err != nil { badExit(err) } diff --git a/doPull.go b/doPull.go index edf3adf..000728a 100644 --- a/doPull.go +++ b/doPull.go @@ -44,14 +44,14 @@ func rillPull(repo *gitpb.Repo) error { func doGitPullNew() { now := time.Now() - me.forge.RillFuncError(rillPull) + pullcount := me.forge.RillFuncError(rillPull) count := me.forge.RillReload() if count != 0 { me.forge.ConfigSave() } total, count, nope, _ := IsEverythingOnMaster() - log.Printf("Master branch check. %d total repos. (%d git pulled) (%d not on master branch) (%s)\n", total, count, nope, shell.FormatDuration(time.Since(now))) + log.Printf("Master branch check. %d total repos. (%d git pulled) (%d not on master branch) (%s) git pull total=%d\n", total, count, nope, shell.FormatDuration(time.Since(now)), pullcount) } /*