...

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

     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		"cmd/go/internal/cfg"
    12		"os"
    13		"sort"
    14	
    15		"cmd/go/internal/base"
    16		"cmd/go/internal/modload"
    17		"cmd/go/internal/module"
    18		"cmd/go/internal/par"
    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		Run: runGraph,
    31	}
    32	
    33	func runGraph(cmd *base.Command, args []string) {
    34		if len(args) > 0 {
    35			base.Fatalf("go mod graph: graph takes no arguments")
    36		}
    37		// Checks go mod expected behavior
    38		if !modload.Enabled() {
    39			if cfg.Getenv("GO111MODULE") == "off" {
    40				base.Fatalf("go: modules disabled by GO111MODULE=off; see 'go help modules'")
    41			} else {
    42				base.Fatalf("go: cannot find main module; see 'go help modules'")
    43			}
    44		}
    45		modload.LoadBuildList()
    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		// Note: using par.Work only to manage work queue.
    56		// No parallelism here, so no locking.
    57		var out []string
    58		var deps int // index in out where deps start
    59		var work par.Work
    60		work.Add(modload.Target)
    61		work.Do(1, func(item interface{}) {
    62			m := item.(module.Version)
    63			list, _ := reqs.Required(m)
    64			for _, r := range list {
    65				work.Add(r)
    66				out = append(out, format(m)+" "+format(r)+"\n")
    67			}
    68			if m == modload.Target {
    69				deps = len(out)
    70			}
    71		})
    72	
    73		sort.Slice(out[deps:], func(i, j int) bool {
    74			return out[deps+i][0] < out[deps+j][0]
    75		})
    76	
    77		w := bufio.NewWriter(os.Stdout)
    78		for _, line := range out {
    79			w.WriteString(line)
    80		}
    81		w.Flush()
    82	}
    83	

View as plain text