summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--main.go11
-rw-r--r--pkg/cli/command.go10
-rw-r--r--pkg/cli/interface.go76
-rw-r--r--pkg/cli/query.go6
-rw-r--r--pkg/rtree/index.go48
-rw-r--r--pkg/rtree/main.go80
-rw-r--r--pkg/rtree/remote.go14
-rw-r--r--pkg/rtree/repo.go26
8 files changed, 141 insertions, 130 deletions
diff --git a/main.go b/main.go
index 30ae9c4..03dc9de 100644
--- a/main.go
+++ b/main.go
@@ -29,30 +29,29 @@ import (
)
func main() {
- ci := cli.NewInterface(os.Stdin, os.Stdout, os.Stderr)
if len(earlyerrors.Get()) > 0 {
for _, msg := range earlyerrors.Get() {
- ci.ShowError(msg)
+ cli.Interface.ShowError(msg)
}
os.Exit(255)
}
- os.Exit(execApplet(ci, filepath.Base(os.Args[0]), os.Args[1:], true))
+ os.Exit(execApplet(filepath.Base(os.Args[0]), os.Args[1:], true))
}
-func execApplet(ci *cli.Interface, applet string, args []string, allowGofu bool) int {
+func execApplet(applet string, args []string, allowGofu bool) int {
//allow explicit specification of applet as "./build/gofu <applet> <args>"
if allowGofu && applet == "gofu" {
if len(args) == 0 {
fmt.Fprintln(os.Stderr, "Usage: gofu <applet> [args...]")
return 1
}
- return execApplet(ci, args[0], args[1:], false)
+ return execApplet(args[0], args[1:], false)
}
switch applet {
case "rtree":
- return rtree.Exec(ci, args)
+ return rtree.Exec(args)
default:
fmt.Fprintln(os.Stderr, "ERROR: unknown applet: "+applet)
return 255
diff --git a/pkg/cli/command.go b/pkg/cli/command.go
index 5b3ded5..d07a120 100644
--- a/pkg/cli/command.go
+++ b/pkg/cli/command.go
@@ -26,7 +26,7 @@ import (
)
//Command describes a command that can be run using the methods in the
-//Interface interface.
+//Implementation interface.
type Command struct {
Program []string
WorkDir string
@@ -49,8 +49,14 @@ func (e commandError) Error() string {
)
}
-func (c Command) run(stdout, stderr io.Writer) error {
+//CommandRunner is a function that can execute commands given to it.
+//This interface is only useful for unit tests; the default CommandRunner
+//suffices for all regular operation.
+type CommandRunner func(c Command, stdin io.Reader, stdout, stderr io.Writer) error
+
+func DefaultCommandRunner(c Command, stdin io.Reader, stdout, stderr io.Writer) error {
cmd := exec.Command(c.Program[0], c.Program[1:]...)
+ cmd.Stdin = stdin
cmd.Stdout = stdout
cmd.Stderr = stderr
cmd.Dir = c.WorkDir
diff --git a/pkg/cli/interface.go b/pkg/cli/interface.go
index c188c77..0f1ba74 100644
--- a/pkg/cli/interface.go
+++ b/pkg/cli/interface.go
@@ -30,32 +30,40 @@ import (
"golang.org/x/crypto/ssh/terminal"
)
-//NewInterface creates an Interface instance.
-func NewInterface(stdin, stdout, stderr *os.File) *Interface {
- i := &Interface{
- stdin: stdin,
- stdout: stdout,
- stderr: stderr,
- stdinBuf: bufio.NewReader(stdin),
+//Interface wraps access to the CLI, including input, output and subprocesses.
+var Interface *Implementation
+
+func init() {
+ SetupInterface(os.Stdin, os.Stdout, os.Stderr, DefaultCommandRunner)
+}
+
+//SetupInterface prepares the Interface instance with nonstandard file streams
+//or a nonstandard CommandRunner. This is only required for unit tests.
+func SetupInterface(stdin io.Reader, stdout, stderr io.Writer, commandRunner CommandRunner) {
+ Interface = &Implementation{
+ stdin: stdin,
+ stdout: stdout,
+ stderr: stderr,
+ stdinBuf: bufio.NewReader(stdin),
+ commandRunner: commandRunner,
}
- if terminal.IsTerminal(int(stdin.Fd())) {
- i.tui = &terminalTUI{i}
+ if stdinFile, ok := stdin.(*os.File); ok && terminal.IsTerminal(int(stdinFile.Fd())) {
+ Interface.tui = &terminalTUI{Interface}
} else {
- i.tui = &pipeTUI{i}
+ Interface.tui = &pipeTUI{Interface}
}
-
- return i
}
-//Interface wraps access to the CLI, including input, output and subprocesses.
-type Interface struct {
+//Implementation wraps access to the CLI, including input, output and subprocesses.
+type Implementation struct {
//TODO: flag isStdinTerminal that disables color output and swaps out the TUI instance
- stdin io.Reader
- stdout io.Writer
- stderr io.Writer
- stdinBuf *bufio.Reader
- tui TUI
+ stdin io.Reader
+ stdout io.Writer
+ stderr io.Writer
+ stdinBuf *bufio.Reader
+ tui TUI
+ commandRunner CommandRunner
//If this flag is set, only ShowResult() will write into stdout; everything
//else that usually goes to stdout goes to stderr instead.
//
@@ -65,7 +73,7 @@ type Interface struct {
StdoutProtected bool
}
-//TUI provides the interactive parts of the cli.Interface, so that these can be
+//TUI provides the interactive parts of the cli.Implementation, so that these can be
//easily swapped out for mock implementations in unit tests.
type TUI interface {
//ReadLine reads a line from stdin (if tty: uses canonical mode).
@@ -77,7 +85,7 @@ type TUI interface {
Query(prompt string, choices ...Choice) (string, error)
}
-func (i *Interface) safeStdout() io.Writer {
+func (i *Implementation) safeStdout() io.Writer {
if i.StdoutProtected {
return i.stderr
}
@@ -88,18 +96,18 @@ func (i *Interface) safeStdout() io.Writer {
// input
//ReadLine reads a line from stdin (if tty: uses canonical mode).
-func (i *Interface) ReadLine(prompt string) (string, error) {
+func (i *Implementation) ReadLine(prompt string) (string, error) {
return i.tui.ReadLine(prompt)
}
//Confirm displays a yes/no question and returns whether the user answered "yes".
-func (i *Interface) Confirm(question string) (bool, error) {
+func (i *Implementation) Confirm(question string) (bool, error) {
return i.tui.Confirm(question)
}
//Query displays a question and a set of answers and allows the user to select
//one of the answers. Returns the Return attribute of the selected Choice.
-func (i *Interface) Query(prompt string, choices ...Choice) (string, error) {
+func (i *Implementation) Query(prompt string, choices ...Choice) (string, error) {
return i.tui.Query(prompt, choices...)
}
@@ -107,14 +115,14 @@ func (i *Interface) Query(prompt string, choices ...Choice) (string, error) {
// subprocesses
//Run executes the given command on the same stdout and stderr.
-func (i *Interface) Run(c Command) error {
- return c.run(i.safeStdout(), i.stderr)
+func (i *Implementation) Run(c Command) error {
+ return i.commandRunner(c, nil, i.safeStdout(), i.stderr)
}
//CaptureStdout executes the given command on the same stderr and captures its stdout.
-func (i *Interface) CaptureStdout(c Command) (string, error) {
+func (i *Implementation) CaptureStdout(c Command) (string, error) {
var buf bytes.Buffer
- err := c.run(&buf, i.stderr)
+ err := i.commandRunner(c, nil, &buf, i.stderr)
return string(buf.Bytes()), err
}
@@ -122,13 +130,13 @@ func (i *Interface) CaptureStdout(c Command) (string, error) {
// output
//ShowResult displays the result of a computation on stdout.
-func (i *Interface) ShowResult(str string) {
+func (i *Implementation) ShowResult(str string) {
str = strings.TrimSpace(str) + "\n"
i.stdout.Write([]byte(str))
}
//ShowResultsSorted calls ShowResult() on each of the results after sorting them.
-func (i *Interface) ShowResultsSorted(strs []string) {
+func (i *Implementation) ShowResultsSorted(strs []string) {
sort.Strings(strs)
for _, str := range strs {
i.ShowResult(str)
@@ -136,22 +144,22 @@ func (i *Interface) ShowResultsSorted(strs []string) {
}
//ShowProgress displays a progress message on stderr.
-func (i *Interface) ShowProgress(str string) {
+func (i *Implementation) ShowProgress(str string) {
fmt.Fprintf(i.stderr, "\x1B[0;1;36m>>\x1B[0;36m %s\x1B[0m", strings.TrimSpace(str))
}
//ShowWarning displays a warning message on stderr.
-func (i *Interface) ShowWarning(str string) {
+func (i *Implementation) ShowWarning(str string) {
fmt.Fprintf(i.stderr, "\x1B[0;1;33m!!\x1B[0;36m %s\x1B[0m", strings.TrimSpace(str))
}
//ShowError displays an error message on stderr.
-func (i *Interface) ShowError(str string) {
+func (i *Implementation) ShowError(str string) {
fmt.Fprintf(i.stderr, "\x1B[0;1;31m!!\x1B[0;36m %s\x1B[0m", strings.TrimSpace(str))
}
//ShowUsage displays a usage synopsis on stderr.
-func (i *Interface) ShowUsage(str string) {
+func (i *Implementation) ShowUsage(str string) {
str = strings.TrimSpace(str) + "\n"
i.stderr.Write([]byte(str))
}
diff --git a/pkg/cli/query.go b/pkg/cli/query.go
index ed9e913..d9aa9a2 100644
--- a/pkg/cli/query.go
+++ b/pkg/cli/query.go
@@ -41,7 +41,7 @@ func (e errInterrupted) Error() string {
// TUI implementation for when stdin is a terminal
type terminalTUI struct {
- i *Interface
+ i *Implementation
}
func (t terminalTUI) ReadLine(prompt string) (string, error) {
@@ -78,7 +78,7 @@ type Choice struct {
Shortcut byte
//The display string that describes this choice.
Text string
- //The string to return from Interface.Query().
+ //The string to return from Implementation.Query().
Return string
}
@@ -228,7 +228,7 @@ func (b *buffer) getNextInput() []byte {
// TUI implementation for when stdin is a pipe
type pipeTUI struct {
- i *Interface
+ i *Implementation
}
func (t *pipeTUI) ReadLine(prompt string) (string, error) {
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(),
})