435c0d9fc8
This PR switches the Nomad repository from using govendor to Go modules for managing dependencies. Aspects of the Nomad workflow remain pretty much the same. The usual Makefile targets should continue to work as they always did. The API submodule simply defers to the parent Nomad version on the repository, keeping the semantics of API versioning that currently exists.
110 lines
3.2 KiB
Go
110 lines
3.2 KiB
Go
package buildutil
|
|
|
|
import (
|
|
"fmt"
|
|
"go/build"
|
|
"io"
|
|
"io/ioutil"
|
|
"os"
|
|
"path"
|
|
"path/filepath"
|
|
"sort"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
// FakeContext returns a build.Context for the fake file tree specified
|
|
// by pkgs, which maps package import paths to a mapping from file base
|
|
// names to contents.
|
|
//
|
|
// The fake Context has a GOROOT of "/go" and no GOPATH, and overrides
|
|
// the necessary file access methods to read from memory instead of the
|
|
// real file system.
|
|
//
|
|
// Unlike a real file tree, the fake one has only two levels---packages
|
|
// and files---so ReadDir("/go/src/") returns all packages under
|
|
// /go/src/ including, for instance, "math" and "math/big".
|
|
// ReadDir("/go/src/math/big") would return all the files in the
|
|
// "math/big" package.
|
|
//
|
|
func FakeContext(pkgs map[string]map[string]string) *build.Context {
|
|
clean := func(filename string) string {
|
|
f := path.Clean(filepath.ToSlash(filename))
|
|
// Removing "/go/src" while respecting segment
|
|
// boundaries has this unfortunate corner case:
|
|
if f == "/go/src" {
|
|
return ""
|
|
}
|
|
return strings.TrimPrefix(f, "/go/src/")
|
|
}
|
|
|
|
ctxt := build.Default // copy
|
|
ctxt.GOROOT = "/go"
|
|
ctxt.GOPATH = ""
|
|
ctxt.Compiler = "gc"
|
|
ctxt.IsDir = func(dir string) bool {
|
|
dir = clean(dir)
|
|
if dir == "" {
|
|
return true // needed by (*build.Context).SrcDirs
|
|
}
|
|
return pkgs[dir] != nil
|
|
}
|
|
ctxt.ReadDir = func(dir string) ([]os.FileInfo, error) {
|
|
dir = clean(dir)
|
|
var fis []os.FileInfo
|
|
if dir == "" {
|
|
// enumerate packages
|
|
for importPath := range pkgs {
|
|
fis = append(fis, fakeDirInfo(importPath))
|
|
}
|
|
} else {
|
|
// enumerate files of package
|
|
for basename := range pkgs[dir] {
|
|
fis = append(fis, fakeFileInfo(basename))
|
|
}
|
|
}
|
|
sort.Sort(byName(fis))
|
|
return fis, nil
|
|
}
|
|
ctxt.OpenFile = func(filename string) (io.ReadCloser, error) {
|
|
filename = clean(filename)
|
|
dir, base := path.Split(filename)
|
|
content, ok := pkgs[path.Clean(dir)][base]
|
|
if !ok {
|
|
return nil, fmt.Errorf("file not found: %s", filename)
|
|
}
|
|
return ioutil.NopCloser(strings.NewReader(content)), nil
|
|
}
|
|
ctxt.IsAbsPath = func(path string) bool {
|
|
path = filepath.ToSlash(path)
|
|
// Don't rely on the default (filepath.Path) since on
|
|
// Windows, it reports virtual paths as non-absolute.
|
|
return strings.HasPrefix(path, "/")
|
|
}
|
|
return &ctxt
|
|
}
|
|
|
|
type byName []os.FileInfo
|
|
|
|
func (s byName) Len() int { return len(s) }
|
|
func (s byName) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
|
|
func (s byName) Less(i, j int) bool { return s[i].Name() < s[j].Name() }
|
|
|
|
type fakeFileInfo string
|
|
|
|
func (fi fakeFileInfo) Name() string { return string(fi) }
|
|
func (fakeFileInfo) Sys() interface{} { return nil }
|
|
func (fakeFileInfo) ModTime() time.Time { return time.Time{} }
|
|
func (fakeFileInfo) IsDir() bool { return false }
|
|
func (fakeFileInfo) Size() int64 { return 0 }
|
|
func (fakeFileInfo) Mode() os.FileMode { return 0644 }
|
|
|
|
type fakeDirInfo string
|
|
|
|
func (fd fakeDirInfo) Name() string { return string(fd) }
|
|
func (fakeDirInfo) Sys() interface{} { return nil }
|
|
func (fakeDirInfo) ModTime() time.Time { return time.Time{} }
|
|
func (fakeDirInfo) IsDir() bool { return true }
|
|
func (fakeDirInfo) Size() int64 { return 0 }
|
|
func (fakeDirInfo) Mode() os.FileMode { return 0755 }
|