...

Source file src/golang.org/x/tools/go/buildutil/fakecontext.go

Documentation: golang.org/x/tools/go/buildutil

     1  // Copyright 2015 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package buildutil
     6  
     7  import (
     8  	"fmt"
     9  	"go/build"
    10  	"io"
    11  	"io/ioutil"
    12  	"os"
    13  	"path"
    14  	"path/filepath"
    15  	"sort"
    16  	"strings"
    17  	"time"
    18  )
    19  
    20  // FakeContext returns a build.Context for the fake file tree specified
    21  // by pkgs, which maps package import paths to a mapping from file base
    22  // names to contents.
    23  //
    24  // The fake Context has a GOROOT of "/go" and no GOPATH, and overrides
    25  // the necessary file access methods to read from memory instead of the
    26  // real file system.
    27  //
    28  // Unlike a real file tree, the fake one has only two levels---packages
    29  // and files---so ReadDir("/go/src/") returns all packages under
    30  // /go/src/ including, for instance, "math" and "math/big".
    31  // ReadDir("/go/src/math/big") would return all the files in the
    32  // "math/big" package.
    33  func FakeContext(pkgs map[string]map[string]string) *build.Context {
    34  	clean := func(filename string) string {
    35  		f := path.Clean(filepath.ToSlash(filename))
    36  		// Removing "/go/src" while respecting segment
    37  		// boundaries has this unfortunate corner case:
    38  		if f == "/go/src" {
    39  			return ""
    40  		}
    41  		return strings.TrimPrefix(f, "/go/src/")
    42  	}
    43  
    44  	ctxt := build.Default // copy
    45  	ctxt.GOROOT = "/go"
    46  	ctxt.GOPATH = ""
    47  	ctxt.Compiler = "gc"
    48  	ctxt.IsDir = func(dir string) bool {
    49  		dir = clean(dir)
    50  		if dir == "" {
    51  			return true // needed by (*build.Context).SrcDirs
    52  		}
    53  		return pkgs[dir] != nil
    54  	}
    55  	ctxt.ReadDir = func(dir string) ([]os.FileInfo, error) {
    56  		dir = clean(dir)
    57  		var fis []os.FileInfo
    58  		if dir == "" {
    59  			// enumerate packages
    60  			for importPath := range pkgs {
    61  				fis = append(fis, fakeDirInfo(importPath))
    62  			}
    63  		} else {
    64  			// enumerate files of package
    65  			for basename := range pkgs[dir] {
    66  				fis = append(fis, fakeFileInfo(basename))
    67  			}
    68  		}
    69  		sort.Sort(byName(fis))
    70  		return fis, nil
    71  	}
    72  	ctxt.OpenFile = func(filename string) (io.ReadCloser, error) {
    73  		filename = clean(filename)
    74  		dir, base := path.Split(filename)
    75  		content, ok := pkgs[path.Clean(dir)][base]
    76  		if !ok {
    77  			return nil, fmt.Errorf("file not found: %s", filename)
    78  		}
    79  		return ioutil.NopCloser(strings.NewReader(content)), nil
    80  	}
    81  	ctxt.IsAbsPath = func(path string) bool {
    82  		path = filepath.ToSlash(path)
    83  		// Don't rely on the default (filepath.Path) since on
    84  		// Windows, it reports virtual paths as non-absolute.
    85  		return strings.HasPrefix(path, "/")
    86  	}
    87  	return &ctxt
    88  }
    89  
    90  type byName []os.FileInfo
    91  
    92  func (s byName) Len() int           { return len(s) }
    93  func (s byName) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }
    94  func (s byName) Less(i, j int) bool { return s[i].Name() < s[j].Name() }
    95  
    96  type fakeFileInfo string
    97  
    98  func (fi fakeFileInfo) Name() string    { return string(fi) }
    99  func (fakeFileInfo) Sys() interface{}   { return nil }
   100  func (fakeFileInfo) ModTime() time.Time { return time.Time{} }
   101  func (fakeFileInfo) IsDir() bool        { return false }
   102  func (fakeFileInfo) Size() int64        { return 0 }
   103  func (fakeFileInfo) Mode() os.FileMode  { return 0644 }
   104  
   105  type fakeDirInfo string
   106  
   107  func (fd fakeDirInfo) Name() string    { return string(fd) }
   108  func (fakeDirInfo) Sys() interface{}   { return nil }
   109  func (fakeDirInfo) ModTime() time.Time { return time.Time{} }
   110  func (fakeDirInfo) IsDir() bool        { return true }
   111  func (fakeDirInfo) Size() int64        { return 0 }
   112  func (fakeDirInfo) Mode() os.FileMode  { return 0755 }
   113  

View as plain text