diff --git a/.gitignore b/.gitignore index 0cc6ddfa7..bedafd4cd 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ dist/ vendor coverage.txt goreleaser +debug.test diff --git a/pipeline/build/build.go b/pipeline/build/build.go index dbb106de6..2161583fd 100644 --- a/pipeline/build/build.go +++ b/pipeline/build/build.go @@ -4,7 +4,9 @@ package build import ( "fmt" - "io/ioutil" + "go/ast" + "go/parser" + "go/token" "os" "os/exec" "path/filepath" @@ -16,7 +18,6 @@ import ( "github.com/goreleaser/goreleaser/internal/buildtarget" "github.com/goreleaser/goreleaser/internal/ext" "github.com/goreleaser/goreleaser/internal/name" - zglob "github.com/mattn/go-zglob" "github.com/pkg/errors" "golang.org/x/sync/errgroup" ) @@ -44,25 +45,26 @@ func (Pipe) Run(ctx *context.Context) error { } func checkMain(ctx *context.Context, build config.Build) error { - var glob = build.Main - if !strings.HasSuffix(glob, "main.go") { - // TODO: in real live , glob will never be empty. Maybe this is worth - // guarding here anyway - glob = glob + "/" + "*.go" + var dir = strings.Replace(build.Main, "main.go", "", -1) + if dir == "" { + dir = "." } - log.Debugf("glob is %s", glob) - files, err := zglob.Glob(glob) + packs, err := parser.ParseDir(token.NewFileSet(), dir, nil, 0) if err != nil { - return errors.Wrap(err, "failed to find go files") + return errors.Wrapf(err, "failed dir: %s", dir) } - log.WithField("files", files).Debug("go files") - for _, file := range files { - bts, err := ioutil.ReadFile(file) - if err != nil { - return errors.Wrapf(err, "failed to read file: %s", file) - } - if strings.Contains(string(bts), "func main() {") { - return nil + for _, pack := range packs { + for _, file := range pack.Files { + for _, decl := range file.Decls { + fn, ok := decl.(*ast.FuncDecl) + if !ok { + continue + } + log.Info(fn.Name.Name) + if fn.Name.Name == "main" && fn.Recv == nil { + return nil + } + } } } return fmt.Errorf("build for %s does not contain a main function", build.Binary) diff --git a/pipeline/build/build_test.go b/pipeline/build/build_test.go index b20022c92..d99171e03 100644 --- a/pipeline/build/build_test.go +++ b/pipeline/build/build_test.go @@ -234,35 +234,33 @@ func TestRunInvalidLdflags(t *testing.T) { } func TestRunPipeFailingHooks(t *testing.T) { - prepare := func() *context.Context { - folder, back := testlib.Mktmp(t) - defer back() - writeGoodMain(t, folder) - var config = config.Project{ - Dist: folder, - Builds: []config.Build{ - { - Main: ".", - Binary: "hooks", - Hooks: config.Hooks{}, - Goos: []string{ - runtime.GOOS, - }, - Goarch: []string{ - runtime.GOARCH, - }, + folder, back := testlib.Mktmp(t) + defer back() + writeGoodMain(t, folder) + var config = config.Project{ + Dist: folder, + Builds: []config.Build{ + { + Binary: "hooks", + Hooks: config.Hooks{}, + Goos: []string{ + runtime.GOOS, + }, + Goarch: []string{ + runtime.GOARCH, }, }, - } - return context.New(config) + }, } t.Run("pre-hook", func(t *testing.T) { - var ctx = prepare() + var ctx = context.New(config) ctx.Config.Builds[0].Hooks.Pre = "exit 1" + ctx.Config.Builds[0].Hooks.Post = "echo post" assert.EqualError(t, Pipe{}.Run(ctx), `pre hook failed: `) }) t.Run("post-hook", func(t *testing.T) { - var ctx = prepare() + var ctx = context.New(config) + ctx.Config.Builds[0].Hooks.Pre = "echo pre" ctx.Config.Builds[0].Hooks.Post = "exit 1" assert.EqualError(t, Pipe{}.Run(ctx), `post hook failed: `) }) @@ -288,6 +286,10 @@ func TestRunPipeWithouMainFunc(t *testing.T) { }, } var ctx = context.New(config) + t.Run("empty", func(t *testing.T) { + ctx.Config.Builds[0].Main = "" + assert.EqualError(t, Pipe{}.Run(ctx), `build for no-main does not contain a main function`) + }) t.Run("glob", func(t *testing.T) { ctx.Config.Builds[0].Main = "." assert.EqualError(t, Pipe{}.Run(ctx), `build for no-main does not contain a main function`) @@ -304,11 +306,11 @@ func exists(file string) bool { } func writeMainWithoutMainFunc(t *testing.T, folder string) { - writeFile(t, folder, "package main\nfunc notMain() {println(0)}") + writeFile(t, folder, "package main\nconst a = 2\nfunc notMain() {println(0)}") } func writeGoodMain(t *testing.T, folder string) { - writeFile(t, folder, "package main\nfunc main() {println(0)}") + writeFile(t, folder, "package main\nvar a = 1\nfunc main() {println(0)}") } func writeFile(t *testing.T, folder, content string) {