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  }