interp: support another vendoring case

This commit is contained in:
mpl
2020-07-01 10:44:03 +02:00
committed by GitHub
parent 55f2fe396a
commit 4f3481b55c
6 changed files with 142 additions and 17 deletions

View File

@@ -0,0 +1,17 @@
package pkg
import (
"fmt"
"guthib.com/containous/fromage"
)
func Here() string {
return "root"
}
func NewSample() func() string {
return func() string {
return fmt.Sprintf("%s %s", Here(), fromage.Hello())
}
}

View File

@@ -0,0 +1,7 @@
package fromage
import "fmt"
func Hello() string {
return fmt.Sprint("Fromage")
}

View File

@@ -0,0 +1,11 @@
package main
import (
"fmt"
"guthib.com/containous/fromage"
)
func main() {
fmt.Print(fromage.Hello())
}

View File

@@ -0,0 +1,7 @@
package fromage
import "fmt"
func Hello() string {
return fmt.Sprint("Fromage")
}

View File

@@ -1,6 +1,11 @@
package pkg
import (
"bytes"
"fmt"
"io"
"io/ioutil"
"os"
"path/filepath"
"testing"
@@ -10,9 +15,11 @@ import (
func TestPackages(t *testing.T) {
testCases := []struct {
desc string
goPath string
expected string
desc string
goPath string
expected string
topImport string
evalFile string
}{
{
desc: "vendor",
@@ -64,6 +71,18 @@ func TestPackages(t *testing.T) {
goPath: "./_pkg8/",
expected: "root Fromage!",
},
{
desc: "at the project root",
goPath: "./_pkg10/",
expected: "root Fromage",
topImport: "github.com/foo",
},
{
desc: "eval main that has vendored dep",
goPath: "./_pkg11/",
expected: "Fromage",
evalFile: "./_pkg11/src/foo/foo.go",
},
}
for _, test := range testCases {
@@ -78,20 +97,61 @@ func TestPackages(t *testing.T) {
i := interp.New(interp.Options{GoPath: goPath})
i.Use(stdlib.Symbols) // Use binary standard library
// Load pkg from sources
if _, err = i.Eval(`import "github.com/foo/pkg"`); err != nil {
t.Fatal(err)
var msg string
if test.evalFile != "" {
// setting i.Name as this is how it's actually done in cmd/yaegi
i.Name = test.evalFile
data, err := ioutil.ReadFile(test.evalFile)
if err != nil {
t.Fatal(err)
}
// TODO(mpl): this is brittle if we do concurrent tests and stuff, do better later.
stdout := os.Stdout
defer func() { os.Stdout = stdout }()
pr, pw, err := os.Pipe()
if err != nil {
t.Fatal(err)
}
os.Stdout = pw
if _, err := i.Eval(string(data)); err != nil {
t.Fatal(err)
}
var buf bytes.Buffer
errC := make(chan error)
go func() {
_, err := io.Copy(&buf, pr)
errC <- err
}()
if err := pw.Close(); err != nil {
t.Fatal(err)
}
if err := <-errC; err != nil {
t.Fatal(err)
}
msg = buf.String()
} else {
// Load pkg from sources
topImport := "github.com/foo/pkg"
if test.topImport != "" {
topImport = test.topImport
}
if _, err = i.Eval(fmt.Sprintf(`import "%s"`, topImport)); err != nil {
t.Fatal(err)
}
value, err := i.Eval(`pkg.NewSample()`)
if err != nil {
t.Fatal(err)
}
fn := value.Interface().(func() string)
msg = fn()
}
value, err := i.Eval(`pkg.NewSample()`)
if err != nil {
t.Fatal(err)
}
fn := value.Interface().(func() string)
msg := fn()
if msg != test.expected {
t.Errorf("Got %q, want %q", msg, test.expected)
}

View File

@@ -26,8 +26,14 @@ func (interp *Interpreter) importSrc(rPath, path string) (string, error) {
rPath = "."
}
dir = filepath.Join(filepath.Dir(interp.Name), rPath, path)
} else if dir, rPath, err = pkgDir(interp.context.GOPATH, rPath, path); err != nil {
return "", err
} else {
root, err := interp.rootFromSourceLocation(rPath)
if err != nil {
return "", err
}
if dir, rPath, err = pkgDir(interp.context.GOPATH, root, path); err != nil {
return "", err
}
}
if interp.rdir[path] {
@@ -138,6 +144,23 @@ func (interp *Interpreter) importSrc(rPath, path string) (string, error) {
return pkgName, nil
}
func (interp *Interpreter) rootFromSourceLocation(rPath string) (string, error) {
sourceFile := interp.Name
if rPath != "main" || !strings.HasSuffix(sourceFile, ".go") {
return rPath, nil
}
wd, err := os.Getwd()
if err != nil {
return "", err
}
pkgDir := filepath.Join(wd, filepath.Dir(sourceFile))
root := strings.TrimPrefix(pkgDir, filepath.Join(interp.context.GOPATH, "src")+"/")
if root == wd {
return "", fmt.Errorf("package location %s not in GOPATH", pkgDir)
}
return root, nil
}
// pkgDir returns the absolute path in filesystem for a package given its name and
// the root of the subtree dependencies.
func pkgDir(goPath string, root, path string) (string, string, error) {