libgo: update to Go 1.11
[official-gcc.git] / libgo / go / cmd / go / internal / modcmd / why.go
blob03e0a039bc5014d796a894b69fe9fcf4b0b6deea
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.
5 package modcmd
7 import (
8 "cmd/go/internal/base"
9 "cmd/go/internal/modload"
10 "cmd/go/internal/module"
11 "fmt"
12 "strings"
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.
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.
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.
36 For example:
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
44 # golang.org/x/text/encoding
45 (main module does not need package golang.org/x/text/encoding)
50 var (
51 whyM = cmdWhy.Flag.Bool("m", false, "")
52 whyVendor = cmdWhy.Flag.Bool("vendor", false, "")
55 func init() {
56 cmdWhy.Run = runWhy // break init cycle
59 func runWhy(cmd *base.Command, args []string) {
60 loadALL := modload.LoadALL
61 if *whyVendor {
62 loadALL = modload.LoadVendor
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")
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)
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
91 why := modload.Why(best)
92 if why == "" {
93 vendoring := ""
94 if *whyVendor {
95 vendoring = " to vendor"
97 why = "(main module does not need" + vendoring + " module " + m.Path + ")\n"
99 fmt.Printf("%s# %s\n%s", sep, m.Path, why)
100 sep = "\n"
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"
114 why = "(main module does not need" + vendoring + " package " + path + ")\n"
116 fmt.Printf("%s# %s\n%s", sep, path, why)
117 sep = "\n"