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