github.com/zxy12/go_duplicate_112_new@v0.0.0-20200807091221-747231827200/src/cmd/go/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  	"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  			if !HasModRoot() {
   122  				continue // If there is no main module, we can't search in it.
   123  			}
   124  			root = ModRoot()
   125  		} else {
   126  			var err error
   127  			root, _, err = fetch(mod)
   128  			if err != nil {
   129  				base.Errorf("go: %v", err)
   130  				continue
   131  			}
   132  		}
   133  		walkPkgs(root, mod.Path)
   134  	}
   135  
   136  	return pkgs
   137  }