mirror of https://github.com/markbates/pkger.git
Adds -include flag and pkger.Include directive fixes #28
This commit is contained in:
parent
1a3cb0f04d
commit
7ee0500044
2
Makefile
2
Makefile
|
@ -17,7 +17,7 @@ build: tidy
|
|||
make tidy
|
||||
|
||||
test: tidy
|
||||
$(GO_BIN) test -count 1 -cover -tags ${TAGS} -timeout 10s ./...
|
||||
$(GO_BIN) test -count 1 -cover -tags ${TAGS} -timeout 1m ./...
|
||||
make tidy
|
||||
|
||||
cov:
|
||||
|
|
|
@ -18,6 +18,7 @@ type listCmd struct {
|
|||
*flag.FlagSet
|
||||
help bool
|
||||
json bool
|
||||
include slice
|
||||
subs []command
|
||||
}
|
||||
|
||||
|
@ -43,7 +44,7 @@ func (e *listCmd) Exec(args []string) error {
|
|||
fp := filepath.Join(info.Dir, outName)
|
||||
os.RemoveAll(fp)
|
||||
|
||||
decls, err := parser.Parse(info)
|
||||
decls, err := parser.Parse(info, e.include...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -93,6 +94,7 @@ func (e *listCmd) Flags() *flag.FlagSet {
|
|||
if e.FlagSet == nil {
|
||||
e.FlagSet = flag.NewFlagSet("list", flag.ExitOnError)
|
||||
e.BoolVar(&e.json, "json", false, "prints in JSON format")
|
||||
e.Var(&e.include, "include", "packages the specified file or directory")
|
||||
}
|
||||
e.Usage = Usage(os.Stderr, e.FlagSet)
|
||||
return e.FlagSet
|
||||
|
|
|
@ -14,12 +14,24 @@ import (
|
|||
"github.com/markbates/pkger/pkging/pkgutil"
|
||||
)
|
||||
|
||||
type slice []string
|
||||
|
||||
func (i slice) String() string {
|
||||
return fmt.Sprintf("%s", []string(i))
|
||||
}
|
||||
|
||||
func (i *slice) Set(value string) error {
|
||||
*i = append(*i, value)
|
||||
return nil
|
||||
}
|
||||
|
||||
const outName = "pkged.go"
|
||||
|
||||
type packCmd struct {
|
||||
*flag.FlagSet
|
||||
out string
|
||||
help bool
|
||||
include slice
|
||||
subs []command
|
||||
}
|
||||
|
||||
|
@ -36,7 +48,7 @@ func (e *packCmd) Exec(args []string) error {
|
|||
fp := filepath.Join(info.Dir, e.out, outName)
|
||||
os.RemoveAll(fp)
|
||||
|
||||
decls, err := parser.Parse(info)
|
||||
decls, err := parser.Parse(info, e.include...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -92,6 +104,7 @@ func New() (*packCmd, error) {
|
|||
c.FlagSet = flag.NewFlagSet("pkger", flag.ExitOnError)
|
||||
c.BoolVar(&c.help, "h", false, "prints help information")
|
||||
c.StringVar(&c.out, "o", "", "output directory for pkged.go")
|
||||
c.Var(&c.include, "include", "packages the specified file or directory")
|
||||
c.Usage = func() {
|
||||
fmt.Fprintf(os.Stderr, "Usage:\n\n")
|
||||
Usage(os.Stderr, c.FlagSet)()
|
||||
|
|
|
@ -10,7 +10,7 @@ import (
|
|||
|
||||
func main() {
|
||||
clean := func() {
|
||||
c := exec.Command("go", "mod", "tidy", "-v")
|
||||
c := exec.Command("go", "mod", "tidy")
|
||||
c.Stdout = os.Stdout
|
||||
c.Stderr = os.Stderr
|
||||
c.Stdin = os.Stdin
|
||||
|
@ -18,6 +18,13 @@ func main() {
|
|||
}
|
||||
defer clean()
|
||||
|
||||
defer func() {
|
||||
if err := recover(); err != nil {
|
||||
clean()
|
||||
log.Fatal(err)
|
||||
}
|
||||
}()
|
||||
|
||||
if err := run(); err != nil {
|
||||
clean()
|
||||
log.Fatal(err)
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
"fmt"
|
||||
"os/exec"
|
||||
"regexp"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
|
@ -20,7 +21,7 @@ func run(n string, args ...string) ([]byte, error) {
|
|||
c.Stderr = bb
|
||||
err := c.Run()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: %s", err, bb)
|
||||
return nil, fmt.Errorf("%w: %q: %s", err, strings.Join(c.Args, " "), bb)
|
||||
}
|
||||
|
||||
return bb.Bytes(), nil
|
||||
|
|
11
here/pkg.go
11
here/pkg.go
|
@ -2,8 +2,7 @@ package here
|
|||
|
||||
import (
|
||||
"encoding/json"
|
||||
"path"
|
||||
"strings"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// Package attempts to gather info for the requested package.
|
||||
|
@ -18,15 +17,13 @@ import (
|
|||
func Package(p string) (Info, error) {
|
||||
i, err := Cache(p, func(p string) (Info, error) {
|
||||
var i Info
|
||||
if len(p) == 0 || p == "." {
|
||||
return i, fmt.Errorf("missing package name")
|
||||
}
|
||||
b, err := run("go", "list", "-json", "-find", p)
|
||||
if err != nil {
|
||||
if !strings.Contains(err.Error(), "can't load package: package") {
|
||||
return i, err
|
||||
}
|
||||
|
||||
p, _ = path.Split(p)
|
||||
return Package(p)
|
||||
}
|
||||
if err := json.Unmarshal(b, &i); err != nil {
|
||||
return i, err
|
||||
}
|
||||
|
|
|
@ -0,0 +1,57 @@
|
|||
package parser
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"go/token"
|
||||
"os"
|
||||
)
|
||||
|
||||
var _ Decl = IncludeDecl{}
|
||||
|
||||
type IncludeDecl struct {
|
||||
file *File
|
||||
pos token.Position
|
||||
value string
|
||||
}
|
||||
|
||||
func (d IncludeDecl) String() string {
|
||||
return fmt.Sprintf("pkger.Include(%q)", d.value)
|
||||
}
|
||||
|
||||
func (d IncludeDecl) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(map[string]interface{}{
|
||||
"type": "pkger.Include",
|
||||
"file": d.file,
|
||||
"pos": d.pos,
|
||||
"value": d.value,
|
||||
})
|
||||
}
|
||||
|
||||
func (d IncludeDecl) File() (*File, error) {
|
||||
if d.file == nil {
|
||||
return nil, os.ErrNotExist
|
||||
}
|
||||
return d.file, nil
|
||||
}
|
||||
|
||||
func (d IncludeDecl) Position() (token.Position, error) {
|
||||
return d.pos, nil
|
||||
}
|
||||
|
||||
func (d IncludeDecl) Value() (string, error) {
|
||||
if d.value == "" {
|
||||
return "", os.ErrNotExist
|
||||
}
|
||||
return d.value, nil
|
||||
}
|
||||
|
||||
func (d IncludeDecl) Files(virtual map[string]string) ([]*File, error) {
|
||||
od := OpenDecl{
|
||||
file: d.file,
|
||||
pos: d.pos,
|
||||
value: d.value,
|
||||
}
|
||||
|
||||
return od.Files(virtual)
|
||||
}
|
|
@ -70,6 +70,7 @@ func (d OpenDecl) Files(virtual map[string]string) ([]*File, error) {
|
|||
}
|
||||
return wd.Files(virtual)
|
||||
}
|
||||
|
||||
var files []*File
|
||||
files = append(files, d.file)
|
||||
|
||||
|
|
|
@ -16,15 +16,32 @@ import (
|
|||
|
||||
var defaultIgnoredFolders = []string{".", "_", "vendor", "node_modules", "testdata"}
|
||||
|
||||
func Parse(her here.Info) (Decls, error) {
|
||||
func New(her here.Info) (*Parser, error) {
|
||||
return &Parser{
|
||||
Info: her,
|
||||
decls: map[string]Decls{},
|
||||
}, nil
|
||||
}
|
||||
|
||||
type Parser struct {
|
||||
here.Info
|
||||
decls map[string]Decls
|
||||
once sync.Once
|
||||
includes []string
|
||||
err error
|
||||
}
|
||||
|
||||
func Parse(her here.Info, includes ...string) (Decls, error) {
|
||||
p, err := New(her)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
p.includes = includes
|
||||
|
||||
return p.Decls()
|
||||
}
|
||||
|
||||
func ParseSource(source Source, mode parser.Mode) (*ParsedSource, error) {
|
||||
func (p *Parser) ParseSource(source Source, mode parser.Mode) (*ParsedSource, error) {
|
||||
pf := &ParsedSource{
|
||||
Source: source,
|
||||
FileSet: token.NewFileSet(),
|
||||
|
@ -45,7 +62,7 @@ func ParseSource(source Source, mode parser.Mode) (*ParsedSource, error) {
|
|||
return pf, nil
|
||||
}
|
||||
|
||||
func ParseFile(abs string, mode parser.Mode) (*ParsedSource, error) {
|
||||
func (p *Parser) ParseFile(abs string, mode parser.Mode) (*ParsedSource, error) {
|
||||
s := Source{
|
||||
Abs: abs,
|
||||
}
|
||||
|
@ -68,10 +85,10 @@ func ParseFile(abs string, mode parser.Mode) (*ParsedSource, error) {
|
|||
|
||||
s.Path, err = s.Here.Parse(strings.TrimPrefix(abs, dir))
|
||||
|
||||
return ParseSource(s, 0)
|
||||
return p.ParseSource(s, 0)
|
||||
}
|
||||
|
||||
func ParseDir(abs string, mode parser.Mode) ([]*ParsedSource, error) {
|
||||
func (p *Parser) ParseDir(abs string, mode parser.Mode) ([]*ParsedSource, error) {
|
||||
info, err := os.Stat(abs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -116,19 +133,6 @@ func ParseDir(abs string, mode parser.Mode) ([]*ParsedSource, error) {
|
|||
|
||||
return srcs, nil
|
||||
}
|
||||
func New(her here.Info) (*Parser, error) {
|
||||
return &Parser{
|
||||
Info: her,
|
||||
decls: map[string]Decls{},
|
||||
}, nil
|
||||
}
|
||||
|
||||
type Parser struct {
|
||||
here.Info
|
||||
decls map[string]Decls
|
||||
once sync.Once
|
||||
err error
|
||||
}
|
||||
|
||||
func (p *Parser) Decls() (Decls, error) {
|
||||
if err := p.parse(); err != nil {
|
||||
|
@ -139,6 +143,7 @@ func (p *Parser) Decls() (Decls, error) {
|
|||
orderedNames := []string{
|
||||
"MkdirAll",
|
||||
"Create",
|
||||
"Include",
|
||||
"Stat",
|
||||
"Open",
|
||||
"Dir",
|
||||
|
@ -166,12 +171,18 @@ func (p *Parser) Parse() error {
|
|||
|
||||
func (p *Parser) parse() error {
|
||||
p.decls = map[string]Decls{}
|
||||
|
||||
root := p.Dir
|
||||
|
||||
if err := p.parseIncludes(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fi, err := os.Stat(root)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !fi.IsDir() {
|
||||
return fmt.Errorf("%q is not a directory", root)
|
||||
}
|
||||
|
@ -192,7 +203,7 @@ func (p *Parser) parse() error {
|
|||
}
|
||||
}
|
||||
|
||||
srcs, err := ParseDir(path, 0)
|
||||
srcs, err := p.ParseDir(path, 0)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%w: %s", err, path)
|
||||
}
|
||||
|
@ -212,3 +223,33 @@ func (p *Parser) parse() error {
|
|||
|
||||
return err
|
||||
}
|
||||
|
||||
func (p *Parser) parseIncludes() error {
|
||||
for _, i := range p.includes {
|
||||
pt, err := p.Info.Parse(i)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
her := p.Info
|
||||
if pt.Pkg != her.ImportPath {
|
||||
her, err = here.Package(pt.Pkg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
abs := filepath.Join(her.Module.Dir, pt.Name)
|
||||
|
||||
f := &File{
|
||||
Abs: abs,
|
||||
Path: pt,
|
||||
Here: her,
|
||||
}
|
||||
p.decls["Include"] = append(p.decls["Include"], IncludeDecl{
|
||||
value: i,
|
||||
file: f,
|
||||
})
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -36,7 +36,46 @@ func Test_Parser_Ref(t *testing.T) {
|
|||
|
||||
files, err := res.Files()
|
||||
r.NoError(err)
|
||||
r.Len(files, 23)
|
||||
r.Len(files, 25)
|
||||
|
||||
for _, f := range files {
|
||||
if f.Path.Pkg == ref.Module.Path {
|
||||
r.True(strings.HasPrefix(f.Abs, ref.Dir), "%q %q", f.Abs, ref.Dir)
|
||||
} else {
|
||||
r.False(strings.HasPrefix(f.Abs, ref.Dir), "%q %q", f.Abs, ref.Dir)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func Test_Parser_Ref_Include(t *testing.T) {
|
||||
defer func() {
|
||||
c := exec.Command("go", "mod", "tidy", "-v")
|
||||
c.Run()
|
||||
}()
|
||||
r := require.New(t)
|
||||
|
||||
here.ClearCache()
|
||||
ref, err := pkgtest.NewRef()
|
||||
r.NoError(err)
|
||||
defer os.RemoveAll(ref.Dir)
|
||||
|
||||
disk, err := stdos.New(ref.Info)
|
||||
r.NoError(err)
|
||||
|
||||
_, err = pkgtest.LoadFiles("/", ref, disk)
|
||||
r.NoError(err)
|
||||
|
||||
res, err := Parse(ref.Info, "github.com/gobuffalo/buffalo:/app.go")
|
||||
|
||||
r.NoError(err)
|
||||
|
||||
files, err := res.Files()
|
||||
r.NoError(err)
|
||||
// t.FailNow()
|
||||
|
||||
l := len(files)
|
||||
r.Equal(26, l)
|
||||
// r.Len(files, 27)
|
||||
|
||||
for _, f := range files {
|
||||
if f.Path.Pkg == ref.Module.Path {
|
||||
|
|
|
@ -88,6 +88,14 @@ func (p *ParsedSource) parse() error {
|
|||
value: value,
|
||||
}
|
||||
}
|
||||
case "Include":
|
||||
fn = func(f File, pos token.Position, value string) Decl {
|
||||
return IncludeDecl{
|
||||
file: &f,
|
||||
pos: pos,
|
||||
value: value,
|
||||
}
|
||||
}
|
||||
case "Stat":
|
||||
fn = func(f File, pos token.Position, value string) Decl {
|
||||
return StatDecl{
|
||||
|
|
3
pkger.go
3
pkger.go
|
@ -95,3 +95,6 @@ func Remove(name string) error {
|
|||
func RemoveAll(name string) error {
|
||||
return impl().RemoveAll(name)
|
||||
}
|
||||
|
||||
// Include is a no-op that directs the pkger tool to include the desired file or folder.
|
||||
func Include(name string) {}
|
||||
|
|
|
@ -2,9 +2,6 @@ module app
|
|||
|
||||
go 1.13
|
||||
|
||||
require (
|
||||
github.com/gobuffalo/buffalo v0.15.0 // indirect
|
||||
github.com/markbates/pkger v0.0.0
|
||||
)
|
||||
require github.com/markbates/pkger v0.0.0
|
||||
|
||||
replace github.com/markbates/pkger => ../../../../
|
||||
|
|
|
@ -12,6 +12,7 @@ import (
|
|||
)
|
||||
|
||||
func main() {
|
||||
pkger.Include("/web")
|
||||
if err := run(); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@ func Test_Stuff(t *testing.T) {
|
|||
decls, err := parser.Parse(ref.Info)
|
||||
r.NoError(err)
|
||||
|
||||
r.Len(decls, 10)
|
||||
r.Len(decls, 11)
|
||||
|
||||
files, err := decls.Files()
|
||||
r.NoError(err)
|
||||
|
@ -42,7 +42,7 @@ func Test_Stuff(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
r.Len(files, 23)
|
||||
r.Len(files, 25)
|
||||
|
||||
bb := &bytes.Buffer{}
|
||||
|
||||
|
|
Loading…
Reference in New Issue