summaryrefslogtreecommitdiff
path: root/pkg/rtree/index.go
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/rtree/index.go')
-rw-r--r--pkg/rtree/index.go146
1 files changed, 80 insertions, 66 deletions
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)
}