"Fossies" - the Fresh Open Source Software Archive

Member "buildah-1.27.2/tests/tools/vendor/golang.org/x/tools/go/buildutil/allpackages.go" (20 Sep 2022, 5077 Bytes) of package /linux/misc/buildah-1.27.2.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Go source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. See also the last Fossies "Diffs" side-by-side code changes report for "allpackages.go": 1.26.4_vs_1.27.0.

    1 // Copyright 2014 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 buildutil provides utilities related to the go/build
    6 // package in the standard library.
    7 //
    8 // All I/O is done via the build.Context file system interface, which must
    9 // be concurrency-safe.
   10 package buildutil // import "golang.org/x/tools/go/buildutil"
   11 
   12 import (
   13     "go/build"
   14     "os"
   15     "path/filepath"
   16     "sort"
   17     "strings"
   18     "sync"
   19 )
   20 
   21 // AllPackages returns the package path of each Go package in any source
   22 // directory of the specified build context (e.g. $GOROOT or an element
   23 // of $GOPATH).  Errors are ignored.  The results are sorted.
   24 // All package paths are canonical, and thus may contain "/vendor/".
   25 //
   26 // The result may include import paths for directories that contain no
   27 // *.go files, such as "archive" (in $GOROOT/src).
   28 //
   29 // All I/O is done via the build.Context file system interface,
   30 // which must be concurrency-safe.
   31 func AllPackages(ctxt *build.Context) []string {
   32     var list []string
   33     ForEachPackage(ctxt, func(pkg string, _ error) {
   34         list = append(list, pkg)
   35     })
   36     sort.Strings(list)
   37     return list
   38 }
   39 
   40 // ForEachPackage calls the found function with the package path of
   41 // each Go package it finds in any source directory of the specified
   42 // build context (e.g. $GOROOT or an element of $GOPATH).
   43 // All package paths are canonical, and thus may contain "/vendor/".
   44 //
   45 // If the package directory exists but could not be read, the second
   46 // argument to the found function provides the error.
   47 //
   48 // All I/O is done via the build.Context file system interface,
   49 // which must be concurrency-safe.
   50 func ForEachPackage(ctxt *build.Context, found func(importPath string, err error)) {
   51     ch := make(chan item)
   52 
   53     var wg sync.WaitGroup
   54     for _, root := range ctxt.SrcDirs() {
   55         root := root
   56         wg.Add(1)
   57         go func() {
   58             allPackages(ctxt, root, ch)
   59             wg.Done()
   60         }()
   61     }
   62     go func() {
   63         wg.Wait()
   64         close(ch)
   65     }()
   66 
   67     // All calls to found occur in the caller's goroutine.
   68     for i := range ch {
   69         found(i.importPath, i.err)
   70     }
   71 }
   72 
   73 type item struct {
   74     importPath string
   75     err        error // (optional)
   76 }
   77 
   78 // We use a process-wide counting semaphore to limit
   79 // the number of parallel calls to ReadDir.
   80 var ioLimit = make(chan bool, 20)
   81 
   82 func allPackages(ctxt *build.Context, root string, ch chan<- item) {
   83     root = filepath.Clean(root) + string(os.PathSeparator)
   84 
   85     var wg sync.WaitGroup
   86 
   87     var walkDir func(dir string)
   88     walkDir = func(dir string) {
   89         // Avoid .foo, _foo, and testdata directory trees.
   90         base := filepath.Base(dir)
   91         if base == "" || base[0] == '.' || base[0] == '_' || base == "testdata" {
   92             return
   93         }
   94 
   95         pkg := filepath.ToSlash(strings.TrimPrefix(dir, root))
   96 
   97         // Prune search if we encounter any of these import paths.
   98         switch pkg {
   99         case "builtin":
  100             return
  101         }
  102 
  103         ioLimit <- true
  104         files, err := ReadDir(ctxt, dir)
  105         <-ioLimit
  106         if pkg != "" || err != nil {
  107             ch <- item{pkg, err}
  108         }
  109         for _, fi := range files {
  110             fi := fi
  111             if fi.IsDir() {
  112                 wg.Add(1)
  113                 go func() {
  114                     walkDir(filepath.Join(dir, fi.Name()))
  115                     wg.Done()
  116                 }()
  117             }
  118         }
  119     }
  120 
  121     walkDir(root)
  122     wg.Wait()
  123 }
  124 
  125 // ExpandPatterns returns the set of packages matched by patterns,
  126 // which may have the following forms:
  127 //
  128 //  golang.org/x/tools/cmd/guru     # a single package
  129 //  golang.org/x/tools/...          # all packages beneath dir
  130 //  ...                             # the entire workspace.
  131 //
  132 // Order is significant: a pattern preceded by '-' removes matching
  133 // packages from the set.  For example, these patterns match all encoding
  134 // packages except encoding/xml:
  135 //
  136 //  encoding/... -encoding/xml
  137 //
  138 // A trailing slash in a pattern is ignored.  (Path components of Go
  139 // package names are separated by slash, not the platform's path separator.)
  140 func ExpandPatterns(ctxt *build.Context, patterns []string) map[string]bool {
  141     // TODO(adonovan): support other features of 'go list':
  142     // - "std"/"cmd"/"all" meta-packages
  143     // - "..." not at the end of a pattern
  144     // - relative patterns using "./" or "../" prefix
  145 
  146     pkgs := make(map[string]bool)
  147     doPkg := func(pkg string, neg bool) {
  148         if neg {
  149             delete(pkgs, pkg)
  150         } else {
  151             pkgs[pkg] = true
  152         }
  153     }
  154 
  155     // Scan entire workspace if wildcards are present.
  156     // TODO(adonovan): opt: scan only the necessary subtrees of the workspace.
  157     var all []string
  158     for _, arg := range patterns {
  159         if strings.HasSuffix(arg, "...") {
  160             all = AllPackages(ctxt)
  161             break
  162         }
  163     }
  164 
  165     for _, arg := range patterns {
  166         if arg == "" {
  167             continue
  168         }
  169 
  170         neg := arg[0] == '-'
  171         if neg {
  172             arg = arg[1:]
  173         }
  174 
  175         if arg == "..." {
  176             // ... matches all packages
  177             for _, pkg := range all {
  178                 doPkg(pkg, neg)
  179             }
  180         } else if dir := strings.TrimSuffix(arg, "/..."); dir != arg {
  181             // dir/... matches all packages beneath dir
  182             for _, pkg := range all {
  183                 if strings.HasPrefix(pkg, dir) &&
  184                     (len(pkg) == len(dir) || pkg[len(dir)] == '/') {
  185                     doPkg(pkg, neg)
  186                 }
  187             }
  188         } else {
  189             // single package
  190             doPkg(strings.TrimSuffix(arg, "/"), neg)
  191         }
  192     }
  193 
  194     return pkgs
  195 }