package main import ( "errors" "os" "path/filepath" "go.wit.com/dev/alexflint/arg" "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 argvRepo *gitpb.Repo func main() { log.Info("go-clone version", VERSION, "built on", BUILDTIME) 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() argvRepo = forge.Repos.FindByGoPath(argv.Repo) if argvRepo == nil { log.Info("yep, need to clone", argv.Repo) } else { log.Info("already have", argv.Repo) if argv.Recursive { clone() recursiveClone() } autoWork() build() okExit(argv.Repo) } // gui is in testing // myGui := gui.New() // myGui.Default() // 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 { clone() 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") argvRepo.RunEcho([]string{"ls", "-l"}) } else { argvRepo.RunEcho([]string{"ls", "-l"}) 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, forge.GetGoSrc()) 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) check := forge.Repos.FindByGoPath(argv.Repo) if check != nil { return } pb, err := forge.Clone(argv.Repo) if err != nil { log.Info("clone() could not download err:", err) badExit(err) } // update go.sum and go.mod // todo: only do this if they don't exist? // todo: make these git commit metadata pb.RedoGoMod() // 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) } // really only does go.sum things // so not 'really' recursive // but that is because go.sum is supposed // to have everything required in it func recursiveClone() { var good int var bad int // this works sometimes if argv.Recursive { check := forge.Repos.FindByGoPath(argv.Repo) log.Info("download deps for:", check.GoPath) deps := check.GoDeps.SortByGoPath() for deps.Scan() { depRepo := deps.Next() log.Info("download:", depRepo.GoPath) _, err := forge.Clone(depRepo.GoPath) if err != nil { log.Info("recursiveClone() could not download", depRepo.GoPath) log.Info("err:", err) bad += 1 } else { log.Info("downloaded", depRepo.GoPath) good += 1 } } } log.Info("got", good, "repos", "failed on", bad, "repos") } func build() error { forge.RillRedoGoMod() repos := forge.Repos.SortByGoPath() for repos.Scan() { repo := repos.Next() log.Info("go.work repo (hopefully):", repo.GoPath, repo.FullPath, repo.RepoType()) } if argv.Install { if err := forge.Install(argvRepo, nil); err == nil { okExit("install worked") } else { badExit(err) } } if argv.Build { err := forge.Build(argvRepo, nil) pwd, _ := os.Getwd() if err == nil { log.Info("this totally worked", pwd) shell.RunEcho([]string{"ls", "-l"}) log.Info("ran ls") } else { log.Info("this totally did not work", pwd) shell.RunEcho([]string{"ls", "-l"}) log.Info("ran ls") } return err } 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"}) forge.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") } }