+++ /dev/null
-// +build ignore
-
-// Copyright 2013 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Command mkindex creates the file "pkgindex.go" containing an index of the Go
-// standard library. The file is intended to be built as part of the imports
-// package, so that the package may be used in environments where a GOROOT is
-// not available (such as App Engine).
-package imports
-
-import (
- "bytes"
- "fmt"
- "go/ast"
- "go/build"
- "go/format"
- "go/parser"
- "go/token"
- "io/ioutil"
- "log"
- "os"
- "path"
- "path/filepath"
- "strings"
-)
-
-var (
- pkgIndex = make(map[string][]pkg)
- exports = make(map[string]map[string]bool)
-)
-
-func main() {
- // Don't use GOPATH.
- ctx := build.Default
- ctx.GOPATH = ""
-
- // Populate pkgIndex global from GOROOT.
- for _, path := range ctx.SrcDirs() {
- f, err := os.Open(path)
- if err != nil {
- log.Print(err)
- continue
- }
- children, err := f.Readdir(-1)
- f.Close()
- if err != nil {
- log.Print(err)
- continue
- }
- for _, child := range children {
- if child.IsDir() {
- loadPkg(path, child.Name())
- }
- }
- }
- // Populate exports global.
- for _, ps := range pkgIndex {
- for _, p := range ps {
- e := loadExports(p.dir)
- if e != nil {
- exports[p.dir] = e
- }
- }
- }
-
- // Construct source file.
- var buf bytes.Buffer
- fmt.Fprint(&buf, pkgIndexHead)
- fmt.Fprintf(&buf, "var pkgIndexMaster = %#v\n", pkgIndex)
- fmt.Fprintf(&buf, "var exportsMaster = %#v\n", exports)
- src := buf.Bytes()
-
- // Replace main.pkg type name with pkg.
- src = bytes.Replace(src, []byte("main.pkg"), []byte("pkg"), -1)
- // Replace actual GOROOT with "/go".
- src = bytes.Replace(src, []byte(ctx.GOROOT), []byte("/go"), -1)
- // Add some line wrapping.
- src = bytes.Replace(src, []byte("}, "), []byte("},\n"), -1)
- src = bytes.Replace(src, []byte("true, "), []byte("true,\n"), -1)
-
- var err error
- src, err = format.Source(src)
- if err != nil {
- log.Fatal(err)
- }
-
- // Write out source file.
- err = ioutil.WriteFile("pkgindex.go", src, 0644)
- if err != nil {
- log.Fatal(err)
- }
-}
-
-const pkgIndexHead = `package imports
-
-func init() {
- pkgIndexOnce.Do(func() {
- pkgIndex.m = pkgIndexMaster
- })
- loadExports = func(dir string) map[string]bool {
- return exportsMaster[dir]
- }
-}
-`
-
-type pkg struct {
- importpath string // full pkg import path, e.g. "net/http"
- dir string // absolute file path to pkg directory e.g. "/usr/lib/go/src/fmt"
-}
-
-var fset = token.NewFileSet()
-
-func loadPkg(root, importpath string) {
- shortName := path.Base(importpath)
- if shortName == "testdata" {
- return
- }
-
- dir := filepath.Join(root, importpath)
- pkgIndex[shortName] = append(pkgIndex[shortName], pkg{
- importpath: importpath,
- dir: dir,
- })
-
- pkgDir, err := os.Open(dir)
- if err != nil {
- return
- }
- children, err := pkgDir.Readdir(-1)
- pkgDir.Close()
- if err != nil {
- return
- }
- for _, child := range children {
- name := child.Name()
- if name == "" {
- continue
- }
- if c := name[0]; c == '.' || ('0' <= c && c <= '9') {
- continue
- }
- if child.IsDir() {
- loadPkg(root, filepath.Join(importpath, name))
- }
- }
-}
-
-func loadExports(dir string) map[string]bool {
- exports := make(map[string]bool)
- buildPkg, err := build.ImportDir(dir, 0)
- if err != nil {
- if strings.Contains(err.Error(), "no buildable Go source files in") {
- return nil
- }
- log.Printf("could not import %q: %v", dir, err)
- return nil
- }
- for _, file := range buildPkg.GoFiles {
- f, err := parser.ParseFile(fset, filepath.Join(dir, file), nil, 0)
- if err != nil {
- log.Printf("could not parse %q: %v", file, err)
- continue
- }
- for name := range f.Scope.Objects {
- if ast.IsExported(name) {
- exports[name] = true
- }
- }
- }
- return exports
-}