Adds -include flag and pkger.Include directive fixes #28

This commit is contained in:
Mark Bates 2019-11-11 16:01:05 -05:00
parent 1a3cb0f04d
commit 7ee0500044
16 changed files with 212 additions and 47 deletions

View File

@ -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:

View File

@ -1,5 +1,3 @@
// +build !debug
package pkger
import (

View File

@ -16,9 +16,10 @@ import (
type listCmd struct {
*flag.FlagSet
help bool
json bool
subs []command
help bool
json bool
include slice
subs []command
}
func (e *listCmd) Name() string {
@ -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

View File

@ -14,13 +14,25 @@ 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
subs []command
out string
help bool
include slice
subs []command
}
func (e *packCmd) Name() string {
@ -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)()

View File

@ -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)

View File

@ -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

View File

@ -2,8 +2,7 @@ package here
import (
"encoding/json"
"path"
"strings"
"fmt"
)
// Package attempts to gather info for the requested package.
@ -18,14 +17,12 @@ 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)
return i, err
}
if err := json.Unmarshal(b, &i); err != nil {
return i, err

57
parser/include.go Normal file
View File

@ -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)
}

View File

@ -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)

View 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
}

View File

@ -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 {

View File

@ -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{

View File

@ -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) {}

View File

@ -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 => ../../../../

View File

@ -12,6 +12,7 @@ import (
)
func main() {
pkger.Include("/web")
if err := run(); err != nil {
log.Fatal(err)
}

View File

@ -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{}