diff --git a/cmd/pkger/cmds/list.go b/cmd/pkger/cmds/list.go index c2f13dd..4d0e085 100644 --- a/cmd/pkger/cmds/list.go +++ b/cmd/pkger/cmds/list.go @@ -6,6 +6,7 @@ import ( "flag" "fmt" "os" + "path/filepath" "github.com/markbates/pkger" "github.com/markbates/pkger/internal/takeon/github.com/markbates/hepa" @@ -39,7 +40,7 @@ func (e *listCmd) Exec(args []string) error { return err } - fp := info.FilePath(outName) + fp := filepath.Join(info.Dir, outName) os.RemoveAll(fp) decls, err := parser.Parse(info) diff --git a/cmd/pkger/cmds/pack.go b/cmd/pkger/cmds/pack.go index 009500f..681f4bd 100644 --- a/cmd/pkger/cmds/pack.go +++ b/cmd/pkger/cmds/pack.go @@ -4,6 +4,7 @@ import ( "flag" "fmt" "os" + "path/filepath" "sort" "strings" @@ -30,7 +31,7 @@ func (e *packCmd) Exec(args []string) error { return err } - fp := info.FilePath(outName) + fp := filepath.Join(info.Dir, outName) os.RemoveAll(fp) decls, err := parser.Parse(info) diff --git a/here/dir.go b/here/dir.go index 379f114..809f4fa 100644 --- a/here/dir.go +++ b/here/dir.go @@ -4,14 +4,13 @@ import ( "encoding/json" "fmt" "os" - "path" "path/filepath" - "strings" ) // Dir attempts to gather info for the requested directory. func Dir(p string) (Info, error) { i, err := Cache(p, func(p string) (Info, error) { + var i Info fi, err := os.Stat(p) @@ -33,36 +32,11 @@ func Dir(p string) (Info, error) { 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 { - - 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 + return fromNonGoDir(p) } if err := json.Unmarshal(b, &i); err != nil { @@ -76,20 +50,62 @@ func Dir(p string) (Info, error) { return i, err } - Cache(i.ImportPath, func(p string) (Info, error) { + return Cache(i.ImportPath, func(p string) (Info, error) { 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 } -func prepareInfo(p string, info Info, target *Info) { - target.Module = info.Module - ph := strings.TrimPrefix(p, target.Module.Dir) +func fromNonGoDir(dir string) (Info, error) { + fmt.Println(">>>TODO here/dir.go:59: dir ", dir) + i := Info{ + Dir: dir, + } - target.ImportPath = path.Join(info.Module.Path, ph) - target.Name = path.Base(target.ImportPath) + b, err := run("go", "list", "-json", "-m") + if err != nil { + return i, err + } - ph = filepath.Join(info.Module.Dir, ph) - target.Dir = ph + if err := json.Unmarshal(b, &i.Module); err != nil { + return i, err + } + + return i, err } diff --git a/here/dir_test.go b/here/dir_test.go index 3455767..044e077 100644 --- a/here/dir_test.go +++ b/here/dir_test.go @@ -1,8 +1,11 @@ package here_test import ( + "os" + "path/filepath" "testing" + "github.com/markbates/pkger/here" "github.com/markbates/pkger/pkging/pkgtest" "github.com/stretchr/testify/require" ) @@ -13,18 +16,43 @@ func Test_Dir(t *testing.T) { ref, err := pkgtest.NewRef() 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 { in string 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 { t.Run(tt.in, func(st *testing.T) { r := require.New(st) + _, err = here.Dir(tt.in) if tt.err { r.Error(err) + return } r.NoError(err) diff --git a/here/here.go b/here/here.go index 91520c9..ad81774 100644 --- a/here/here.go +++ b/here/here.go @@ -4,6 +4,7 @@ import ( "bytes" "fmt" "os/exec" + "regexp" "sync" ) @@ -37,3 +38,11 @@ func Cache(p string, fn func(string) (Info, error)) (Info, error) { cache.Store(p, i) 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`) diff --git a/here/here_test.go b/here/here_test.go new file mode 100644 index 0000000..79da34b --- /dev/null +++ b/here/here_test.go @@ -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) + + }) + } + +} diff --git a/here/info.go b/here/info.go index 21c447b..66283ef 100644 --- a/here/info.go +++ b/here/info.go @@ -2,10 +2,6 @@ package here import ( "encoding/json" - "os" - "path/filepath" - "runtime" - "strings" ) // Info represents details about the directory/package @@ -16,15 +12,6 @@ type Info struct { 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) { mm := map[string]interface{}{ "ImportPath": i.ImportPath, @@ -36,45 +23,12 @@ func (i Info) MarshalJSON() ([]byte, error) { 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 // with rich chocolately data goodness func (i Info) IsZero() bool { 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 { b, err := json.MarshalIndent(i, "", " ") if err != nil { diff --git a/parser/parser_test.go b/parser/parser_test.go index 073bd3e..7539dbd 100644 --- a/parser/parser_test.go +++ b/parser/parser_test.go @@ -50,21 +50,18 @@ func Test_Parser_Ref(t *testing.T) { func Test_Parser_Example_HTTP(t *testing.T) { r := require.New(t) - cur, err := here.Current() + here.ClearCache() + cur, err := here.Package("github.com/markbates/pkger") r.NoError(err) - pwd, err := os.Getwd() - r.NoError(err) - defer os.Chdir(pwd) - root := filepath.Join(cur.Dir, "examples", "http", "pkger") - r.NoError(os.Chdir(root)) + defer func() { c := exec.Command("go", "mod", "tidy", "-v") c.Run() }() - her, err := here.Dir(".") + her, err := here.Dir(root) r.NoError(err) res, err := Parse(her) diff --git a/pkging/pkgtest/ref.go b/pkging/pkgtest/ref.go index fa421ad..3c1562d 100644 --- a/pkging/pkgtest/ref.go +++ b/pkging/pkgtest/ref.go @@ -17,6 +17,7 @@ type Ref struct { } func NewRef() (*Ref, error) { + here.ClearCache() her, err := here.Package("github.com/markbates/pkger") if err != nil { return nil, err