github.com/yacovm/fabric@v2.0.0-alpha.0.20191128145320-c5d4087dc723+incompatible/core/chaincode/platforms/golang/list.go (about) 1 /* 2 Copyright IBM Corp. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package golang 8 9 import ( 10 "context" 11 "encoding/json" 12 "fmt" 13 "io" 14 "os" 15 "os/exec" 16 "strings" 17 "time" 18 19 "github.com/pkg/errors" 20 ) 21 22 const listTimeout = 3 * time.Minute 23 24 const packageListFormat = ` 25 {{- if eq .Goroot false -}} 26 { 27 "import_path": "{{ .ImportPath }}", 28 "incomplete": {{ .Incomplete }}, 29 "dir": "{{ .Dir }}", 30 "go_files" : [{{ range $i, $file := .GoFiles }}{{ if $i }}, {{ end }}"{{ $file }}"{{end}}], 31 "c_files": [{{ range $i, $file := .CFiles }}{{ if $i }}, {{ end }}"{{ $file }}"{{end}}], 32 "cgo_files": [{{ range $i, $file := .CgoFiles }}{{ if $i }}, {{ end }}"{{ $file }}"{{end}}], 33 "h_files": [{{ range $i, $file := .HFiles }}{{ if $i }}, {{ end }}"{{ $file }}"{{end}}], 34 "s_files": [{{ range $i, $file := .SFiles }}{{ if $i }}, {{ end }}"{{ $file }}"{{end}}], 35 "ignored_go_files": [{{ range $i, $file := .IgnoredGoFiles }}{{ if $i }}, {{ end }}"{{ $file }}"{{end}}] 36 } 37 {{- end -}}` 38 39 type PackageInfo struct { 40 ImportPath string `json:"import_path,omitempty"` 41 Dir string `json:"dir,omitempty"` 42 GoFiles []string `json:"go_files,omitempty"` 43 CFiles []string `json:"c_files,omitempty"` 44 CgoFiles []string `json:"cgo_files,omitempty"` 45 HFiles []string `json:"h_files,omitempty"` 46 SFiles []string `json:"s_files,omitempty"` 47 IgnoredGoFiles []string `json:"ignored_go_files,omitempty"` 48 Incomplete bool `json:"incomplete,omitempty"` 49 } 50 51 func (p PackageInfo) Files() []string { 52 var files []string 53 files = append(files, p.GoFiles...) 54 files = append(files, p.CFiles...) 55 files = append(files, p.CgoFiles...) 56 files = append(files, p.HFiles...) 57 files = append(files, p.SFiles...) 58 files = append(files, p.IgnoredGoFiles...) 59 return files 60 } 61 62 // gopathDependencyPackageInfo extracts dependency information for 63 // specified package. 64 func gopathDependencyPackageInfo(goos, goarch, pkg string) ([]PackageInfo, error) { 65 ctx, cancel := context.WithTimeout(context.Background(), listTimeout) 66 defer cancel() 67 68 cmd := exec.CommandContext(ctx, "go", "list", "-deps", "-f", packageListFormat, pkg) 69 cmd.Env = append(os.Environ(), "GOOS="+goos, "GOARCH="+goarch) 70 71 stdout, err := cmd.StdoutPipe() 72 if err != nil { 73 return nil, wrapExitErr(err, "'go list -deps' failed") 74 } 75 decoder := json.NewDecoder(stdout) 76 77 err = cmd.Start() 78 if err != nil { 79 return nil, err 80 } 81 82 var list []PackageInfo 83 for { 84 var packageInfo PackageInfo 85 err := decoder.Decode(&packageInfo) 86 if err == io.EOF { 87 break 88 } 89 if err != nil { 90 return nil, err 91 } 92 if packageInfo.Incomplete { 93 return nil, fmt.Errorf("failed to calculate dependencies: incomplete package: %s", packageInfo.ImportPath) 94 } 95 96 list = append(list, packageInfo) 97 } 98 99 err = cmd.Wait() 100 if err != nil { 101 return nil, errors.Wrapf(err, "listing deps for pacakge %s failed", pkg) 102 } 103 104 return list, nil 105 } 106 107 func wrapExitErr(err error, message string) error { 108 if ee, ok := err.(*exec.ExitError); ok { 109 return errors.Wrapf(err, message+" with: %s", strings.TrimRight(string(ee.Stderr), "\n\r\t")) 110 } 111 return errors.Wrap(err, message) 112 } 113 114 const moduleListFormat = `{ 115 "dir": "{{ .Module.Dir }}", 116 "gomod": "{{ .Module.GoMod }}", 117 "import_path": "{{ .ImportPath }}", 118 "module_path": "{{ .Module.Path }}" 119 }` 120 121 type ModuleInfo struct { 122 Dir string `json:"dir,omitempty"` 123 ImportPath string `json:"import_path,omitempty"` 124 ModulePath string `json:"module_path,omitempty"` 125 GoMod string `json:"gomod,omitempty"` 126 } 127 128 // listModuleInfo extracts module information for the curent working directory. 129 func listModuleInfo(extraEnv ...string) (*ModuleInfo, error) { 130 ctx, cancel := context.WithTimeout(context.Background(), listTimeout) 131 defer cancel() 132 133 cmd := exec.CommandContext(ctx, "go", "list", "-f", moduleListFormat, ".") 134 cmd.Env = append(os.Environ(), "GO111MODULE=on") 135 cmd.Env = append(cmd.Env, extraEnv...) 136 137 output, err := cmd.Output() 138 if err != nil { 139 return nil, wrapExitErr(err, "'go list' failed") 140 } 141 142 var moduleInfo ModuleInfo 143 if err := json.Unmarshal(output, &moduleInfo); err != nil { 144 return nil, errors.Wrap(err, "failed to unmarshal output from 'go list'") 145 } 146 147 return &moduleInfo, nil 148 }