github.com/gagliardetto/golang-go@v0.0.0-20201020153340-53909ea70814/cmd/go/not-internal/modload/search.go (about) 1 // Copyright 2018 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 modload 6 7 import ( 8 "fmt" 9 "os" 10 "path/filepath" 11 "strings" 12 13 "github.com/gagliardetto/golang-go/cmd/go/not-internal/base" 14 "github.com/gagliardetto/golang-go/cmd/go/not-internal/cfg" 15 "github.com/gagliardetto/golang-go/cmd/go/not-internal/imports" 16 "github.com/gagliardetto/golang-go/cmd/go/not-internal/search" 17 18 "golang.org/x/mod/module" 19 ) 20 21 // matchPackages returns a list of packages in the list of modules 22 // matching the pattern. Package loading assumes the given set of tags. 23 func matchPackages(pattern string, tags map[string]bool, useStd bool, modules []module.Version) []string { 24 match := func(string) bool { return true } 25 treeCanMatch := func(string) bool { return true } 26 if !search.IsMetaPackage(pattern) { 27 match = search.MatchPattern(pattern) 28 treeCanMatch = search.TreeCanMatchPattern(pattern) 29 } 30 31 have := map[string]bool{ 32 "builtin": true, // ignore pseudo-package that exists only for documentation 33 } 34 if !cfg.BuildContext.CgoEnabled { 35 have["runtime/cgo"] = true // ignore during walk 36 } 37 var pkgs []string 38 39 type pruning int8 40 const ( 41 pruneVendor = pruning(1 << iota) 42 pruneGoMod 43 ) 44 45 walkPkgs := func(root, importPathRoot string, prune pruning) { 46 root = filepath.Clean(root) 47 filepath.Walk(root, func(path string, fi os.FileInfo, err error) error { 48 if err != nil { 49 return nil 50 } 51 52 want := true 53 elem := "" 54 55 // Don't use GOROOT/src but do walk down into it. 56 if path == root { 57 if importPathRoot == "" { 58 return nil 59 } 60 } else { 61 // Avoid .foo, _foo, and testdata subdirectory trees. 62 _, elem = filepath.Split(path) 63 if strings.HasPrefix(elem, ".") || strings.HasPrefix(elem, "_") || elem == "testdata" { 64 want = false 65 } 66 } 67 68 name := importPathRoot + filepath.ToSlash(path[len(root):]) 69 if importPathRoot == "" { 70 name = name[1:] // cut leading slash 71 } 72 if !treeCanMatch(name) { 73 want = false 74 } 75 76 if !fi.IsDir() { 77 if fi.Mode()&os.ModeSymlink != 0 && want { 78 if target, err := os.Stat(path); err == nil && target.IsDir() { 79 fmt.Fprintf(os.Stderr, "warning: ignoring symlink %s\n", path) 80 } 81 } 82 return nil 83 } 84 85 if !want { 86 return filepath.SkipDir 87 } 88 // Stop at module boundaries. 89 if (prune&pruneGoMod != 0) && path != root { 90 if fi, err := os.Stat(filepath.Join(path, "go.mod")); err == nil && !fi.IsDir() { 91 return filepath.SkipDir 92 } 93 } 94 95 if !have[name] { 96 have[name] = true 97 if match(name) { 98 if _, _, err := scanDir(path, tags); err != imports.ErrNoGo { 99 pkgs = append(pkgs, name) 100 } 101 } 102 } 103 104 if elem == "vendor" && (prune&pruneVendor != 0) { 105 return filepath.SkipDir 106 } 107 return nil 108 }) 109 } 110 111 if useStd { 112 walkPkgs(cfg.GOROOTsrc, "", pruneGoMod) 113 if treeCanMatch("cmd") { 114 walkPkgs(filepath.Join(cfg.GOROOTsrc, "cmd"), "cmd", pruneGoMod) 115 } 116 } 117 118 if cfg.BuildMod == "vendor" { 119 if HasModRoot() { 120 walkPkgs(ModRoot(), targetPrefix, pruneGoMod|pruneVendor) 121 walkPkgs(filepath.Join(ModRoot(), "vendor"), "", pruneVendor) 122 } 123 return pkgs 124 } 125 126 for _, mod := range modules { 127 if !treeCanMatch(mod.Path) { 128 continue 129 } 130 131 var ( 132 root, modPrefix string 133 isLocal bool 134 ) 135 if mod == Target { 136 if !HasModRoot() { 137 continue // If there is no main module, we can't search in it. 138 } 139 root = ModRoot() 140 modPrefix = targetPrefix 141 isLocal = true 142 } else { 143 var err error 144 root, isLocal, err = fetch(mod) 145 if err != nil { 146 base.Errorf("go: %v", err) 147 continue 148 } 149 modPrefix = mod.Path 150 } 151 152 prune := pruneVendor 153 if isLocal { 154 prune |= pruneGoMod 155 } 156 walkPkgs(root, modPrefix, prune) 157 } 158 159 return pkgs 160 }