mirror of
https://github.com/golang/go
synced 2024-11-23 21:50:08 -07:00
go/build: add ctxt.MatchFile
Fixes #6369. R=dsymonds, r CC=golang-dev https://golang.org/cl/13708043
This commit is contained in:
parent
1385e394cf
commit
aa53b37fa6
@ -408,6 +408,14 @@ func (e *NoGoError) Error() string {
|
||||
return "no buildable Go source files in " + e.Dir
|
||||
}
|
||||
|
||||
func nameExt(name string) string {
|
||||
i := strings.LastIndex(name, ".")
|
||||
if i < 0 {
|
||||
return ""
|
||||
}
|
||||
return name[i:]
|
||||
}
|
||||
|
||||
// Import returns details about the Go package named by the import path,
|
||||
// interpreting local import paths relative to the srcDir directory.
|
||||
// If the path is a local import path naming a package that can be imported
|
||||
@ -591,58 +599,15 @@ Found:
|
||||
if d.IsDir() {
|
||||
continue
|
||||
}
|
||||
|
||||
name := d.Name()
|
||||
if strings.HasPrefix(name, "_") ||
|
||||
strings.HasPrefix(name, ".") {
|
||||
continue
|
||||
}
|
||||
ext := nameExt(name)
|
||||
|
||||
i := strings.LastIndex(name, ".")
|
||||
if i < 0 {
|
||||
i = len(name)
|
||||
}
|
||||
ext := name[i:]
|
||||
|
||||
if !ctxt.goodOSArchFile(name, allTags) && !ctxt.UseAllFiles {
|
||||
if ext == ".go" {
|
||||
p.IgnoredGoFiles = append(p.IgnoredGoFiles, name)
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
switch ext {
|
||||
case ".go", ".c", ".cc", ".cxx", ".cpp", ".s", ".h", ".hh", ".hpp", ".hxx", ".S", ".swig", ".swigcxx":
|
||||
// tentatively okay - read to make sure
|
||||
case ".syso":
|
||||
// binary objects to add to package archive
|
||||
// Likely of the form foo_windows.syso, but
|
||||
// the name was vetted above with goodOSArchFile.
|
||||
p.SysoFiles = append(p.SysoFiles, name)
|
||||
continue
|
||||
default:
|
||||
// skip
|
||||
continue
|
||||
}
|
||||
|
||||
filename := ctxt.joinPath(p.Dir, name)
|
||||
f, err := ctxt.openFile(filename)
|
||||
match, data, filename, err := ctxt.matchFile(p.Dir, name, true, allTags)
|
||||
if err != nil {
|
||||
return p, err
|
||||
}
|
||||
|
||||
var data []byte
|
||||
if strings.HasSuffix(filename, ".go") {
|
||||
data, err = readImports(f, false)
|
||||
} else {
|
||||
data, err = readComments(f)
|
||||
}
|
||||
f.Close()
|
||||
if err != nil {
|
||||
return p, fmt.Errorf("read %s: %v", filename, err)
|
||||
}
|
||||
|
||||
// Look for +build comments to accept or reject the file.
|
||||
if !ctxt.shouldBuild(data, allTags) && !ctxt.UseAllFiles {
|
||||
if !match {
|
||||
if ext == ".go" {
|
||||
p.IgnoredGoFiles = append(p.IgnoredGoFiles, name)
|
||||
}
|
||||
@ -672,6 +637,12 @@ Found:
|
||||
case ".swigcxx":
|
||||
p.SwigCXXFiles = append(p.SwigCXXFiles, name)
|
||||
continue
|
||||
case ".syso":
|
||||
// binary objects to add to package archive
|
||||
// Likely of the form foo_windows.syso, but
|
||||
// the name was vetted above with goodOSArchFile.
|
||||
p.SysoFiles = append(p.SysoFiles, name)
|
||||
continue
|
||||
}
|
||||
|
||||
pf, err := parser.ParseFile(fset, filename, data, parser.ImportsOnly|parser.ParseComments)
|
||||
@ -782,6 +753,79 @@ Found:
|
||||
return p, pkgerr
|
||||
}
|
||||
|
||||
// MatchFile reports whether the file with the given name in the given directory
|
||||
// matches the context and would be included in a Package created by ImportDir
|
||||
// of that directory.
|
||||
//
|
||||
// MatchFile considers the name of the file and may use ctxt.OpenFile to
|
||||
// read some or all of the file's content.
|
||||
func (ctxt *Context) MatchFile(dir, name string) (match bool, err error) {
|
||||
match, _, _, err = ctxt.matchFile(dir, name, false, nil)
|
||||
return
|
||||
}
|
||||
|
||||
// matchFile determines whether the file with the given name in the given directory
|
||||
// should be included in the package being constructed.
|
||||
// It returns the data read from the file.
|
||||
// If returnImports is true and name denotes a Go program, matchFile reads
|
||||
// until the end of the imports (and returns that data) even though it only
|
||||
// considers text until the first non-comment.
|
||||
// If allTags is non-nil, matchFile records any encountered build tag
|
||||
// by setting allTags[tag] = true.
|
||||
func (ctxt *Context) matchFile(dir, name string, returnImports bool, allTags map[string]bool) (match bool, data []byte, filename string, err error) {
|
||||
if strings.HasPrefix(name, "_") ||
|
||||
strings.HasPrefix(name, ".") {
|
||||
return
|
||||
}
|
||||
|
||||
i := strings.LastIndex(name, ".")
|
||||
if i < 0 {
|
||||
i = len(name)
|
||||
}
|
||||
ext := name[i:]
|
||||
|
||||
if !ctxt.goodOSArchFile(name, allTags) && !ctxt.UseAllFiles {
|
||||
return
|
||||
}
|
||||
|
||||
switch ext {
|
||||
case ".go", ".c", ".cc", ".cxx", ".cpp", ".s", ".h", ".hh", ".hpp", ".hxx", ".S", ".swig", ".swigcxx":
|
||||
// tentatively okay - read to make sure
|
||||
case ".syso":
|
||||
// binary, no reading
|
||||
match = true
|
||||
return
|
||||
default:
|
||||
// skip
|
||||
return
|
||||
}
|
||||
|
||||
filename = ctxt.joinPath(dir, name)
|
||||
f, err := ctxt.openFile(filename)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if strings.HasSuffix(filename, ".go") {
|
||||
data, err = readImports(f, false)
|
||||
} else {
|
||||
data, err = readComments(f)
|
||||
}
|
||||
f.Close()
|
||||
if err != nil {
|
||||
err = fmt.Errorf("read %s: %v", filename, err)
|
||||
return
|
||||
}
|
||||
|
||||
// Look for +build comments to accept or reject the file.
|
||||
if !ctxt.shouldBuild(data, allTags) && !ctxt.UseAllFiles {
|
||||
return
|
||||
}
|
||||
|
||||
match = true
|
||||
return
|
||||
}
|
||||
|
||||
func cleanImports(m map[string][]token.Position) ([]string, map[string][]token.Position) {
|
||||
all := make([]string, 0, len(m))
|
||||
for path := range m {
|
||||
@ -1114,16 +1158,22 @@ func (ctxt *Context) goodOSArchFile(name string, allTags map[string]bool) bool {
|
||||
}
|
||||
n := len(l)
|
||||
if n >= 2 && knownOS[l[n-2]] && knownArch[l[n-1]] {
|
||||
allTags[l[n-2]] = true
|
||||
allTags[l[n-1]] = true
|
||||
if allTags != nil {
|
||||
allTags[l[n-2]] = true
|
||||
allTags[l[n-1]] = true
|
||||
}
|
||||
return l[n-2] == ctxt.GOOS && l[n-1] == ctxt.GOARCH
|
||||
}
|
||||
if n >= 1 && knownOS[l[n-1]] {
|
||||
allTags[l[n-1]] = true
|
||||
if allTags != nil {
|
||||
allTags[l[n-1]] = true
|
||||
}
|
||||
return l[n-1] == ctxt.GOOS
|
||||
}
|
||||
if n >= 1 && knownArch[l[n-1]] {
|
||||
allTags[l[n-1]] = true
|
||||
if allTags != nil {
|
||||
allTags[l[n-1]] = true
|
||||
}
|
||||
return l[n-1] == ctxt.GOARCH
|
||||
}
|
||||
return true
|
||||
|
@ -5,10 +5,12 @@
|
||||
package build
|
||||
|
||||
import (
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
@ -142,3 +144,43 @@ func TestShouldBuild(t *testing.T) {
|
||||
t.Errorf("shoudBuild(file3) tags = %v, want %v", m, want3)
|
||||
}
|
||||
}
|
||||
|
||||
type readNopCloser struct {
|
||||
io.Reader
|
||||
}
|
||||
|
||||
func (r readNopCloser) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
var matchFileTests = []struct {
|
||||
name string
|
||||
data string
|
||||
match bool
|
||||
}{
|
||||
{"foo_arm.go", "", true},
|
||||
{"foo1_arm.go", "// +build linux\n\npackage main\n", false},
|
||||
{"foo_darwin.go", "", false},
|
||||
{"foo.go", "", true},
|
||||
{"foo1.go", "// +build linux\n\npackage main\n", false},
|
||||
{"foo.badsuffix", "", false},
|
||||
}
|
||||
|
||||
func TestMatchFile(t *testing.T) {
|
||||
for _, tt := range matchFileTests {
|
||||
ctxt := Context{GOARCH: "arm", GOOS: "plan9"}
|
||||
ctxt.OpenFile = func(path string) (r io.ReadCloser, err error) {
|
||||
if path != "x+"+tt.name {
|
||||
t.Fatalf("OpenFile asked for %q, expected %q", path, "x+"+tt.name)
|
||||
}
|
||||
return &readNopCloser{strings.NewReader(tt.data)}, nil
|
||||
}
|
||||
ctxt.JoinPath = func(elem ...string) string {
|
||||
return strings.Join(elem, "+")
|
||||
}
|
||||
match, err := ctxt.MatchFile("x", tt.name)
|
||||
if match != tt.match || err != nil {
|
||||
t.Fatalf("MatchFile(%q) = %v, %v, want %v, nil", tt.name, match, err, tt.match)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user