src

Go monorepo.
git clone git://code.dwrz.net/src
Log | Files | Refs

fakecontext.go (3405B)


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