github.com/vijaypunugubati/fabric@v2.0.0-alpha.0.20200109185758-70466159f5b3+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  // 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 pacakge %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  }