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  }