| // Copyright 2018 The Go Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| // go mod graph |
| |
| package modcmd |
| |
| import ( |
| "bufio" |
| "context" |
| "os" |
| |
| "cmd/go/internal/base" |
| "cmd/go/internal/cfg" |
| "cmd/go/internal/gover" |
| "cmd/go/internal/modload" |
| "cmd/go/internal/toolchain" |
| |
| "golang.org/x/mod/module" |
| ) |
| |
| var cmdGraph = &base.Command{ |
| UsageLine: "go mod graph [-go=version] [-x]", |
| Short: "print module requirement graph", |
| Long: ` |
| Graph prints the module requirement graph (with replacements applied) |
| in text form. Each line in the output has two space-separated fields: a module |
| and one of its requirements. Each module is identified as a string of the form |
| path@version, except for the main module, which has no @version suffix. |
| |
| The -go flag causes graph to report the module graph as loaded by the |
| given Go version, instead of the version indicated by the 'go' directive |
| in the go.mod file. |
| |
| The -x flag causes graph to print the commands graph executes. |
| |
| See https://golang.org/ref/mod#go-mod-graph for more about 'go mod graph'. |
| `, |
| Run: runGraph, |
| } |
| |
| var ( |
| graphGo goVersionFlag |
| ) |
| |
| func init() { |
| cmdGraph.Flag.Var(&graphGo, "go", "") |
| cmdGraph.Flag.BoolVar(&cfg.BuildX, "x", false, "") |
| base.AddChdirFlag(&cmdGraph.Flag) |
| base.AddModCommonFlags(&cmdGraph.Flag) |
| } |
| |
| func runGraph(ctx context.Context, cmd *base.Command, args []string) { |
| modload.InitWorkfile() |
| |
| if len(args) > 0 { |
| base.Fatalf("go: 'go mod graph' accepts no arguments") |
| } |
| modload.ForceUseModules = true |
| modload.RootMode = modload.NeedRoot |
| |
| goVersion := graphGo.String() |
| if goVersion != "" && gover.Compare(gover.Local(), goVersion) < 0 { |
| toolchain.SwitchOrFatal(ctx, &gover.TooNewError{ |
| What: "-go flag", |
| GoVersion: goVersion, |
| }) |
| } |
| |
| mg, err := modload.LoadModGraph(ctx, goVersion) |
| if err != nil { |
| base.Fatal(err) |
| } |
| |
| w := bufio.NewWriter(os.Stdout) |
| defer w.Flush() |
| |
| format := func(m module.Version) { |
| w.WriteString(m.Path) |
| if m.Version != "" { |
| w.WriteString("@") |
| w.WriteString(m.Version) |
| } |
| } |
| |
| mg.WalkBreadthFirst(func(m module.Version) { |
| reqs, _ := mg.RequiredBy(m) |
| for _, r := range reqs { |
| format(m) |
| w.WriteByte(' ') |
| format(r) |
| w.WriteByte('\n') |
| } |
| }) |
| } |