improve error testing for non go directories.

also cleans up there here.Info api
This commit is contained in:
Mark Bates 2019-11-10 18:22:06 -05:00
parent 2a9f9649bb
commit 812232aaff
9 changed files with 134 additions and 95 deletions

View File

@ -6,6 +6,7 @@ import (
"flag" "flag"
"fmt" "fmt"
"os" "os"
"path/filepath"
"github.com/markbates/pkger" "github.com/markbates/pkger"
"github.com/markbates/pkger/internal/takeon/github.com/markbates/hepa" "github.com/markbates/pkger/internal/takeon/github.com/markbates/hepa"
@ -39,7 +40,7 @@ func (e *listCmd) Exec(args []string) error {
return err return err
} }
fp := info.FilePath(outName) fp := filepath.Join(info.Dir, outName)
os.RemoveAll(fp) os.RemoveAll(fp)
decls, err := parser.Parse(info) decls, err := parser.Parse(info)

View File

@ -4,6 +4,7 @@ import (
"flag" "flag"
"fmt" "fmt"
"os" "os"
"path/filepath"
"sort" "sort"
"strings" "strings"
@ -30,7 +31,7 @@ func (e *packCmd) Exec(args []string) error {
return err return err
} }
fp := info.FilePath(outName) fp := filepath.Join(info.Dir, outName)
os.RemoveAll(fp) os.RemoveAll(fp)
decls, err := parser.Parse(info) decls, err := parser.Parse(info)

View File

@ -4,14 +4,13 @@ import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"os" "os"
"path"
"path/filepath" "path/filepath"
"strings"
) )
// Dir attempts to gather info for the requested directory. // Dir attempts to gather info for the requested directory.
func Dir(p string) (Info, error) { func Dir(p string) (Info, error) {
i, err := Cache(p, func(p string) (Info, error) { i, err := Cache(p, func(p string) (Info, error) {
var i Info var i Info
fi, err := os.Stat(p) fi, err := os.Stat(p)
@ -33,36 +32,11 @@ func Dir(p string) (Info, error) {
os.Chdir(p) os.Chdir(p)
b, err := run("go", "list", "-json") b, err := run("go", "list", "-json")
// go: cannot find main module; see 'go help modules'
// build .: cannot find module for path .
// no Go files in
if err != nil { if err != nil {
return fromNonGoDir(p)
es := err.Error()
if strings.Contains(es, "cannot find module for path .") || strings.Contains(es, "no Go files") || strings.Contains(es, "can't load package") {
if _, err := os.Stat(fmt.Sprintf("%s/go.mod", p)); err == nil {
var mod Module
bm, err := run("go", "list", "-m", "-json")
if err != nil {
return i, err
}
if err := json.Unmarshal(bm, &mod); err != nil {
return i, err
}
info := NewInfoFromPath(p, mod)
prepareInfo(p, info, &i)
return i, err
}
} else {
return i, err
}
info, err := Dir(filepath.Dir(p))
if err != nil {
return info, err
}
prepareInfo(p, info, &i)
return i, err
} }
if err := json.Unmarshal(b, &i); err != nil { if err := json.Unmarshal(b, &i); err != nil {
@ -76,20 +50,62 @@ func Dir(p string) (Info, error) {
return i, err return i, err
} }
Cache(i.ImportPath, func(p string) (Info, error) { return Cache(i.ImportPath, func(p string) (Info, error) {
return i, nil return i, nil
}) })
}
func dir(p string) (Info, error) {
var i Info
fi, err := os.Stat(p)
if err != nil {
return i, err
}
if !fi.IsDir() {
p = filepath.Dir(p)
}
pwd, err := os.Getwd()
if err != nil {
return i, err
}
defer os.Chdir(pwd)
os.Chdir(p)
b, err := run("go", "list", "-json")
// go: cannot find main module; see 'go help modules'
// build .: cannot find module for path .
// no Go files in
if err != nil {
return fromNonGoDir(p)
}
if err := json.Unmarshal(b, &i); err != nil {
return i, err
}
return i, nil return i, nil
} }
func prepareInfo(p string, info Info, target *Info) { func fromNonGoDir(dir string) (Info, error) {
target.Module = info.Module fmt.Println(">>>TODO here/dir.go:59: dir ", dir)
ph := strings.TrimPrefix(p, target.Module.Dir) i := Info{
Dir: dir,
}
target.ImportPath = path.Join(info.Module.Path, ph) b, err := run("go", "list", "-json", "-m")
target.Name = path.Base(target.ImportPath) if err != nil {
return i, err
}
ph = filepath.Join(info.Module.Dir, ph) if err := json.Unmarshal(b, &i.Module); err != nil {
target.Dir = ph return i, err
}
return i, err
} }

View File

@ -1,8 +1,11 @@
package here_test package here_test
import ( import (
"os"
"path/filepath"
"testing" "testing"
"github.com/markbates/pkger/here"
"github.com/markbates/pkger/pkging/pkgtest" "github.com/markbates/pkger/pkging/pkgtest"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
@ -13,18 +16,43 @@ func Test_Dir(t *testing.T) {
ref, err := pkgtest.NewRef() ref, err := pkgtest.NewRef()
r.NoError(err) r.NoError(err)
root := ref.Dir
r.NoError(err)
defer os.RemoveAll(root)
public := filepath.Join(root, "public")
r.NoError(os.MkdirAll(public, 0755))
gf := filepath.Join(root, "cmd", "main.go")
r.NoError(os.MkdirAll(filepath.Dir(gf), 0755))
f, err := os.Create(gf)
r.NoError(err)
_, err = f.Write([]byte("package main"))
r.NoError(err)
r.NoError(f.Close())
table := []struct { table := []struct {
in string in string
err bool err bool
}{ }{
{in: ref.Dir, err: false}, {in: root, err: false},
{in: public, err: false},
{in: gf, err: false},
{in: filepath.Join(root, "."), err: false},
{in: "/unknown", err: true},
} }
for _, tt := range table { for _, tt := range table {
t.Run(tt.in, func(st *testing.T) { t.Run(tt.in, func(st *testing.T) {
r := require.New(st) r := require.New(st)
_, err = here.Dir(tt.in)
if tt.err { if tt.err {
r.Error(err) r.Error(err)
return
} }
r.NoError(err) r.NoError(err)

View File

@ -4,6 +4,7 @@ import (
"bytes" "bytes"
"fmt" "fmt"
"os/exec" "os/exec"
"regexp"
"sync" "sync"
) )
@ -37,3 +38,11 @@ func Cache(p string, fn func(string) (Info, error)) (Info, error) {
cache.Store(p, i) cache.Store(p, i)
return i, nil return i, nil
} }
func ClearCache() {
cache = &infoMap{
data: &sync.Map{},
}
}
var nonGoDirRx = regexp.MustCompile(`cannot find main|go help modules|go: |build .:|no Go files`)

32
here/here_test.go Normal file
View File

@ -0,0 +1,32 @@
package here
import (
"testing"
"github.com/stretchr/testify/require"
)
func Test_nonGoDirRx(t *testing.T) {
r := require.New(t)
r.False(nonGoDirRx.MatchString(""))
r.False(nonGoDirRx.MatchString("hello"))
table := []string{
"go: cannot find main module; see 'go help modules'",
"go help modules",
"go: ",
"build .:",
"no Go files",
}
for _, tt := range table {
t.Run(tt, func(st *testing.T) {
r := require.New(st)
b := nonGoDirRx.MatchString(tt)
r.True(b)
})
}
}

View File

@ -2,10 +2,6 @@ package here
import ( import (
"encoding/json" "encoding/json"
"os"
"path/filepath"
"runtime"
"strings"
) )
// Info represents details about the directory/package // Info represents details about the directory/package
@ -16,15 +12,6 @@ type Info struct {
Module Module Module Module
} }
// NewInfoFromPath initialize a Info with a basic information and his module
// this method could be used when the Unmarshal information is not possible
func NewInfoFromPath(path string, m Module) Info {
return Info{
Dir: path,
Module: m,
}
}
func (i Info) MarshalJSON() ([]byte, error) { func (i Info) MarshalJSON() ([]byte, error) {
mm := map[string]interface{}{ mm := map[string]interface{}{
"ImportPath": i.ImportPath, "ImportPath": i.ImportPath,
@ -36,45 +23,12 @@ func (i Info) MarshalJSON() ([]byte, error) {
return json.Marshal(mm) return json.Marshal(mm)
} }
func (i Info) FilePath(paths ...string) string {
res := []string{i.Dir}
for _, p := range paths {
p = strings.TrimPrefix(p, i.Dir)
p = strings.TrimPrefix(p, "/")
if runtime.GOOS == "windows" {
p = strings.Replace(p, "/", "\\", -1)
}
res = append(res, p)
}
return filepath.Join(res...)
}
func (i Info) Open(p string) (*os.File, error) {
return os.Open(i.FilePath(p))
}
// ModuleName returns the name of the current
// module, or if not using modules, the current
// package. These *might* not match.
func (i Info) ModuleName() string {
if i.Mods() {
return i.Module.Path
}
return i.ImportPath
}
// IsZero checks if the type has been filled // IsZero checks if the type has been filled
// with rich chocolately data goodness // with rich chocolately data goodness
func (i Info) IsZero() bool { func (i Info) IsZero() bool {
return i.String() == Info{}.String() return i.String() == Info{}.String()
} }
// Mods returns whether Go modules are used
// in this directory/package.
func (i Info) Mods() bool {
return !i.Module.IsZero()
}
func (i Info) String() string { func (i Info) String() string {
b, err := json.MarshalIndent(i, "", " ") b, err := json.MarshalIndent(i, "", " ")
if err != nil { if err != nil {

View File

@ -50,21 +50,18 @@ func Test_Parser_Ref(t *testing.T) {
func Test_Parser_Example_HTTP(t *testing.T) { func Test_Parser_Example_HTTP(t *testing.T) {
r := require.New(t) r := require.New(t)
cur, err := here.Current() here.ClearCache()
cur, err := here.Package("github.com/markbates/pkger")
r.NoError(err) r.NoError(err)
pwd, err := os.Getwd()
r.NoError(err)
defer os.Chdir(pwd)
root := filepath.Join(cur.Dir, "examples", "http", "pkger") root := filepath.Join(cur.Dir, "examples", "http", "pkger")
r.NoError(os.Chdir(root))
defer func() { defer func() {
c := exec.Command("go", "mod", "tidy", "-v") c := exec.Command("go", "mod", "tidy", "-v")
c.Run() c.Run()
}() }()
her, err := here.Dir(".") her, err := here.Dir(root)
r.NoError(err) r.NoError(err)
res, err := Parse(her) res, err := Parse(her)

View File

@ -17,6 +17,7 @@ type Ref struct {
} }
func NewRef() (*Ref, error) { func NewRef() (*Ref, error) {
here.ClearCache()
her, err := here.Package("github.com/markbates/pkger") her, err := here.Package("github.com/markbates/pkger")
if err != nil { if err != nil {
return nil, err return nil, err