go/buildutil: call ReadDir via the build.Context's file system interface
LGTM=gri R=gri, crawshaw CC=golang-codereviews https://golang.org/cl/171920043
This commit is contained in:
parent
ef648ad89b
commit
3191bbae17
|
@ -4,11 +4,13 @@
|
||||||
|
|
||||||
// Package buildutil provides utilities related to the go/build
|
// Package buildutil provides utilities related to the go/build
|
||||||
// package in the standard library.
|
// package in the standard library.
|
||||||
|
//
|
||||||
|
// All I/O is done via the build.Context file system interface, which must
|
||||||
|
// be concurrency-safe.
|
||||||
package buildutil
|
package buildutil
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"go/build"
|
"go/build"
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"sort"
|
"sort"
|
||||||
|
@ -23,7 +25,7 @@ import (
|
||||||
// The result may include import paths for directories that contain no
|
// The result may include import paths for directories that contain no
|
||||||
// *.go files, such as "archive" (in $GOROOT/src).
|
// *.go files, such as "archive" (in $GOROOT/src).
|
||||||
//
|
//
|
||||||
// All I/O is via the build.Context virtual file system,
|
// All I/O is done via the build.Context file system interface,
|
||||||
// which must be concurrency-safe.
|
// which must be concurrency-safe.
|
||||||
//
|
//
|
||||||
func AllPackages(ctxt *build.Context) []string {
|
func AllPackages(ctxt *build.Context) []string {
|
||||||
|
@ -45,7 +47,7 @@ func AllPackages(ctxt *build.Context) []string {
|
||||||
// If the package directory exists but could not be read, the second
|
// If the package directory exists but could not be read, the second
|
||||||
// argument to the found function provides the error.
|
// argument to the found function provides the error.
|
||||||
//
|
//
|
||||||
// The found function and the build.Context virtual file system
|
// The found function and the build.Context file system interface
|
||||||
// accessors must be concurrency safe.
|
// accessors must be concurrency safe.
|
||||||
//
|
//
|
||||||
func ForEachPackage(ctxt *build.Context, found func(importPath string, err error)) {
|
func ForEachPackage(ctxt *build.Context, found func(importPath string, err error)) {
|
||||||
|
@ -66,11 +68,6 @@ func ForEachPackage(ctxt *build.Context, found func(importPath string, err error
|
||||||
}
|
}
|
||||||
|
|
||||||
func allPackages(ctxt *build.Context, sema chan bool, root string, found func(string, error)) {
|
func allPackages(ctxt *build.Context, sema chan bool, root string, found func(string, error)) {
|
||||||
ReadDir := ctxt.ReadDir
|
|
||||||
if ReadDir == nil {
|
|
||||||
ReadDir = ioutil.ReadDir
|
|
||||||
}
|
|
||||||
|
|
||||||
root = filepath.Clean(root) + string(os.PathSeparator)
|
root = filepath.Clean(root) + string(os.PathSeparator)
|
||||||
|
|
||||||
var wg sync.WaitGroup
|
var wg sync.WaitGroup
|
||||||
|
@ -92,7 +89,7 @@ func allPackages(ctxt *build.Context, sema chan bool, root string, found func(st
|
||||||
}
|
}
|
||||||
|
|
||||||
sema <- true
|
sema <- true
|
||||||
files, err := ReadDir(dir)
|
files, err := ReadDir(ctxt, dir)
|
||||||
<-sema
|
<-sema
|
||||||
if pkg != "" || err != nil {
|
if pkg != "" || err != nil {
|
||||||
found(pkg, err)
|
found(pkg, err)
|
||||||
|
|
|
@ -11,6 +11,7 @@ import (
|
||||||
"go/parser"
|
"go/parser"
|
||||||
"go/token"
|
"go/token"
|
||||||
"io"
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
@ -18,7 +19,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// ParseFile behaves like parser.ParseFile,
|
// ParseFile behaves like parser.ParseFile,
|
||||||
// but uses the build context's virtual file system, if any.
|
// but uses the build context's file system interface, if any.
|
||||||
//
|
//
|
||||||
// If file is not absolute (as defined by IsAbsPath), the (dir, file)
|
// If file is not absolute (as defined by IsAbsPath), the (dir, file)
|
||||||
// components are joined using JoinPath; dir must be absolute.
|
// components are joined using JoinPath; dir must be absolute.
|
||||||
|
@ -46,7 +47,7 @@ func ParseFile(fset *token.FileSet, ctxt *build.Context, displayPath func(string
|
||||||
// ContainingPackage returns the package containing filename.
|
// ContainingPackage returns the package containing filename.
|
||||||
//
|
//
|
||||||
// If filename is not absolute, it is interpreted relative to working directory dir.
|
// If filename is not absolute, it is interpreted relative to working directory dir.
|
||||||
// All I/O is via the build context's virtual file system, if any.
|
// All I/O is via the build context's file system interface, if any.
|
||||||
//
|
//
|
||||||
// The '...Files []string' fields of the resulting build.Package are not
|
// The '...Files []string' fields of the resulting build.Package are not
|
||||||
// populated (build.FindOnly mode).
|
// populated (build.FindOnly mode).
|
||||||
|
@ -58,12 +59,12 @@ func ContainingPackage(ctxt *build.Context, dir, filename string) (*build.Packag
|
||||||
filename = JoinPath(ctxt, dir, filename)
|
filename = JoinPath(ctxt, dir, filename)
|
||||||
}
|
}
|
||||||
|
|
||||||
// We must not assume the virtualized file tree uses
|
// We must not assume the file tree uses
|
||||||
// "/" always,
|
// "/" always,
|
||||||
// `\` always,
|
// `\` always,
|
||||||
// or os.PathSeparator (which varies by platform),
|
// or os.PathSeparator (which varies by platform),
|
||||||
// but to make any progress, we are forced to assume that
|
// but to make any progress, we are forced to assume that
|
||||||
// virtualized paths will not use `\` unless the PathSeparator
|
// paths will not use `\` unless the PathSeparator
|
||||||
// is also `\`, thus we can rely on filepath.ToSlash for some sanity.
|
// is also `\`, thus we can rely on filepath.ToSlash for some sanity.
|
||||||
|
|
||||||
dirSlash := path.Dir(filepath.ToSlash(filename)) + "/"
|
dirSlash := path.Dir(filepath.ToSlash(filename)) + "/"
|
||||||
|
@ -80,10 +81,14 @@ func ContainingPackage(ctxt *build.Context, dir, filename string) (*build.Packag
|
||||||
return nil, fmt.Errorf("can't find package containing %s", filename)
|
return nil, fmt.Errorf("can't find package containing %s", filename)
|
||||||
}
|
}
|
||||||
|
|
||||||
// -- Effective methods of virtual file system -------------------------
|
// -- Effective methods of file system interface -------------------------
|
||||||
|
|
||||||
|
// (go/build.Context defines these as methods, but does not export them.)
|
||||||
|
|
||||||
|
// TODO(adonovan): HasSubdir?
|
||||||
|
|
||||||
// FileExists returns true if the specified file exists,
|
// FileExists returns true if the specified file exists,
|
||||||
// using the build context's virtual file system.
|
// using the build context's file system interface.
|
||||||
func FileExists(ctxt *build.Context, path string) bool {
|
func FileExists(ctxt *build.Context, path string) bool {
|
||||||
if ctxt.OpenFile != nil {
|
if ctxt.OpenFile != nil {
|
||||||
r, err := ctxt.OpenFile(path)
|
r, err := ctxt.OpenFile(path)
|
||||||
|
@ -98,7 +103,7 @@ func FileExists(ctxt *build.Context, path string) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
// OpenFile behaves like os.Open,
|
// OpenFile behaves like os.Open,
|
||||||
// but uses the build context's virtual file system, if any.
|
// but uses the build context's file system interface, if any.
|
||||||
func OpenFile(ctxt *build.Context, path string) (io.ReadCloser, error) {
|
func OpenFile(ctxt *build.Context, path string) (io.ReadCloser, error) {
|
||||||
if ctxt.OpenFile != nil {
|
if ctxt.OpenFile != nil {
|
||||||
return ctxt.OpenFile(path)
|
return ctxt.OpenFile(path)
|
||||||
|
@ -107,7 +112,7 @@ func OpenFile(ctxt *build.Context, path string) (io.ReadCloser, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsAbsPath behaves like filepath.IsAbs,
|
// IsAbsPath behaves like filepath.IsAbs,
|
||||||
// but uses the build context's virtual file system, if any.
|
// but uses the build context's file system interface, if any.
|
||||||
func IsAbsPath(ctxt *build.Context, path string) bool {
|
func IsAbsPath(ctxt *build.Context, path string) bool {
|
||||||
if ctxt.IsAbsPath != nil {
|
if ctxt.IsAbsPath != nil {
|
||||||
return ctxt.IsAbsPath(path)
|
return ctxt.IsAbsPath(path)
|
||||||
|
@ -116,7 +121,7 @@ func IsAbsPath(ctxt *build.Context, path string) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
// JoinPath behaves like filepath.Join,
|
// JoinPath behaves like filepath.Join,
|
||||||
// but uses the build context's virtual file system.
|
// but uses the build context's file system interface, if any.
|
||||||
func JoinPath(ctxt *build.Context, path ...string) string {
|
func JoinPath(ctxt *build.Context, path ...string) string {
|
||||||
if ctxt.JoinPath != nil {
|
if ctxt.JoinPath != nil {
|
||||||
return ctxt.JoinPath(path...)
|
return ctxt.JoinPath(path...)
|
||||||
|
@ -124,4 +129,30 @@ func JoinPath(ctxt *build.Context, path ...string) string {
|
||||||
return filepath.Join(path...)
|
return filepath.Join(path...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(adonovan): SplitPathList, IsDir, HasSubdir, ReadDir?
|
// IsDir behaves like os.Stat plus IsDir,
|
||||||
|
// but uses the build context's file system interface, if any.
|
||||||
|
func IsDir(ctxt *build.Context, path string) bool {
|
||||||
|
if ctxt.IsDir != nil {
|
||||||
|
return ctxt.IsDir(path)
|
||||||
|
}
|
||||||
|
fi, err := os.Stat(path)
|
||||||
|
return err == nil && fi.IsDir()
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReadDir behaves like ioutil.ReadDir,
|
||||||
|
// but uses the build context's file system interface, if any.
|
||||||
|
func ReadDir(ctxt *build.Context, path string) ([]os.FileInfo, error) {
|
||||||
|
if ctxt.ReadDir != nil {
|
||||||
|
return ctxt.ReadDir(path)
|
||||||
|
}
|
||||||
|
return ioutil.ReadDir(path)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SplitPathList behaves like filepath.SplitList,
|
||||||
|
// but uses the build context's file system interface, if any.
|
||||||
|
func SplitPathList(ctxt *build.Context, s string) []string {
|
||||||
|
if ctxt.SplitPathList != nil {
|
||||||
|
return ctxt.SplitPathList(s)
|
||||||
|
}
|
||||||
|
return filepath.SplitList(s)
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue