go.undefinedlabs.com/scopeagent@v0.4.2/agent/dependencies.go (about) 1 package agent 2 3 import ( 4 "bytes" 5 "encoding/json" 6 "os/exec" 7 "sort" 8 "strings" 9 10 "go.undefinedlabs.com/scopeagent/env" 11 ) 12 13 type ( 14 dependency struct { 15 Path string 16 Version string 17 Main bool 18 Indirect bool 19 } 20 ) 21 22 // Gets the dependencies map 23 func getDependencyMap() map[string]string { 24 deps := map[string][]string{} 25 if modGraphBytes, err := exec.Command("go", "list", "-m", "-json", "all").Output(); err == nil { 26 lIdx := 0 27 remain := modGraphBytes 28 for { 29 // We have to parse this way because the tool returns multiple object but not in array format 30 if len(remain) == 0 { 31 break 32 } 33 lIdx = bytes.IndexByte(remain, '}') 34 if lIdx == -1 { 35 break 36 } 37 item := remain[:lIdx+1] 38 remain = remain[lIdx+1:] 39 40 var depJson dependency 41 if err := json.Unmarshal(item, &depJson); err == nil { 42 if depJson.Main { 43 continue 44 } 45 if !env.ScopeDependenciesIndirect.Value && depJson.Indirect { 46 continue 47 } 48 if preValue, ok := deps[depJson.Path]; ok { 49 // We can have multiple versions of the same dependency by indirection 50 deps[depJson.Path] = unique(append(preValue, depJson.Version)) 51 } else { 52 deps[depJson.Path] = []string{depJson.Version} 53 } 54 } 55 } 56 } 57 dependencies := map[string]string{} 58 for k, v := range deps { 59 if len(v) > 0 { 60 sort.Strings(v) 61 dependencies[k] = strings.Join(v, ", ") 62 } else { 63 dependencies[k] = v[0] 64 } 65 } 66 return dependencies 67 } 68 69 func unique(slice []string) []string { 70 keys := make(map[string]bool) 71 var list []string 72 for _, entry := range slice { 73 if _, value := keys[entry]; !value { 74 keys[entry] = true 75 list = append(list, entry) 76 } 77 } 78 return list 79 }