...
Source file src/pkg/cmd/go/internal/modload/search.go
1
2
3
4
5 package modload
6
7 import (
8 "fmt"
9 "os"
10 "path/filepath"
11 "strings"
12
13 "cmd/go/internal/base"
14 "cmd/go/internal/cfg"
15 "cmd/go/internal/imports"
16 "cmd/go/internal/module"
17 "cmd/go/internal/search"
18 )
19
20
21
22 func matchPackages(pattern string, tags map[string]bool, useStd bool, modules []module.Version) []string {
23 match := func(string) bool { return true }
24 treeCanMatch := func(string) bool { return true }
25 if !search.IsMetaPackage(pattern) {
26 match = search.MatchPattern(pattern)
27 treeCanMatch = search.TreeCanMatchPattern(pattern)
28 }
29
30 have := map[string]bool{
31 "builtin": true,
32 }
33 if !cfg.BuildContext.CgoEnabled {
34 have["runtime/cgo"] = true
35 }
36 var pkgs []string
37
38 type pruning int8
39 const (
40 pruneVendor = pruning(1 << iota)
41 pruneGoMod
42 )
43
44 walkPkgs := func(root, importPathRoot string, prune pruning) {
45 root = filepath.Clean(root)
46 filepath.Walk(root, func(path string, fi os.FileInfo, err error) error {
47 if err != nil {
48 return nil
49 }
50
51
52 if path == root && importPathRoot == "" {
53 return nil
54 }
55
56 want := true
57
58 _, elem := filepath.Split(path)
59 if strings.HasPrefix(elem, ".") || strings.HasPrefix(elem, "_") || elem == "testdata" {
60 want = false
61 }
62
63 name := importPathRoot + filepath.ToSlash(path[len(root):])
64 if importPathRoot == "" {
65 name = name[1:]
66 }
67 if !treeCanMatch(name) {
68 want = false
69 }
70
71 if !fi.IsDir() {
72 if fi.Mode()&os.ModeSymlink != 0 && want {
73 if target, err := os.Stat(path); err == nil && target.IsDir() {
74 fmt.Fprintf(os.Stderr, "warning: ignoring symlink %s\n", path)
75 }
76 }
77 return nil
78 }
79
80 if !want {
81 return filepath.SkipDir
82 }
83
84 if (prune&pruneGoMod != 0) && path != root {
85 if fi, err := os.Stat(filepath.Join(path, "go.mod")); err == nil && !fi.IsDir() {
86 return filepath.SkipDir
87 }
88 }
89
90 if !have[name] {
91 have[name] = true
92 if match(name) {
93 if _, _, err := scanDir(path, tags); err != imports.ErrNoGo {
94 pkgs = append(pkgs, name)
95 }
96 }
97 }
98
99 if elem == "vendor" && (prune&pruneVendor != 0) {
100 return filepath.SkipDir
101 }
102 return nil
103 })
104 }
105
106 if useStd {
107 walkPkgs(cfg.GOROOTsrc, "", pruneGoMod)
108 if treeCanMatch("cmd") {
109 walkPkgs(filepath.Join(cfg.GOROOTsrc, "cmd"), "cmd", pruneGoMod)
110 }
111 }
112
113 if cfg.BuildMod == "vendor" {
114 if HasModRoot() {
115 walkPkgs(ModRoot(), targetPrefix, pruneGoMod|pruneVendor)
116 walkPkgs(filepath.Join(ModRoot(), "vendor"), "", pruneVendor)
117 }
118 return pkgs
119 }
120
121 for _, mod := range modules {
122 if !treeCanMatch(mod.Path) {
123 continue
124 }
125
126 var (
127 root, modPrefix string
128 isLocal bool
129 )
130 if mod == Target {
131 if !HasModRoot() {
132 continue
133 }
134 root = ModRoot()
135 modPrefix = targetPrefix
136 isLocal = true
137 } else {
138 var err error
139 root, isLocal, err = fetch(mod)
140 if err != nil {
141 base.Errorf("go: %v", err)
142 continue
143 }
144 modPrefix = mod.Path
145 }
146
147 prune := pruneVendor
148 if isLocal {
149 prune |= pruneGoMod
150 }
151 walkPkgs(root, modPrefix, prune)
152 }
153
154 return pkgs
155 }
156
View as plain text