Skip to content

Commit 85ed9df

Browse files
authored
refactor(listGoFiles): remove go list dependency (#440)
* refactor(listGoFiles): remove go list dependency * refactor to use go/build package to cover all usecases
1 parent 26cdb5c commit 85ed9df

File tree

2 files changed

+49
-29
lines changed

2 files changed

+49
-29
lines changed

internal/run.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,9 @@ func OutputDebug(cmd string, args ...string) (string, error) {
5757
return strings.TrimSpace(buf.String()), nil
5858
}
5959

60-
// splitEnv takes the results from os.Environ() (a []string of foo=bar values)
60+
// SplitEnv takes the results from os.Environ() (a []string of foo=bar values)
6161
// and makes a map[string]string out of it.
62-
func splitEnv(env []string) (map[string]string, error) {
62+
func SplitEnv(env []string) (map[string]string, error) {
6363
out := map[string]string{}
6464

6565
for _, s := range env {
@@ -85,7 +85,7 @@ func joinEnv(env map[string]string) []string {
8585
// EnvWithCurrentGOOS returns a copy of os.Environ with the GOOS and GOARCH set
8686
// to runtime.GOOS and runtime.GOARCH.
8787
func EnvWithCurrentGOOS() ([]string, error) {
88-
vals, err := splitEnv(os.Environ())
88+
vals, err := SplitEnv(os.Environ())
8989
if err != nil {
9090
return nil, err
9191
}
@@ -97,7 +97,7 @@ func EnvWithCurrentGOOS() ([]string, error) {
9797
// EnvWithGOOS retuns the os.Environ() values with GOOS and/or GOARCH either set
9898
// to their runtime value, or the given value if non-empty.
9999
func EnvWithGOOS(goos, goarch string) ([]string, error) {
100-
env, err := splitEnv(os.Environ())
100+
env, err := SplitEnv(os.Environ())
101101
if err != nil {
102102
return nil, err
103103
}

mage/main.go

Lines changed: 45 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"errors"
77
"flag"
88
"fmt"
9+
"go/build"
910
"io"
1011
"io/ioutil"
1112
"log"
@@ -468,35 +469,53 @@ type mainfileTemplateData struct {
468469
BinaryName string
469470
}
470471

471-
func listGoFiles(magePath, goCmd, tags string, env []string) ([]string, error) {
472-
args := []string{"list"}
473-
if tags != "" {
474-
args = append(args, fmt.Sprintf("-tags=%s", tags))
475-
}
476-
args = append(args, "-e", "-f", `{{join .GoFiles "||"}}`)
477-
cmd := exec.Command(goCmd, args...)
478-
cmd.Env = env
479-
buf := &bytes.Buffer{}
480-
cmd.Stderr = buf
481-
cmd.Dir = magePath
482-
b, err := cmd.Output()
472+
// listGoFiles returns a list of all .go files in a given directory,
473+
// matching the provided tag
474+
func listGoFiles(magePath, goCmd, tag string, envStr []string) ([]string, error) {
475+
origMagePath := magePath
476+
if !filepath.IsAbs(magePath) {
477+
cwd, err := os.Getwd()
478+
if err != nil {
479+
return nil, fmt.Errorf("can't get current working directory: %v", err)
480+
}
481+
magePath = filepath.Join(cwd, magePath)
482+
}
483+
484+
env, err := internal.SplitEnv(envStr)
483485
if err != nil {
484-
stderr := buf.String()
485-
// if the error is "cannot find module", that can mean that there's no
486-
// non-mage files, which is fine, so ignore it.
487-
if !strings.Contains(stderr, "cannot find module for path") {
488-
if tags == "" {
489-
return nil, fmt.Errorf("failed to list un-tagged gofiles: %v: %s", err, stderr)
490-
}
491-
return nil, fmt.Errorf("failed to list gofiles tagged with %q: %v: %s", tags, err, stderr)
486+
return nil, fmt.Errorf("error parsing environment variables: %v", err)
487+
}
488+
489+
bctx := build.Default
490+
bctx.BuildTags = []string{tag}
491+
492+
if _, ok := env["GOOS"]; ok {
493+
bctx.GOOS = env["GOOS"]
494+
}
495+
496+
if _, ok := env["GOARCH"]; ok {
497+
bctx.GOARCH = env["GOARCH"]
498+
}
499+
500+
pkg, err := bctx.Import(".", magePath, 0)
501+
if err != nil {
502+
if _, ok := err.(*build.NoGoError); ok {
503+
return []string{}, nil
504+
}
505+
506+
// Allow multiple packages in the same directory
507+
if _, ok := err.(*build.MultiplePackageError); !ok {
508+
return nil, fmt.Errorf("failed to parse go source files: %v", err)
492509
}
493510
}
494-
out := strings.TrimSpace(string(b))
495-
list := strings.Split(out, "||")
496-
for i := range list {
497-
list[i] = filepath.Join(magePath, list[i])
511+
512+
goFiles := make([]string, len(pkg.GoFiles))
513+
for i := range pkg.GoFiles {
514+
goFiles[i] = filepath.Join(origMagePath, pkg.GoFiles[i])
498515
}
499-
return list, nil
516+
517+
debug.Printf("found %d go files with build tag %s (files: %v)", len(goFiles), tag, goFiles)
518+
return goFiles, nil
500519
}
501520

502521
// Magefiles returns the list of magefiles in dir.
@@ -549,6 +568,7 @@ func Magefiles(magePath, goos, goarch, goCmd string, stderr io.Writer, isMagefil
549568
files = append(files, f)
550569
}
551570
}
571+
552572
return files, nil
553573
}
554574

0 commit comments

Comments
 (0)