package main import ( "errors" "os" "strings" "go.wit.com/dev/alexflint/arg" "go.wit.com/lib/protobuf/forgepb" "go.wit.com/lib/protobuf/gitpb" "go.wit.com/log" ) // sent via -ldflags var VERSION string var BUILDTIME string var pp *arg.Parser var forge *forgepb.Forge // var check *gitpb.Repo var configSave bool func main() { var check *gitpb.Repo log.Info("go-mod-clean version", VERSION, "built on", BUILDTIME) pp = arg.MustParse(&argv) // load the ~/.config/forge/ config // this lets you configure repos you have read/write access too forge = forgepb.Init() if argv.All { // run this on every single repo // do this before publishing new golang versions all := forge.Repos.SortByGoPath() for all.Scan() { check = all.Next() if err := doMain(check); err != nil { badExit(check, err) } } } else { // figure out what directory we are running in check = findPwdRepo() if check == nil { log.Info("this directory isn't in a golang project (not in ~/go/src nor a go.work file)") os.Exit(-1) } if err := doMain(check); err != nil { badExit(check, err) } } if configSave { forge.ConfigSave() } log.Info("forge.FinalGoDepsCheck() worked :", check.GoPath) okExit(check, "go.sum seems clean") } func findPwdRepo() *gitpb.Repo { var check *gitpb.Repo // attempt to use the working directory // this is probably what happens most of the time pwd, _ := os.Getwd() if strings.HasPrefix(pwd, forge.GetGoSrc()) { gopath := strings.TrimPrefix(pwd, forge.GetGoSrc()) gopath = strings.Trim(gopath, "/") log.Info("findRepo() trying gopath", gopath) check = forge.Repos.FindByGoPath(gopath) if check != nil { log.Info("findRepo() worked", check.GoPath) return check } } return nil } func saveAsMetadata(repo *gitpb.Repo) error { cname := repo.GetCurrentBranchName() if repo.GoPrimitive { if err := repo.AutogenSave([]string{"go.mod"}, cname, true); err != nil { return err } } else { if err := repo.AutogenSave([]string{"go.mod", "go.sum"}, cname, true); err != nil { return err } } return nil } func doMain(repo *gitpb.Repo) error { if !repo.IsValid() { log.Info(repo.GoPath, "is invalid. fix your repos.pb file with 'forge' first") log.Info("") log.Info("go install go.wit.com/apps/forge@latest") log.Info("") return errors.New(repo.GoPath + " is invalid. fix your repository list with 'forge' first") } else { log.Info(repo.GoPath, "is valid according to forge") } // skip restore if --force if !argv.Force { // erase the go.mod and go.sum files eraseGoMod(repo) cname := repo.GetCurrentBranchName() // try to restore from the git metadata if err := repo.AutogenRestore(cname); err != nil { // ignore errors here } if err := repo.ValidGoSum(); err == nil { log.Info(repo.GoPath, "go.mod and go.sum were restored ok") configSave = true return nil } } // double check here. use --force to remake them if err := repo.ValidGoSum(); err == nil { log.Info(repo.GoPath, "go.mod and go.sum are already valid") return nil } if repo.GetMasterBranchName() != repo.GetCurrentBranchName() { log.Info("") log.Info("You can only run go-mod-clean on a git master branch.") log.Info("Publishing go.mod & go.sum files must come from from git version tag") log.Info("Anything else doesn't make sense.") log.Info("") return errors.New(repo.GoPath + " not in the git master branch") } ok, err := repoIgnoresGoMod(repo) if err != nil { log.Info(repo.GoPath, "some wierd git error happened. investigate.", err) return err } // if ok, then git owns 'go.mod' and we can't really do anything // todo: ignore this with --force if ok { log.Info(repo.GoPath, "git says it does not own go.mod") // continue and attempt to create go.mod and go.sum } else { if forge.Config.IsReadOnly(repo.GoPath) { log.Info("skipping read only", repo.GoPath) return nil } // continue and attempt to create go.mod and go.sum } if repo.CheckDirty() { log.Info("") log.Info("You can not run this on dirty branches.") log.Info("") return errors.New(repo.GoPath + " git repo is dirty") } log.Info(repo.GoPath, "GOING TO MAKE NEW go.* FILES") // actually will re-create go.sum and go.mod now if err := redoGoMod(repo); err != nil { return err } if argv.Trim { // the first time, it'll attempt to fix some stuff cleanGoDepsCheckOk(repo) // try to trim junk if err := trimGoSum(repo); err != nil { return err } repo.ParseGoSum() } /* data, _ := repo.ReadFile("go.mod") log.Info(string(data)) data, _ = repo.ReadFile("go.sum") log.Info(string(data)) */ // check go.sum file if err := cleanGoDepsCheckOk(repo); err != nil { log.Info("forge.FinalGoDepsCheck() failed. boo. :", repo.GoPath) return err } // put the files in the notes section in git // this way, git commits are not messed up // with this autogenerated code if err := saveAsMetadata(repo); err != nil { log.Info("save go.mod as git metadata failed", repo.GoPath, err) return err } // everything worked! configSave = true return nil }