aboutsummaryrefslogtreecommitdiff
path: root/pkg/rtree/index.go
diff options
context:
space:
mode:
authorStefan Majewsky <majewsky@gmx.net>2017-05-02 23:05:09 +0200
committerStefan Majewsky <majewsky@gmx.net>2017-05-02 23:05:09 +0200
commitc69e9f604c47469429a6a8a27ba7ef873134e0a1 (patch)
tree9f1fe244cde4fde4b792b1136770af1e48f6fa6d /pkg/rtree/index.go
parent72733e8203654cd26464c8c5a6c955b025102cca (diff)
downloadgofu-c69e9f604c47469429a6a8a27ba7ef873134e0a1.tar.gz
initial implementation of "rtree get" command
Diffstat (limited to 'pkg/rtree/index.go')
-rw-r--r--pkg/rtree/index.go114
1 files changed, 112 insertions, 2 deletions
diff --git a/pkg/rtree/index.go b/pkg/rtree/index.go
index a4a0b74..0809fee 100644
--- a/pkg/rtree/index.go
+++ b/pkg/rtree/index.go
@@ -23,6 +23,8 @@ import (
"fmt"
"io/ioutil"
"os"
+ "os/exec"
+ "path"
"path/filepath"
"sort"
"strings"
@@ -142,12 +144,12 @@ func (i *Index) InteractiveRebuild() error {
var choice string
if len(remoteURLs) == 0 {
- choice = util.Prompt(
+ choice = util.Prompt(os.Stdout,
"no remote to restore from; (d)elete from index or (s)kip?",
[]string{"d", "s"},
)
} else {
- choice = util.Prompt(
+ choice = util.Prompt(os.Stdout,
fmt.Sprintf("(r)estore from %s, (d)elete from index, or (s)kip?", strings.Join(remoteURLs, " and ")),
[]string{"r", "d", "s"},
)
@@ -185,3 +187,111 @@ func (i *Index) InteractiveRebuild() error {
i.Repos = newRepos
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 {
+ //NOTE: This function prints *everything* on stderr, because stdout is
+ //reserved for the result path during `rtree get`.
+
+ expandedRemoteURL := ExpandRemoteURL(remoteURL)
+ basename := path.Base(expandedRemoteURL)
+
+ //is this remote already checked out directly? also look for repos with the
+ //same basename that could be forks
+ var candidates []*Repo
+ for _, repo := range i.Repos {
+ isCandidate := false
+ for _, remote := range repo.Remotes {
+ otherExpandedRemoteURL := ExpandRemoteURL(remote.URL)
+ if expandedRemoteURL == otherExpandedRemoteURL {
+ return repo
+ }
+ if basename == path.Base(otherExpandedRemoteURL) {
+ isCandidate = true
+ }
+ }
+ if isCandidate {
+ candidates = append(candidates, repo)
+ }
+ }
+
+ //double-check if the repo is already checked out, but we didn't notice it yet
+ newRepo := NewRepoFromRemoteURL(remoteURL)
+ if newRepo.ExistsOnDisk() {
+ util.FatalIfError(fmt.Errorf(
+ "%s already exists (if there is a repo there, try `rtree index`)",
+ newRepo.AbsolutePath(),
+ ))
+ }
+
+ if !allowClone {
+ return nil
+ }
+
+ //if no fork candidates found, clone as new repo
+ if len(candidates) == 0 {
+ util.FatalIfError(newRepo.Checkout())
+ i.Repos = append(i.Repos, &newRepo)
+ i.Write()
+ return &newRepo
+ }
+
+ //if we found fork candidates, ask the user to match the repo with a fork
+ //candidate (or confirm that the repo shall be cloned fresh)
+ if len(candidates) > 10 {
+ candidates = candidates[:10]
+ }
+ prompt := "Found possible fork candidates.\n"
+ for idx, repo := range candidates {
+ prompt += fmt.Sprintf("\t(%s) add as remote to %s\n", tenLetters[idx], repo.AbsolutePath())
+ }
+ prompt += fmt.Sprintf("\t(x) clone to %s\nSelect action:", newRepo.AbsolutePath())
+ choices := append([]string{"x"}, tenLetters[:len(candidates)]...)
+ choice := util.Prompt(os.Stderr, prompt, choices)
+
+ if choice == "x" {
+ util.FatalIfError(newRepo.Checkout())
+ i.Repos = append(i.Repos, &newRepo)
+ i.Write()
+ return &newRepo
+ }
+
+ //find the repo selected by the user
+ var target *Repo
+ for idx, str := range choices {
+ if choice == str {
+ target = candidates[idx-1]
+ }
+ }
+
+ //report the existing remotes, and ask for the name of the new remote
+ fmt.Fprintln(os.Stderr, "Existing remotes:")
+ for _, remote := range target.Remotes {
+ fmt.Fprintf(os.Stderr, "\t(%s) %s\n", remote.Name, remote.URL)
+ }
+ fmt.Fprintf(os.Stderr, "Enter remote name for %s: ", remoteURL)
+ remoteName := util.ReadLine()
+
+ cmd := exec.Command("git", "remote", "add", remoteName, remoteURL)
+ cmd.Stdout = os.Stderr
+ cmd.Stderr = os.Stderr
+ cmd.Dir = target.AbsolutePath()
+ util.FatalIfError(cmd.Run())
+
+ cmd = exec.Command("git", "remote", "update", remoteName)
+ cmd.Stdout = os.Stderr
+ cmd.Stderr = os.Stderr
+ cmd.Dir = target.AbsolutePath()
+ util.FatalIfError(cmd.Run())
+
+ target.Remotes = append(target.Remotes, Remote{
+ Name: remoteName,
+ URL: remoteURL,
+ })
+ i.Write()
+ return target
+}