Black Lives Matter. Support the Equal Justice Initiative.

Source file src/cmd/go/internal/modcmd/graph.go

Documentation: cmd/go/internal/modcmd

     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  // go mod graph
     6  
     7  package modcmd
     8  
     9  import (
    10  	"bufio"
    11  	"context"
    12  	"os"
    13  	"sort"
    14  
    15  	"cmd/go/internal/base"
    16  	"cmd/go/internal/modload"
    17  
    18  	"golang.org/x/mod/module"
    19  )
    20  
    21  var cmdGraph = &base.Command{
    22  	UsageLine: "go mod graph",
    23  	Short:     "print module requirement graph",
    24  	Long: `
    25  Graph prints the module requirement graph (with replacements applied)
    26  in text form. Each line in the output has two space-separated fields: a module
    27  and one of its requirements. Each module is identified as a string of the form
    28  path@version, except for the main module, which has no @version suffix.
    29  
    30  See https://golang.org/ref/mod#go-mod-graph for more about 'go mod graph'.
    31  	`,
    32  	Run: runGraph,
    33  }
    34  
    35  func init() {
    36  	base.AddModCommonFlags(&cmdGraph.Flag)
    37  }
    38  
    39  func runGraph(ctx context.Context, cmd *base.Command, args []string) {
    40  	if len(args) > 0 {
    41  		base.Fatalf("go mod graph: graph takes no arguments")
    42  	}
    43  	modload.ForceUseModules = true
    44  	modload.RootMode = modload.NeedRoot
    45  	modload.LoadAllModules(ctx)
    46  
    47  	reqs := modload.MinReqs()
    48  	format := func(m module.Version) string {
    49  		if m.Version == "" {
    50  			return m.Path
    51  		}
    52  		return m.Path + "@" + m.Version
    53  	}
    54  
    55  	var out []string
    56  	var deps int // index in out where deps start
    57  	seen := map[module.Version]bool{modload.Target: true}
    58  	queue := []module.Version{modload.Target}
    59  	for len(queue) > 0 {
    60  		var m module.Version
    61  		m, queue = queue[0], queue[1:]
    62  		list, _ := reqs.Required(m)
    63  		for _, r := range list {
    64  			if !seen[r] {
    65  				queue = append(queue, r)
    66  				seen[r] = true
    67  			}
    68  			out = append(out, format(m)+" "+format(r)+"\n")
    69  		}
    70  		if m == modload.Target {
    71  			deps = len(out)
    72  		}
    73  	}
    74  
    75  	sort.Slice(out[deps:], func(i, j int) bool {
    76  		return out[deps+i][0] < out[deps+j][0]
    77  	})
    78  
    79  	w := bufio.NewWriter(os.Stdout)
    80  	for _, line := range out {
    81  		w.WriteString(line)
    82  	}
    83  	w.Flush()
    84  }
    85  

View as plain text