diff options
| author | Stefan Majewsky <majewsky@gmx.net> | 2017-05-09 21:32:16 +0200 |
|---|---|---|
| committer | Stefan Majewsky <majewsky@gmx.net> | 2017-05-09 21:38:24 +0200 |
| commit | a92faf7689fa01595fd613ddd3880e9c301ed558 (patch) | |
| tree | f6607fa23ac41385f9f18d8ed6ad0f970c4ba6df /pkg/rtree | |
| parent | a4dfbab3b06360245f6b2fce4b56d6caf2729f8f (diff) | |
| download | gofu-a92faf7689fa01595fd613ddd3880e9c301ed558.tar.gz | |
refactor cli.Interface yet again
- Only one global instance now, so we don't need to pass it around all
the time.
- Allow to swap out the Command.Run implementation for unit tests.
- Can now use cli.Interface during func init() of packages importing
pkg/cli.
Diffstat (limited to 'pkg/rtree')
| -rw-r--r-- | pkg/rtree/index.go | 48 | ||||
| -rw-r--r-- | pkg/rtree/main.go | 80 | ||||
| -rw-r--r-- | pkg/rtree/remote.go | 14 | ||||
| -rw-r--r-- | pkg/rtree/repo.go | 26 |
4 files changed, 83 insertions, 85 deletions
diff --git a/pkg/rtree/index.go b/pkg/rtree/index.go index d0813fe..49ef385 100644 --- a/pkg/rtree/index.go +++ b/pkg/rtree/index.go @@ -104,7 +104,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(ci *cli.Interface) error { +func (i *Index) Write() error { buf, err := yaml.Marshal(i) if err != nil { return err @@ -125,7 +125,7 @@ func (i *Index) Write(ci *cli.Interface) error { warned := make(map[string]bool) for _, repo := range i.Repos { if seen[repo.CheckoutPath] && !warned[repo.CheckoutPath] { - ci.ShowWarning( + cli.Interface.ShowWarning( fmt.Sprintf("repo %s appears multiple times in the index file!", repo.AbsolutePath()), ) warned[repo.CheckoutPath] = true @@ -137,7 +137,7 @@ func (i *Index) Write(ci *cli.Interface) error { } //Rebuild implements the `rtree index` subcommand. -func (i *Index) Rebuild(ci *cli.Interface) error { +func (i *Index) Rebuild() error { //check if existing index entries are still checked out var newRepos []*Repo for _, repo := range i.Repos { @@ -167,13 +167,13 @@ func (i *Index) Rebuild(ci *cli.Interface) error { var selection string if len(remoteURLs) == 0 { - selection, err = ci.Query( + selection, err = cli.Interface.Query( fmt.Sprintf("repository %s has been deleted; no remote to restore from", filepath.Join(RootPath, repo.CheckoutPath)), cli.Choice{Return: "d", Shortcut: 'd', Text: "delete from index"}, cli.Choice{Return: "s", Shortcut: 's', Text: "skip"}, ) } else { - selection, err = ci.Query( + selection, err = cli.Interface.Query( fmt.Sprintf("repository %s has been deleted", filepath.Join(RootPath, repo.CheckoutPath)), cli.Choice{Return: "r", Shortcut: 'r', Text: "(r)estore from " + strings.Join(remoteURLs, " and ")}, cli.Choice{Return: "d", Shortcut: 'd', Text: "delete from index"}, @@ -186,7 +186,7 @@ func (i *Index) Rebuild(ci *cli.Interface) error { switch selection { case "r": - err := repo.Checkout(ci) + err := repo.Checkout() if err != nil { return err } @@ -204,7 +204,7 @@ func (i *Index) Rebuild(ci *cli.Interface) error { } //index new repos - err := ForeachPhysicalRepo(ci, func(newRepo Repo) error { + err := ForeachPhysicalRepo(func(newRepo Repo) error { repo, exists := existingRepos[newRepo.CheckoutPath] if exists { //update the existing index entry with the new remotes @@ -225,7 +225,7 @@ func (i *Index) Rebuild(ci *cli.Interface) 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) { +func (i *Index) FindRepo(remoteURL string, allowClone bool) (*Repo, error) { //make sure that stdout is not used for prompts originalStdout := os.Stdout os.Stdout = os.Stderr @@ -277,12 +277,12 @@ func (i *Index) FindRepo(ci *cli.Interface, remoteURL string, allowClone bool) ( //if no fork candidates found, clone as new repo if len(candidates) == 0 { - err := newRepo.Checkout(ci) + err := newRepo.Checkout() if err != nil { return nil, err } i.Repos = append(i.Repos, &newRepo) - i.Write(ci) + i.Write() return &newRepo, nil } @@ -300,18 +300,18 @@ func (i *Index) FindRepo(ci *cli.Interface, remoteURL string, allowClone bool) ( Shortcut: 'n', Text: "clone to " + newRepo.AbsolutePath(), } - selection, err := ci.Query("Found possible fork candidates. What to do?", choices...) + selection, err := cli.Interface.Query("Found possible fork candidates. What to do?", choices...) if err != nil { return nil, err } if selection == "clone" { - err := newRepo.Checkout(ci) + err := newRepo.Checkout() if err != nil { return nil, err } i.Repos = append(i.Repos, &newRepo) - i.Write(ci) + i.Write() return &newRepo, nil } @@ -330,12 +330,12 @@ func (i *Index) FindRepo(ci *cli.Interface, remoteURL string, allowClone bool) ( 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) + remoteName, err := cli.Interface.ReadLine(prompt) if err != nil { return nil, err } - err = ci.Run(cli.Command{ + err = cli.Interface.Run(cli.Command{ Program: []string{"git", "remote", "add", remoteName, remoteURL}, WorkDir: target.AbsolutePath(), }) @@ -343,7 +343,7 @@ func (i *Index) FindRepo(ci *cli.Interface, remoteURL string, allowClone bool) ( return nil, err } - err = ci.Run(cli.Command{ + err = cli.Interface.Run(cli.Command{ Program: []string{"git", "remote", "update", remoteName}, WorkDir: target.AbsolutePath(), }) @@ -355,18 +355,18 @@ func (i *Index) FindRepo(ci *cli.Interface, remoteURL string, allowClone bool) ( Name: remoteName, URL: remoteURL, }) - i.Write(ci) + i.Write() return target, nil } //ImportRepo moves the given repo into the rtree and adds it to the index. -func (i *Index) ImportRepo(ci *cli.Interface, dirPath string) error { +func (i *Index) ImportRepo(dirPath string) error { //need to make dirPath absolute first dirPath, err := filepath.Abs(dirPath) if err != nil { return err } - repo, err := NewRepoFromAbsolutePath(ci, dirPath) + repo, err := NewRepoFromAbsolutePath(dirPath) if err != nil { return err } @@ -399,7 +399,7 @@ func (i *Index) ImportRepo(ci *cli.Interface, dirPath string) error { } question := fmt.Sprintf("Repo has multiple remotes. Where to put below %s?", RootPath) - checkoutPath, err = ci.Query(question, choices...) + checkoutPath, err = cli.Interface.Query(question, choices...) if err != nil { return err } @@ -422,12 +422,12 @@ func (i *Index) ImportRepo(ci *cli.Interface, dirPath string) error { } //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") +func (i *Index) DropRepo(repo *Repo) error { + err := repo.Exec("git", "status") if err != nil { return err } - ok, err := ci.Confirm(">> Drop this repo?") + ok, err := cli.Interface.Confirm(">> Drop this repo?") if !ok || err != nil { return err } @@ -444,5 +444,5 @@ func (i *Index) DropRepo(ci *cli.Interface, repo *Repo) error { } } i.Repos = reposNew - return i.Write(ci) + return i.Write() } diff --git a/pkg/rtree/main.go b/pkg/rtree/main.go index 42e540e..581fa7e 100644 --- a/pkg/rtree/main.go +++ b/pkg/rtree/main.go @@ -26,15 +26,15 @@ import ( //Exec executes the rtree applet and does not return. The argument is os.Args //minus the leading "rtree" or "gofu rtree". -func Exec(ci *cli.Interface, args []string) int { +func Exec(args []string) int { if len(args) == 0 { - return usage(ci) + return usage() } index, errs := ReadIndex() if len(errs) > 0 { for _, err := range errs { - ci.ShowError(err.Error()) + cli.Interface.ShowError(err.Error()) } return 1 } @@ -43,47 +43,47 @@ func Exec(ci *cli.Interface, args []string) int { switch args[0] { case "get": if len(args) != 2 { - return usage(ci) + return usage() } - err = commandGet(ci, index, args[1]) + err = commandGet(index, args[1]) case "drop": if len(args) != 2 { - return usage(ci) + return usage() } - err = commandDrop(ci, index, args[1]) + err = commandDrop(index, args[1]) case "index": if len(args) != 1 { - return usage(ci) + return usage() } - err = commandIndex(ci, index) + err = commandIndex(index) case "repos": if len(args) != 1 { - return usage(ci) + return usage() } - commandRepos(ci, index) + commandRepos(index) case "remotes": if len(args) != 1 { - return usage(ci) + return usage() } - commandRemotes(ci, index) + commandRemotes(index) case "import": if len(args) != 2 { - return usage(ci) + return usage() } - err = commandImport(ci, index, args[1]) + err = commandImport(index, args[1]) case "each": if len(args) < 2 { - return usage(ci) + return usage() } - return commandEach(ci, index, args[1:]) + return commandEach(index, args[1:]) default: - return usage(ci) + return usage() } if err == nil { return 0 } - ci.ShowError(err.Error()) + cli.Interface.ShowError(err.Error()) return 1 } @@ -95,70 +95,70 @@ Usage: rtree each <command> `) -func usage(ci *cli.Interface) int { - ci.ShowUsage(usageStr) +func usage() int { + cli.Interface.ShowUsage(usageStr) return 1 } -func commandGet(ci *cli.Interface, index *Index, url string) error { - repo, err := index.FindRepo(ci, url, true) +func commandGet(index *Index, url string) error { + repo, err := index.FindRepo(url, true) if err != nil { return err } - ci.ShowResult(repo.AbsolutePath()) + cli.Interface.ShowResult(repo.AbsolutePath()) return nil } -func commandDrop(ci *cli.Interface, index *Index, url string) error { - repo, err := index.FindRepo(ci, url, true) +func commandDrop(index *Index, url string) error { + repo, err := index.FindRepo(url, true) if err != nil { return err } - return index.DropRepo(ci, repo) + return index.DropRepo(repo) } -func commandIndex(ci *cli.Interface, index *Index) error { - err := index.Rebuild(ci) +func commandIndex(index *Index) error { + err := index.Rebuild() if err != nil { return err } - return index.Write(ci) + return index.Write() } -func commandRepos(ci *cli.Interface, index *Index) { +func commandRepos(index *Index) { var items []string for _, repo := range index.Repos { items = append(items, repo.CheckoutPath) } - ci.ShowResultsSorted(items) + cli.Interface.ShowResultsSorted(items) } -func commandRemotes(ci *cli.Interface, index *Index) { +func commandRemotes(index *Index) { var items []string for _, repo := range index.Repos { for _, remote := range repo.Remotes { items = append(items, remote.URL) } } - ci.ShowResultsSorted(items) + cli.Interface.ShowResultsSorted(items) } -func commandEach(ci *cli.Interface, index *Index, cmdline []string) (exitCode int) { +func commandEach(index *Index, cmdline []string) (exitCode int) { exitCode = 0 for _, repo := range index.Repos { - err := repo.Exec(ci, cmdline...) + err := repo.Exec(cmdline...) if err != nil { - ci.ShowError(err.Error()) + cli.Interface.ShowError(err.Error()) exitCode = 1 } } return } -func commandImport(ci *cli.Interface, index *Index, dirPath string) error { - err := index.ImportRepo(ci, dirPath) +func commandImport(index *Index, dirPath string) error { + err := index.ImportRepo(dirPath) if err != nil { return err } - return index.Write(ci) + return index.Write() } diff --git a/pkg/rtree/remote.go b/pkg/rtree/remote.go index 353916d..8f88deb 100644 --- a/pkg/rtree/remote.go +++ b/pkg/rtree/remote.go @@ -19,13 +19,12 @@ package rtree import ( - "bytes" "net/url" - "os/exec" "path/filepath" "regexp" "strings" + "github.com/majewsky/gofu/pkg/cli" "github.com/majewsky/gofu/pkg/earlyerrors" ) @@ -39,16 +38,15 @@ type remoteAlias struct { var remoteAliases []*remoteAlias func init() { - cmd := exec.Command("git", "config", "--global", "-l") - var buf bytes.Buffer - cmd.Stdout = &buf - err := cmd.Run() + out, err := cli.Interface.CaptureStdout(cli.Command{ + Program: []string{"git", "config", "--global", "-l"}, + }) if err != nil { - earlyerrors.Put("exec `git config --global -l` failed: " + err.Error()) + earlyerrors.Put(err.Error()) } rx := regexp.MustCompile(`^url\.([^=]+)\.insteadof=(.+)$`) - for _, line := range strings.Split(string(buf.Bytes()), "\n") { + for _, line := range strings.Split(out, "\n") { match := rx.FindStringSubmatch(line) if match == nil { continue diff --git a/pkg/rtree/repo.go b/pkg/rtree/repo.go index 99df30d..636e3a7 100644 --- a/pkg/rtree/repo.go +++ b/pkg/rtree/repo.go @@ -65,14 +65,14 @@ func (r Repo) AbsolutePath() string { //NewRepoFromAbsolutePath initializes a Repo instance by scanning the existing //checkout at the given path. -func NewRepoFromAbsolutePath(ci *cli.Interface, path string) (repo Repo, err error) { +func NewRepoFromAbsolutePath(path string) (repo Repo, err error) { repo.CheckoutPath, err = filepath.Rel(RootPath, path) if err != nil { return } //list remotes - out, err := ci.CaptureStdout(cli.Command{ + out, err := cli.Interface.CaptureStdout(cli.Command{ Program: []string{"git", "config", "-l"}, WorkDir: path, }) @@ -113,7 +113,7 @@ var remoteConfigRx = regexp.MustCompile(`remote\.([^=]+)\.url=(.+)`) //ForeachPhysicalRepo walks over the repository tree, executing the action //function once for every repo encountered (but *not* for repos contained //within other repos, e.g. submodules). -func ForeachPhysicalRepo(ci *cli.Interface, action func(repo Repo) error) error { +func ForeachPhysicalRepo(action func(repo Repo) error) error { return filepath.Walk(RootPath, func(path string, info os.FileInfo, err error) error { if err != nil { return err @@ -128,7 +128,7 @@ func ForeachPhysicalRepo(ci *cli.Interface, action func(repo Repo) error) error } //appears to be a repo - repo, err := NewRepoFromAbsolutePath(ci, path) + repo, err := NewRepoFromAbsolutePath(path) if err == nil { err = action(repo) } @@ -142,7 +142,7 @@ func ForeachPhysicalRepo(ci *cli.Interface, action func(repo Repo) error) error //Checkout creates the repo in the given path with the given remotes. The //working copy will only be initialized if there is an "origin" remote. -func (r Repo) Checkout(ci *cli.Interface) error { +func (r Repo) Checkout() error { //check if we have an "origin" remote to clone from var originURL string for _, remote := range r.Remotes { @@ -153,15 +153,15 @@ func (r Repo) Checkout(ci *cli.Interface) error { } if originURL == "" { - err := ci.Run(cli.Command{ + err := cli.Interface.Run(cli.Command{ Program: []string{"git", "init", r.AbsolutePath()}, }) if err != nil { return err } - ci.ShowWarning(`will not checkout anything since there is no remote named "origin"`) + cli.Interface.ShowWarning(`will not checkout anything since there is no remote named "origin"`) } else { - err := ci.Run(cli.Command{ + err := cli.Interface.Run(cli.Command{ Program: []string{"git", "clone", originURL, r.AbsolutePath()}, }) if err != nil { @@ -172,7 +172,7 @@ func (r Repo) Checkout(ci *cli.Interface) error { remotesAdded := false for _, remote := range r.Remotes { if remote.Name != "origin" { - err := ci.Run(cli.Command{ + err := cli.Interface.Run(cli.Command{ Program: []string{"git", "remote", "add", remote.Name, remote.URL}, WorkDir: r.AbsolutePath(), }) @@ -183,7 +183,7 @@ func (r Repo) Checkout(ci *cli.Interface) error { } } if remotesAdded { - return ci.Run(cli.Command{ + return cli.Interface.Run(cli.Command{ Program: []string{"git", "remote", "update"}, WorkDir: r.AbsolutePath(), }) @@ -194,9 +194,9 @@ func (r Repo) Checkout(ci *cli.Interface) error { //Exec implements the meat of the `rtree exec` command. It returns //true iff the command exited successfully. -func (r Repo) Exec(ci *cli.Interface, cmdline ...string) error { - ci.ShowProgress(r.AbsolutePath()) - return ci.Run(cli.Command{ +func (r Repo) Exec(cmdline ...string) error { + cli.Interface.ShowProgress(r.AbsolutePath()) + return cli.Interface.Run(cli.Command{ Program: cmdline, WorkDir: r.AbsolutePath(), }) |
