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 }