...
1
2
3
4
5 package debug
6
7 import (
8 "strings"
9 )
10
11
12 func modinfo() string
13
14
15
16
17 func ReadBuildInfo() (info *BuildInfo, ok bool) {
18 return readBuildInfo(modinfo())
19 }
20
21
22
23 type BuildInfo struct {
24 Path string
25 Main Module
26 Deps []*Module
27 }
28
29
30 type Module struct {
31 Path string
32 Version string
33 Sum string
34 Replace *Module
35 }
36
37 func readBuildInfo(data string) (*BuildInfo, bool) {
38 if len(data) < 32 {
39 return nil, false
40 }
41 data = data[16 : len(data)-16]
42
43 const (
44 pathLine = "path\t"
45 modLine = "mod\t"
46 depLine = "dep\t"
47 repLine = "=>\t"
48 )
49
50 readEntryFirstLine := func(elem []string) (Module, bool) {
51 if len(elem) != 2 && len(elem) != 3 {
52 return Module{}, false
53 }
54 sum := ""
55 if len(elem) == 3 {
56 sum = elem[2]
57 }
58 return Module{
59 Path: elem[0],
60 Version: elem[1],
61 Sum: sum,
62 }, true
63 }
64
65 var (
66 info = &BuildInfo{}
67 last *Module
68 line string
69 ok bool
70 )
71
72 for len(data) > 0 {
73 i := strings.IndexByte(data, '\n')
74 if i < 0 {
75 break
76 }
77 line, data = data[:i], data[i+1:]
78 switch {
79 case strings.HasPrefix(line, pathLine):
80 elem := line[len(pathLine):]
81 info.Path = elem
82 case strings.HasPrefix(line, modLine):
83 elem := strings.Split(line[len(modLine):], "\t")
84 last = &info.Main
85 *last, ok = readEntryFirstLine(elem)
86 if !ok {
87 return nil, false
88 }
89 case strings.HasPrefix(line, depLine):
90 elem := strings.Split(line[len(depLine):], "\t")
91 last = new(Module)
92 info.Deps = append(info.Deps, last)
93 *last, ok = readEntryFirstLine(elem)
94 if !ok {
95 return nil, false
96 }
97 case strings.HasPrefix(line, repLine):
98 elem := strings.Split(line[len(repLine):], "\t")
99 if len(elem) != 3 {
100 return nil, false
101 }
102 if last == nil {
103 return nil, false
104 }
105 last.Replace = &Module{
106 Path: elem[0],
107 Version: elem[1],
108 Sum: elem[2],
109 }
110 last = nil
111 }
112 }
113 return info, true
114 }
115
View as plain text