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