// Copyright 2017-2025 WIT.COM Inc. All rights reserved. // Use of this source code is governed by the GPL 3.0 package main import ( "fmt" "path/filepath" "go.wit.com/lib/protobuf/gitpb" "go.wit.com/log" ) 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 argv.Clean.Pub != nil { if err := doCleanPub(); err != nil { badExit(err) } log.Info("finished attempt at cleaning devel branches") return nil } 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 { 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 } var anyerr error all := me.forge.Repos.SortByFullPath() for all.Scan() { repo := all.Next() if err := doCleanUserRepo(repo); err != nil { log.Info(repo.GetGoPath(), err) anyerr = err } } return anyerr } /* func doesLocalBranchExist(repo *gitpb.Repo, branch string) bool { return repo.Exists(filepath.Join(".git/refs/heads", branch)) } */ func doCleanDevel() error { var total int var count int all := me.forge.Repos.SortByFullPath() for all.Scan() { repo := all.Next() total += 1 if !repo.IsLocalBranch(repo.GetDevelBranchName()) { // there is no local branch named 'devel' continue } if repo.GetCurrentBranchName() != repo.GetMasterBranchName() { log.Info("Repo not on master branch:", repo.GetGoPath()) continue } if repo.IsDirty() { log.Info("Repo is dirty:", repo.GetGoPath()) continue } count += 1 if err := justDeleteTheDevelBranchAlready(repo); err != nil { log.Info("justDeleteTheDevel() err", repo.GetGoPath(), err) } } log.Info("") log.Printf("attempted cleaning %d devel branches of %d total branches\n", count, total) return nil } // removes all local branches func doCleanUserRepo(repo *gitpb.Repo) error { if repo.IsDirty() { return nil } bruser := repo.GetUserBranchName() brdevel := repo.GetDevelBranchName() 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.IsLocalBranch(bruser) { // there is no local user branch return nil } log.Info("trying to delete", bruser, repo.GetUserVersion()) b1 := repo.CountDiffObjects(bruser, brdevel) // should be zero if b1 == 0 { cmd := []string{"git", "branch", "-D", bruser} log.Info("USER IS IN DEVEL", repo.GetGoPath(), cmd) err := repo.RunVerbose(cmd) return err } return fmt.Errorf("%s branch has things not in %s count=%d", bruser, brdevel, b1) } // hack to cleanup release versioning info func doCleanPub() error { total := 0 all := me.forge.Repos.SortByFullPath() for all.Scan() { repo := all.Next() if repo.GetTargetVersion() != "" { repo.SetTargetVersion("") configSave = true total += 1 } } log.Printf("clearing %d total repos\n", total) return nil } // if you call this, there is no going back. no checks anymore. nothing // it deletes the 'devel' branch. git branch -D "devel". END OF STORY 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 := 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) err := repo.RunVerbose(cmd) return err } cmd := []string{"git", "push"} log.Info("DEVEL LOCAL NEEDS GIT PUSH TO REMOTE", repo.GetGoPath(), cmd) err := repo.RunVerbose(cmd) return err } // remote doesn't exist, check against master master := repo.GetMasterBranchName() 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) err := repo.RunVerbose(cmd) return err } cmd := []string{"git", "merge something somehow"} log.Info("DEVEL LOCAL NEEDS GIT MERGE TO MASTER", repo.GetGoPath(), cmd, b1) // _, err := repo.RunVerbose(cmd) return nil }