github.com/gagliardetto/golang-go@v0.0.0-20201020153340-53909ea70814/cmd/go/not-internal/modcmd/graph.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  // go mod graph
     6  
     7  package modcmd
     8  
     9  import (
    10  	"bufio"
    11  	"os"
    12  	"sort"
    13  
    14  	"github.com/gagliardetto/golang-go/cmd/go/not-internal/base"
    15  	"github.com/gagliardetto/golang-go/cmd/go/not-internal/cfg"
    16  	"github.com/gagliardetto/golang-go/cmd/go/not-internal/modload"
    17  	"github.com/gagliardetto/golang-go/cmd/go/not-internal/par"
    18  	"github.com/gagliardetto/golang-go/cmd/go/not-internal/work"
    19  
    20  	"golang.org/x/mod/module"
    21  )
    22  
    23  var cmdGraph = &base.Command{
    24  	UsageLine: "go mod graph",
    25  	Short:     "print module requirement graph",
    26  	Long: `
    27  Graph prints the module requirement graph (with replacements applied)
    28  in text form. Each line in the output has two space-separated fields: a module
    29  and one of its requirements. Each module is identified as a string of the form
    30  path@version, except for the main module, which has no @version suffix.
    31  	`,
    32  	Run: runGraph,
    33  }
    34  
    35  func init() {
    36  	work.AddModCommonFlags(cmdGraph)
    37  }
    38  
    39  func runGraph(cmd *base.Command, args []string) {
    40  	if len(args) > 0 {
    41  		base.Fatalf("go mod graph: graph takes no arguments")
    42  	}
    43  	// Checks go mod expected behavior
    44  	if !modload.Enabled() {
    45  		if cfg.Getenv("GO111MODULE") == "off" {
    46  			base.Fatalf("go: modules disabled by GO111MODULE=off; see 'go help modules'")
    47  		} else {
    48  			base.Fatalf("go: cannot find main module; see 'go help modules'")
    49  		}
    50  	}
    51  	modload.LoadBuildList()
    52  
    53  	reqs := modload.MinReqs()
    54  	format := func(m module.Version) string {
    55  		if m.Version == "" {
    56  			return m.Path
    57  		}
    58  		return m.Path + "@" + m.Version
    59  	}
    60  
    61  	// Note: using par.Work only to manage work queue.
    62  	// No parallelism here, so no locking.
    63  	var out []string
    64  	var deps int // index in out where deps start
    65  	var work par.Work
    66  	work.Add(modload.Target)
    67  	work.Do(1, func(item interface{}) {
    68  		m := item.(module.Version)
    69  		list, _ := reqs.Required(m)
    70  		for _, r := range list {
    71  			work.Add(r)
    72  			out = append(out, format(m)+" "+format(r)+"\n")
    73  		}
    74  		if m == modload.Target {
    75  			deps = len(out)
    76  		}
    77  	})
    78  
    79  	sort.Slice(out[deps:], func(i, j int) bool {
    80  		return out[deps+i][0] < out[deps+j][0]
    81  	})
    82  
    83  	w := bufio.NewWriter(os.Stdout)
    84  	for _, line := range out {
    85  		w.WriteString(line)
    86  	}
    87  	w.Flush()
    88  }