package main import ( "errors" "os" "path/filepath" "go.wit.com/dev/alexflint/arg" "go.wit.com/gui" "go.wit.com/lib/gui/repolist" "go.wit.com/lib/gui/shell" "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 rv *repolist.RepoList var argvRepo *gitpb.Repo func main() { pp = arg.MustParse(&argv) // for very new users or users unfamilar with the command line, this may help them if argv.Repo == "help" || argv.Repo == "?" { pp.WriteHelp(os.Stdout) os.Exit(0) } if argv.Repo == "version" { log.Info(argv.Version()) os.Exit(0) } // load the ~/.config/forge/ config // this lets you configure repos you have read/write access too forge = forgepb.Init() // forge.ConfigPrintTable() os.Setenv("REPO_WORK_PATH", forge.GetGoSrc()) argvRepo = forge.Repos.FindByGoPath(argv.Repo) if argvRepo == nil { log.Info("yep, need to clone", argv.Repo) } else { log.Info("already have", argv.Repo) build() okExit(argv.Repo) } // gui is in testing myGui := gui.New() // myGui.Default() // find and scan all repos rv := repolist.Init(forge, myGui) rv.Enable() rv.ScanRepositories() // run 'git pull' if argv --git-pull if argv.Pull { gitPull() okExit("git pull") } // remake all the go.sum & go.mod in every repo // todo: make go.sum and go.mod git commit metadata if argv.RedoGoMod { redoGoModAll() } // this works sometimes if argv.Recursive { recursiveClone() autoWork() build() okExit("--recursive") } clone() autoWork() if argv.Install { if err := forge.Install(argvRepo, nil); err == nil { okExit("install worked") } else { badExit(err) } } if argv.Build { if err := forge.Build(argvRepo, nil); err == nil { okExit("build worked") } else { badExit(err) } } okExit("skipping build of " + argv.Repo) } func okExit(thing string) { log.Info(thing, "ok") log.Info("Finished clone on", argvRepo.GetGoPath(), "ok") os.Exit(0) } func badExit(err error) { log.Info("Total repositories:", forge.Repos.Len()) log.Info("Finished go-clone with error", err) os.Exit(-1) } func clone() { // if the user defined a repo, attempt to download it now if argv.Repo != "" { os.Setenv("REPO_AUTO_CLONE", "true") // pb, _ := forge.NewGoPath(argv.Repo) pb, err := forge.Clone(argv.Repo) if err != nil { log.Info("could not download") badExit(err) } newr, err := rv.AddRepo(pb) if err != nil { log.Info("repolist.AddRepo() failed") badExit(err) } // update go.sum and go.mod // todo: only do this if they don't exist? // todo: make these git commit metadata newr.MakeRedoMod() // double check it actually downloaded fullgitdir := filepath.Join(forge.GetGoSrc(), argv.Repo, ".git") if !shell.IsDir(fullgitdir) { log.Info("repo cloned failed", filepath.Join(forge.GetGoSrc(), argv.Repo)) badExit(errors.New(fullgitdir + " was not created")) } build() // exit unless other --argv options are set if !(argv.Recursive || argv.Pull || argv.RedoGoMod) { log.Info("repo cloned worked to", filepath.Join(forge.GetGoSrc(), argv.Repo)) okExit(argv.Repo) } log.Info("onward and upward") } } func gitPull() { log.Info("Total repositories:", forge.Repos.Len()) log.Info("Going to run git pull in each one. TODO: use rill here") log.Sleep(1) pull := []string{"git", "pull"} var trycount, errcount int repos := forge.Repos.SortByGoPath() for repos.Scan() { repo := repos.Next() if argv.DryRun { log.Info("git pull --dry-run", repo.GoPath) continue } log.Info("git pull:", repo.FullPath) trycount += 1 log.Info("actually run: git pull:", repo.GoPath) if result := shell.PathRunRealtime(repo.FullPath, pull); result.Error != nil { log.Info("git pull error:", result.Error) errcount += 1 } } log.Info("Total repositories:", forge.Repos.Len(), "Total attempted:", trycount, "Errors:", errcount) } func recursiveClone() { // this works sometimes if argv.Recursive { newr := rv.FindByName(argv.Repo) if newr == nil { log.Info("how did this repo still not exist?", argv.Repo) badExit(errors.New("failed to clone repo: " + argv.Repo)) } os.Setenv("REPO_AUTO_CLONE", "true") godep := newr.Status.GetGoDeps() for gopath, version := range godep { pb, err := forge.Clone(gopath) if err != nil { log.Info("could not download") badExit(err) } repo, err := rv.AddRepo(pb) if err != nil { log.Info("git clone failed for", gopath, version) continue } // always do this for now. probably always forever repo.MakeRedoMod() } } } func redoGoModAll() { loop := rv.ReposSortByName() for loop.Scan() { repo := loop.Repo() repo.MakeRedoMod() } } func build() error { if argv.Install { if err := forge.Install(argvRepo, nil); err == nil { okExit("install worked") } else { badExit(err) } } if argv.Build { return forge.Build(argvRepo, nil) } log.Info("skipping build") return nil } func autoWork() { // remake the go.work file if argv.AutoWork { log.Info("About to re-create", forge.GetGoSrc()+"/go.work") log.Info("Sleep 3. original go.work saved as go.work.last (hit ctrl-c to cancel)") log.Sleep(3) shell.PathRun(forge.GetGoSrc(), []string{"mv", "go.work", "go.work.last"}) rv.MakeGoWork() shell.PathRun(forge.GetGoSrc(), []string{"go", "work", "use"}) log.Info("") log.Info("original go.work file saved as go.work.last") log.Info("") okExit("go.work create") } }