From 36b903423828b2e35c9c1fde3fdc898fe2ed23ca Mon Sep 17 00:00:00 2001 From: Stefan Majewsky Date: Sun, 7 May 2017 22:46:38 +0200 Subject: refactor towards new cli.Interface --- pkg/rtree/index.go | 146 +++++++++++++++++++++++++++++------------------------ 1 file changed, 80 insertions(+), 66 deletions(-) (limited to 'pkg/rtree/index.go') diff --git a/pkg/rtree/index.go b/pkg/rtree/index.go index dd1b979..c2c0202 100644 --- a/pkg/rtree/index.go +++ b/pkg/rtree/index.go @@ -23,14 +23,12 @@ import ( "fmt" "io/ioutil" "os" - "os/exec" "path" "path/filepath" "sort" "strings" "github.com/majewsky/gofu/pkg/cli" - "github.com/majewsky/gofu/pkg/util" yaml "gopkg.in/yaml.v2" ) @@ -102,7 +100,7 @@ func (r reposByAbsPath) Less(i, j int) bool { return r[i].AbsolutePath() < r[j]. func (r reposByAbsPath) Swap(i, j int) { r[i], r[j] = r[j], r[i] } //Write writes the index file to disk. -func (i *Index) Write() error { +func (i *Index) Write(ci *cli.Interface) error { buf, err := yaml.Marshal(i) if err != nil { return err @@ -123,7 +121,9 @@ func (i *Index) Write() error { warned := make(map[string]bool) for _, repo := range i.Repos { if seen[repo.CheckoutPath] && !warned[repo.CheckoutPath] { - fmt.Fprintf(os.Stderr, "warning: repo %s appears multiple times in the index file!\n", repo.AbsolutePath()) + ci.ShowWarning( + fmt.Sprintf("repo %s appears multiple times in the index file!", repo.AbsolutePath()), + ) warned[repo.CheckoutPath] = true } seen[repo.CheckoutPath] = true @@ -132,8 +132,8 @@ func (i *Index) Write() error { return nil } -//InteractiveRebuild implements the `rtree index` subcommand. -func (i *Index) InteractiveRebuild() error { +//Rebuild implements the `rtree index` subcommand. +func (i *Index) Rebuild(ci *cli.Interface) error { //check if existing index entries are still checked out var newRepos []*Repo for _, repo := range i.Repos { @@ -161,32 +161,35 @@ func (i *Index) InteractiveRebuild() error { remoteURLs = append(remoteURLs, remote.URL) } - var choice cli.Choice + var selection string if len(remoteURLs) == 0 { - choice, _ = cli.Query( + selection, err = ci.Query( fmt.Sprintf("repository %s has been deleted; no remote to restore from", filepath.Join(RootPath, repo.CheckoutPath)), - cli.Choice{Shortcut: 'd', Text: "delete from index"}, - cli.Choice{Shortcut: 's', Text: "skip"}, + cli.Choice{Return: "d", Shortcut: 'd', Text: "delete from index"}, + cli.Choice{Return: "s", Shortcut: 's', Text: "skip"}, ) } else { - choice, _ = cli.Query( + selection, err = ci.Query( fmt.Sprintf("repository %s has been deleted", filepath.Join(RootPath, repo.CheckoutPath)), - cli.Choice{Shortcut: 'r', Text: "(r)estore from " + strings.Join(remoteURLs, " and ")}, - cli.Choice{Shortcut: 'd', Text: "delete from index"}, - cli.Choice{Shortcut: 's', Text: "skip"}, + cli.Choice{Return: "r", Shortcut: 'r', Text: "(r)estore from " + strings.Join(remoteURLs, " and ")}, + cli.Choice{Return: "d", Shortcut: 'd', Text: "delete from index"}, + cli.Choice{Return: "s", Shortcut: 's', Text: "skip"}, ) } + if err != nil { + return err + } - switch choice.Shortcut { - case 'r': - err := repo.Checkout() + switch selection { + case "r": + err := repo.Checkout(ci) if err != nil { return err } newRepos = append(newRepos, repo) - case 'd': + case "d": continue - case 's': + case "s": newRepos = append(newRepos, repo) } } @@ -197,7 +200,7 @@ func (i *Index) InteractiveRebuild() error { } //index new repos - err := ForeachPhysicalRepo(func(newRepo Repo) error { + err := ForeachPhysicalRepo(ci, func(newRepo Repo) error { repo, exists := existingRepos[newRepo.CheckoutPath] if exists { //update the existing index entry with the new remotes @@ -215,12 +218,10 @@ func (i *Index) InteractiveRebuild() error { return nil } -var tenLetters = []string{"a", "b", "c", "d", "e", "f", "g", "h", "i", "j"} - -//InteractiveFindRepo locates the repo with the given remote if it exists on -//disk or (if allowClone is set) clones it and adds it to the index. This -//is the meat of `rtree get`, and is also used by `rtree drop`. -func (i *Index) InteractiveFindRepo(remoteURL string, allowClone bool) (*Repo, error) { +//FindRepo locates the repo with the given remote if it exists on disk or (if +//allowClone is set) clones it and adds it to the index. This is the meat of +//`rtree get`, and is also used by `rtree drop`. +func (i *Index) FindRepo(ci *cli.Interface, remoteURL string, allowClone bool) (*Repo, error) { //make sure that stdout is not used for prompts originalStdout := os.Stdout os.Stdout = os.Stderr @@ -255,7 +256,7 @@ func (i *Index) InteractiveFindRepo(remoteURL string, allowClone bool) (*Repo, e if err != nil { return nil, err } - fi, err := os.Stat(newRepo.AbsolutePath()) + _, err = os.Stat(newRepo.AbsolutePath()) switch { case err == nil: return nil, fmt.Errorf( @@ -272,12 +273,12 @@ func (i *Index) InteractiveFindRepo(remoteURL string, allowClone bool) (*Repo, e //if no fork candidates found, clone as new repo if len(candidates) == 0 { - err := newRepo.Checkout() + err := newRepo.Checkout(ci) if err != nil { return nil, err } i.Repos = append(i.Repos, &newRepo) - i.Write() + i.Write(ci) return &newRepo, nil } @@ -288,49 +289,60 @@ func (i *Index) InteractiveFindRepo(remoteURL string, allowClone bool) (*Repo, e } choices := make([]cli.Choice, len(candidates)+1) for idx, repo := range candidates { - choices[idx] = cli.Choice{Text: "add as remote to " + repo.AbsolutePath()} + choices[idx] = cli.Choice{Text: "add as remote to " + repo.AbsolutePath(), Return: repo.CheckoutPath} } choices[len(candidates)] = cli.Choice{ + Return: "clone", Shortcut: 'n', Text: "clone to " + newRepo.AbsolutePath(), } - choice, choiceIdx := cli.Query("Found possible fork candidates. What to do?", choices...) + selection, err := ci.Query("Found possible fork candidates. What to do?", choices...) + if err != nil { + return nil, err + } - if choice.Shortcut == 'n' { - err := newRepo.Checkout() + if selection == "clone" { + err := newRepo.Checkout(ci) if err != nil { return nil, err } i.Repos = append(i.Repos, &newRepo) - i.Write() + i.Write(ci) return &newRepo, nil } //find the repo selected by the user - target := candidates[choiceIdx] + var target *Repo + for _, repo := range candidates { + if target.CheckoutPath == selection { + target = repo + break + } + } //report the existing remotes, and ask for the name of the new remote - fmt.Println("Existing remotes:") + prompt := "Existing remotes:\n" for _, remote := range target.Remotes { - fmt.Printf("\t(%s) %s\n", remote.Name, remote.URL) + prompt += fmt.Sprintf("\t(%s) %s\n", remote.Name, remote.URL) + } + prompt += fmt.Sprintf("Enter remote name for %s:", remoteURL) + remoteName, err := ci.ReadLine(prompt) + if err != nil { + return nil, err } - fmt.Printf("Enter remote name for %s: ", remoteURL) - remoteName := util.ReadLine() - cmd := exec.Command("git", "remote", "add", remoteName, remoteURL) - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - cmd.Dir = target.AbsolutePath() - err = cmd.Run() + err = ci.Run(cli.Command{ + Program: []string{"git", "remote", "add", remoteName, remoteURL}, + WorkDir: target.AbsolutePath(), + }) if err != nil { return nil, err } - cmd = exec.Command("git", "remote", "update", remoteName) - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - cmd.Dir = target.AbsolutePath() - err = cmd.Run() + err = ci.Run(cli.Command{ + Program: []string{"git", "remote", "update", remoteName}, + WorkDir: target.AbsolutePath(), + }) if err != nil { return nil, err } @@ -339,18 +351,18 @@ func (i *Index) InteractiveFindRepo(remoteURL string, allowClone bool) (*Repo, e Name: remoteName, URL: remoteURL, }) - i.Write() + i.Write(ci) return target, nil } -//InteractiveImportRepo moves the given repo into the rtree and adds it to the index. -func (i *Index) InteractiveImportRepo(dirPath string) error { +//ImportRepo moves the given repo into the rtree and adds it to the index. +func (i *Index) ImportRepo(ci *cli.Interface, dirPath string) error { //need to make dirPath absolute first dirPath, err := filepath.Abs(dirPath) if err != nil { return err } - repo, err := NewRepoFromAbsolutePath(dirPath) + repo, err := NewRepoFromAbsolutePath(ci, dirPath) if err != nil { return err } @@ -373,7 +385,7 @@ func (i *Index) InteractiveImportRepo(dirPath string) error { checkoutPath = thisPath break } - choices[idx] = cli.Choice{Text: thisPath} + choices[idx] = cli.Choice{Return: thisPath, Text: thisPath} } //cannot decide myself -> let the user select @@ -383,8 +395,10 @@ func (i *Index) InteractiveImportRepo(dirPath string) error { } question := fmt.Sprintf("Repo has multiple remotes. Where to put below %s?", RootPath) - choice, _ := cli.Query(question, choices...) - checkoutPath = choice.Text + checkoutPath, err = ci.Query(question, choices...) + if err != nil { + return err + } } //double-check that there is no such repo in the rtree yet @@ -403,18 +417,18 @@ func (i *Index) InteractiveImportRepo(dirPath string) error { return nil } -//InteractiveDropRepo deletes the given repo from the rtree and removes it from -//the index. -func (i *Index) InteractiveDropRepo(repo *Repo) error { - ok := repo.InteractiveExec("git", "status") - if !ok { - return nil +//DropRepo deletes the given repo from the rtree and removes it from the index. +func (i *Index) DropRepo(ci *cli.Interface, repo *Repo) error { + err := repo.Exec(ci, "git", "status") + if err != nil { + return err } - if !cli.Confirm(">> Drop this repo?") { - return nil + ok, err := ci.Confirm(">> Drop this repo?") + if !ok || err != nil { + return err } - err := os.RemoveAll(repo.AbsolutePath()) + err = os.RemoveAll(repo.AbsolutePath()) if err != nil { return err } @@ -426,5 +440,5 @@ func (i *Index) InteractiveDropRepo(repo *Repo) error { } } i.Repos = reposNew - return nil + return i.Write(ci) } -- cgit v1.3.1