github.com/zxy12/go_duplicate_112_new@v0.0.0-20200807091221-747231827200/src/cmd/go/internal/modcmd/why.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 modcmd
     6  
     7  import (
     8  	"cmd/go/internal/base"
     9  	"cmd/go/internal/modload"
    10  	"cmd/go/internal/module"
    11  	"fmt"
    12  	"strings"
    13  )
    14  
    15  var cmdWhy = &base.Command{
    16  	UsageLine: "go mod why [-m] [-vendor] packages...",
    17  	Short:     "explain why packages or modules are needed",
    18  	Long: `
    19  Why shows a shortest path in the import graph from the main module to
    20  each of the listed packages. If the -m flag is given, why treats the
    21  arguments as a list of modules and finds a path to any package in each
    22  of the modules.
    23  
    24  By default, why queries the graph of packages matched by "go list all",
    25  which includes tests for reachable packages. The -vendor flag causes why
    26  to exclude tests of dependencies.
    27  
    28  The output is a sequence of stanzas, one for each package or module
    29  name on the command line, separated by blank lines. Each stanza begins
    30  with a comment line "# package" or "# module" giving the target
    31  package or module. Subsequent lines give a path through the import
    32  graph, one package per line. If the package or module is not
    33  referenced from the main module, the stanza will display a single
    34  parenthesized note indicating that fact.
    35  
    36  For example:
    37  
    38  	$ go mod why golang.org/x/text/language golang.org/x/text/encoding
    39  	# golang.org/x/text/language
    40  	rsc.io/quote
    41  	rsc.io/sampler
    42  	golang.org/x/text/language
    43  
    44  	# golang.org/x/text/encoding
    45  	(main module does not need package golang.org/x/text/encoding)
    46  	$
    47  	`,
    48  }
    49  
    50  var (
    51  	whyM      = cmdWhy.Flag.Bool("m", false, "")
    52  	whyVendor = cmdWhy.Flag.Bool("vendor", false, "")
    53  )
    54  
    55  func init() {
    56  	cmdWhy.Run = runWhy // break init cycle
    57  }
    58  
    59  func runWhy(cmd *base.Command, args []string) {
    60  	loadALL := modload.LoadALL
    61  	if *whyVendor {
    62  		loadALL = modload.LoadVendor
    63  	}
    64  	if *whyM {
    65  		listU := false
    66  		listVersions := false
    67  		for _, arg := range args {
    68  			if strings.Contains(arg, "@") {
    69  				base.Fatalf("go mod why: module query not allowed")
    70  			}
    71  		}
    72  		mods := modload.ListModules(args, listU, listVersions)
    73  		byModule := make(map[module.Version][]string)
    74  		for _, path := range loadALL() {
    75  			m := modload.PackageModule(path)
    76  			if m.Path != "" {
    77  				byModule[m] = append(byModule[m], path)
    78  			}
    79  		}
    80  		sep := ""
    81  		for _, m := range mods {
    82  			best := ""
    83  			bestDepth := 1000000000
    84  			for _, path := range byModule[module.Version{Path: m.Path, Version: m.Version}] {
    85  				d := modload.WhyDepth(path)
    86  				if d > 0 && d < bestDepth {
    87  					best = path
    88  					bestDepth = d
    89  				}
    90  			}
    91  			why := modload.Why(best)
    92  			if why == "" {
    93  				vendoring := ""
    94  				if *whyVendor {
    95  					vendoring = " to vendor"
    96  				}
    97  				why = "(main module does not need" + vendoring + " module " + m.Path + ")\n"
    98  			}
    99  			fmt.Printf("%s# %s\n%s", sep, m.Path, why)
   100  			sep = "\n"
   101  		}
   102  	} else {
   103  		matches := modload.ImportPaths(args) // resolve to packages
   104  		loadALL()                            // rebuild graph, from main module (not from named packages)
   105  		sep := ""
   106  		for _, m := range matches {
   107  			for _, path := range m.Pkgs {
   108  				why := modload.Why(path)
   109  				if why == "" {
   110  					vendoring := ""
   111  					if *whyVendor {
   112  						vendoring = " to vendor"
   113  					}
   114  					why = "(main module does not need" + vendoring + " package " + path + ")\n"
   115  				}
   116  				fmt.Printf("%s# %s\n%s", sep, path, why)
   117  				sep = "\n"
   118  			}
   119  		}
   120  	}
   121  }