github.com/Hnampk/my-fabric@v0.0.0-20201028083322-75069da399c0/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 // PackageInfo is the subset of data from `go list -deps -json` that's 25 // necessary to calculate chaincode package dependencies. 26 type PackageInfo struct { 27 ImportPath string 28 Dir string 29 GoFiles []string 30 Goroot bool 31 CFiles []string 32 CgoFiles []string 33 HFiles []string 34 SFiles []string 35 IgnoredGoFiles []string 36 Incomplete bool 37 } 38 39 func (p PackageInfo) Files() []string { 40 var files []string 41 files = append(files, p.GoFiles...) 42 files = append(files, p.CFiles...) 43 files = append(files, p.CgoFiles...) 44 files = append(files, p.HFiles...) 45 files = append(files, p.SFiles...) 46 files = append(files, p.IgnoredGoFiles...) 47 return files 48 } 49 50 // gopathDependencyPackageInfo extracts dependency information for 51 // specified package. 52 func gopathDependencyPackageInfo(goos, goarch, pkg string) ([]PackageInfo, error) { 53 ctx, cancel := context.WithTimeout(context.Background(), listTimeout) 54 defer cancel() 55 56 cmd := exec.CommandContext(ctx, "go", "list", "-deps", "-json", pkg) 57 cmd.Env = append(os.Environ(), "GOOS="+goos, "GOARCH="+goarch) 58 59 stdout, err := cmd.StdoutPipe() 60 if err != nil { 61 return nil, wrapExitErr(err, "'go list -deps' failed") 62 } 63 decoder := json.NewDecoder(stdout) 64 65 err = cmd.Start() 66 if err != nil { 67 return nil, err 68 } 69 70 var list []PackageInfo 71 for { 72 var packageInfo PackageInfo 73 err := decoder.Decode(&packageInfo) 74 if err == io.EOF { 75 break 76 } 77 if err != nil { 78 return nil, err 79 } 80 if packageInfo.Incomplete { 81 return nil, fmt.Errorf("failed to calculate dependencies: incomplete package: %s", packageInfo.ImportPath) 82 } 83 if packageInfo.Goroot { 84 continue 85 } 86 87 list = append(list, packageInfo) 88 } 89 90 err = cmd.Wait() 91 if err != nil { 92 return nil, errors.Wrapf(err, "listing deps for package %s failed", pkg) 93 } 94 95 return list, nil 96 } 97 98 func wrapExitErr(err error, message string) error { 99 if ee, ok := err.(*exec.ExitError); ok { 100 return errors.Wrapf(err, message+" with: %s", strings.TrimRight(string(ee.Stderr), "\n\r\t")) 101 } 102 return errors.Wrap(err, message) 103 } 104 105 type ModuleInfo struct { 106 Dir string 107 GoMod string 108 ImportPath string 109 ModulePath string 110 } 111 112 // listModuleInfo extracts module information for the curent working directory. 113 func listModuleInfo(extraEnv ...string) (*ModuleInfo, error) { 114 ctx, cancel := context.WithTimeout(context.Background(), listTimeout) 115 defer cancel() 116 117 cmd := exec.CommandContext(ctx, "go", "list", "-json", ".") 118 cmd.Env = append(os.Environ(), "GO111MODULE=on") 119 cmd.Env = append(cmd.Env, extraEnv...) 120 121 output, err := cmd.Output() 122 if err != nil { 123 return nil, wrapExitErr(err, "'go list' failed") 124 } 125 126 var moduleData struct { 127 ImportPath string 128 Module struct { 129 Dir string 130 Path string 131 GoMod string 132 } 133 } 134 135 if err := json.Unmarshal(output, &moduleData); err != nil { 136 return nil, errors.Wrap(err, "failed to unmarshal output from 'go list'") 137 } 138 139 return &ModuleInfo{ 140 Dir: moduleData.Module.Dir, 141 GoMod: moduleData.Module.GoMod, 142 ImportPath: moduleData.ImportPath, 143 ModulePath: moduleData.Module.Path, 144 }, nil 145 }