-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.go
87 lines (74 loc) · 1.8 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
package main
import (
"bufio"
"flag"
"fmt"
"go/build"
"os"
"path/filepath"
"regexp"
"strings"
"github.com/emicklei/dot"
)
var (
versionRegex = regexp.MustCompile(`\sv\d+.\d+.\d+`)
pkgPath = filepath.Join(build.Default.GOPATH, "pkg/mod")
maxDepth = 10
regex *regexp.Regexp
)
func main() {
flag.IntVar(&maxDepth, "depth", 10, "The maximum depth for building the graph")
var regexStr string
flag.StringVar(®exStr, "reg", "", "Specifies the regular expression for filtering the dependencies")
flag.Parse()
regex = regexp.MustCompile(regexStr)
path, _ := os.Getwd()
if args := flag.Args(); len(args) != 0 {
var err error
path, err = filepath.Abs(args[0])
if err != nil {
panic(err)
}
}
if _, err := os.Stat(filepath.Join(path, "go.mod")); err != nil {
panic(err)
}
g := dot.NewGraph(dot.Directed)
node := g.Node(filepath.Base(path))
f, err := os.Open(filepath.Join(path, "go.mod"))
if err != nil {
panic(err)
}
defer f.Close()
buildGraph(g, node, f, 0)
os.Stdout.WriteString(g.String())
}
func buildGraph(g *dot.Graph, parent dot.Node, f *os.File, depth int) {
if depth >= maxDepth {
return
}
scanner := bufio.NewScanner(f)
for scanner.Scan() {
line := strings.TrimSpace(strings.TrimPrefix(scanner.Text(), "require"))
if strings.Contains(line, "// indirect") ||
!versionRegex.MatchString(line) ||
!regex.MatchString(line) {
continue
}
parts := strings.Fields(line)
pkg := parts[0]
node := g.Node(pkg)
if edges := g.FindEdges(parent, node); len(edges) == 0 {
g.Edge(parent, node)
}
version := parts[1]
target := fmt.Sprintf("%s@%s", pkg, version)
gomodPath := filepath.Join(pkgPath, target, "go.mod")
func() {
if f, err := os.Open(gomodPath); err == nil {
defer f.Close()
buildGraph(g, node, f, depth+1)
}
}()
}
}