]> Cypherpunks.ru repositories - gostls13.git/blob - src/cmd/go/internal/modload/search.go
[dev.boringcrypto] all: merge master into dev.boringcrypto
[gostls13.git] / src / cmd / go / internal / modload / search.go
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         "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 // matchPackages returns a list of packages in the list of modules
21 // matching the pattern. Package loading assumes the given set of tags.
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, // ignore pseudo-package that exists only for documentation
32         }
33         if !cfg.BuildContext.CgoEnabled {
34                 have["runtime/cgo"] = true // ignore during walk
35         }
36         var pkgs []string
37
38         walkPkgs := func(root, importPathRoot string) {
39                 root = filepath.Clean(root)
40                 var cmd string
41                 if root == cfg.GOROOTsrc {
42                         cmd = filepath.Join(root, "cmd")
43                 }
44                 filepath.Walk(root, func(path string, fi os.FileInfo, err error) error {
45                         if err != nil {
46                                 return nil
47                         }
48
49                         // Don't use GOROOT/src but do walk down into it.
50                         if path == root && importPathRoot == "" {
51                                 return nil
52                         }
53
54                         // GOROOT/src/cmd makes use of GOROOT/src/cmd/vendor,
55                         // which module mode can't deal with. Eventually we'll stop using
56                         // that vendor directory, and then we can remove this exclusion.
57                         // golang.org/issue/26924.
58                         if path == cmd {
59                                 return filepath.SkipDir
60                         }
61
62                         want := true
63                         // Avoid .foo, _foo, and testdata directory trees.
64                         _, elem := filepath.Split(path)
65                         if strings.HasPrefix(elem, ".") || strings.HasPrefix(elem, "_") || elem == "testdata" {
66                                 want = false
67                         }
68
69                         name := importPathRoot + filepath.ToSlash(path[len(root):])
70                         if importPathRoot == "" {
71                                 name = name[1:] // cut leading slash
72                         }
73                         if !treeCanMatch(name) {
74                                 want = false
75                         }
76
77                         if !fi.IsDir() {
78                                 if fi.Mode()&os.ModeSymlink != 0 && want {
79                                         if target, err := os.Stat(path); err == nil && target.IsDir() {
80                                                 fmt.Fprintf(os.Stderr, "warning: ignoring symlink %s\n", path)
81                                         }
82                                 }
83                                 return nil
84                         }
85
86                         if !want {
87                                 return filepath.SkipDir
88                         }
89                         if path != root {
90                                 if _, err := os.Stat(filepath.Join(path, "go.mod")); err == nil {
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" {
105                                 return filepath.SkipDir
106                         }
107                         return nil
108                 })
109         }
110
111         if useStd {
112                 walkPkgs(cfg.GOROOTsrc, "")
113         }
114
115         for _, mod := range modules {
116                 if !treeCanMatch(mod.Path) {
117                         continue
118                 }
119                 var root string
120                 if mod.Version == "" {
121                         root = ModRoot
122                 } else {
123                         var err error
124                         root, _, err = fetch(mod)
125                         if err != nil {
126                                 base.Errorf("go: %v", err)
127                                 continue
128                         }
129                 }
130                 walkPkgs(root, mod.Path)
131         }
132
133         return pkgs
134 }