From e1022c29c33363bd3c2471b7cef2d37dbd704dca Mon Sep 17 00:00:00 2001 From: Stefan Majewsky Date: Fri, 5 May 2017 19:56:30 +0200 Subject: implement rtree import --- pkg/cli/query.go | 2 +- pkg/rtree/index.go | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ pkg/rtree/main.go | 11 ++++++++++- pkg/rtree/repo.go | 36 ++++++++++++++++++++++++++++++++++++ 4 files changed, 96 insertions(+), 2 deletions(-) diff --git a/pkg/cli/query.go b/pkg/cli/query.go index d8602bc..0d367be 100644 --- a/pkg/cli/query.go +++ b/pkg/cli/query.go @@ -87,7 +87,7 @@ OUTER: selected = len(choices) - 1 } case "\x03": // Ctrl-C - fmt.Fprintf(os.Stderr, "Interrupted!") + fmt.Fprintln(os.Stderr, "Interrupted!") os.Exit(255) default: fmt.Printf("%#v\n", string(input)) diff --git a/pkg/rtree/index.go b/pkg/rtree/index.go index aa2b2a3..2edc452 100644 --- a/pkg/rtree/index.go +++ b/pkg/rtree/index.go @@ -298,3 +298,52 @@ func (i *Index) InteractiveFindRepo(remoteURL string, allowClone bool) *Repo { i.Write() return target } + +//InteractiveImportRepo moves the given repo into the rtree and adds it to the index. +func (i *Index) InteractiveImportRepo(dirPath string) { + //need to make dirPath absolute first + dirPath, err := filepath.Abs(dirPath) + util.FatalIfError(err) + repo, err := NewRepoFromAbsolutePath(dirPath) + util.FatalIfError(err) + + //repo must be outside $GOPATH/src + if !strings.HasPrefix(repo.CheckoutPath, "../") { + util.FatalIfError(fmt.Errorf("%s is already inside GOPATH", dirPath)) + } + + //select the remote which determines the checkout path + choices := make([]cli.Choice, len(repo.Remotes)) + var checkoutPath string + for idx, remote := range repo.Remotes { + thisPath := CheckoutPathForRemoteURL(ExpandRemoteURL(remote.URL)) + if remote.Name == "origin" { + //prefer "origin" over everything else + checkoutPath = thisPath + break + } + choices[idx] = cli.Choice{Text: thisPath} + } + + //cannot decide myself -> let the user select + if checkoutPath == "" { + if len(choices) == 0 { + util.FatalIfError(errors.New("repo has no remotes")) + } + + question := fmt.Sprintf("Repo has multiple remotes. Where to put below %s?", RootPath) + choice, _ := cli.Query(question, choices...) + checkoutPath = choice.Text + } + + //double-check that there is no such repo in the rtree yet + for _, other := range i.Repos { + if other.CheckoutPath == checkoutPath { + util.FatalIfError(errors.New("will not overwrite existing checkout at " + other.AbsolutePath())) + } + } + + //do the move + util.FatalIfError(repo.Move(checkoutPath, true)) + i.Repos = append(i.Repos, &repo) +} diff --git a/pkg/rtree/main.go b/pkg/rtree/main.go index 2a85ab9..4c8fb98 100644 --- a/pkg/rtree/main.go +++ b/pkg/rtree/main.go @@ -55,7 +55,10 @@ func Exec(args []string) { } commandRemotes() case "import": - panic("unimplemented") + if len(args) != 2 { + usageAndExit() + } + commandImport(args[1]) case "each": if len(args) < 2 { usageAndExit() @@ -124,3 +127,9 @@ func commandEach(command string, args []string) { os.Exit(1) } } + +func commandImport(dirPath string) { + index := ReadIndex() + index.InteractiveImportRepo(dirPath) + index.Write() +} diff --git a/pkg/rtree/repo.go b/pkg/rtree/repo.go index 93ab9d2..12f087f 100644 --- a/pkg/rtree/repo.go +++ b/pkg/rtree/repo.go @@ -226,3 +226,39 @@ func (r Repo) InteractiveExec(command string, args ...string) (ok bool) { } return true } + +//Move sets the CheckoutPath to the given value and moves the existing repo +//from the old to the new checkoutPath. If makeSymlink is given, a symlink will +//be created from the old to the new location. +func (r *Repo) Move(checkoutPath string, makeSymlink bool) error { + sourcePath := filepath.Join(RootPath, r.CheckoutPath) + targetPath := filepath.Join(RootPath, checkoutPath) + + //ensure that target does not exist + _, err := os.Lstat(targetPath) + if err == nil { + return fmt.Errorf("cannot move %s to %s: target exists in filesystem", sourcePath, targetPath) + } + if !os.IsNotExist(err) { + return err + } + + //prepare directory to move repo into + err = os.MkdirAll(filepath.Dir(targetPath), 0755) + if err != nil { + return err + } + + //move directory + err = os.Rename(sourcePath, targetPath) + if err != nil { + return err + } + r.CheckoutPath = checkoutPath + + //if requested, make compatibility symlink + if makeSymlink { + return os.Symlink(targetPath, sourcePath) + } + return nil +} -- cgit v1.3.1