github.com/vchain-us/vcn@v0.9.11-0.20210921212052-a2484d23c0b3/pkg/extractor/gocom/gocom.go (about)

     1  /*
     2   * Copyright (c) 2021 CodeNotary, Inc. All Rights Reserved.
     3   * This software is released under GPL3.
     4   * The full license information can be found under:
     5   * https://www.gnu.org/licenses/gpl-3.0.en.html
     6   *
     7   */
     8  
     9  package gocom
    10  
    11  import (
    12  	"encoding/json"
    13  	"fmt"
    14  	"os/exec"
    15  	"strings"
    16  
    17  	"github.com/vchain-us/vcn/pkg/api"
    18  	"github.com/vchain-us/vcn/pkg/bom/artifact"
    19  	"github.com/vchain-us/vcn/pkg/bom/golang"
    20  	"github.com/vchain-us/vcn/pkg/extractor"
    21  	"github.com/vchain-us/vcn/pkg/uri"
    22  )
    23  
    24  // Scheme for Go component
    25  const Scheme = "gocom"
    26  
    27  type modInfo struct {
    28  	Path    string
    29  	Version string
    30  	Sum     string
    31  }
    32  
    33  var modInfoArgs = []string{"mod", "download", "-json"}
    34  
    35  // Artifact returns a file *api.Artifact from a given uri
    36  func Artifact(u *uri.URI, options ...extractor.Option) ([]*api.Artifact, error) {
    37  	if u.Scheme != Scheme {
    38  		return nil, nil
    39  	}
    40  
    41  	path := strings.TrimPrefix(u.Opaque, "//")
    42  
    43  	buf, err := exec.Command("go", append(modInfoArgs, path)...).Output()
    44  	if err != nil {
    45  		if len(buf) > 0 {
    46  			// Error field in json may contain error message
    47  			var fields map[string]string
    48  			if nil != json.Unmarshal(buf, &fields) {
    49  				// output isn't a valid JSON - return original execution error
    50  				return nil, fmt.Errorf("cannot get Go module: %w", err)
    51  			}
    52  			errMsg, ok := fields["Error"]
    53  			if !ok {
    54  				return nil, fmt.Errorf("cannot get Go module: %w", err)
    55  			}
    56  			return nil, fmt.Errorf("cannot get Go module: %s", errMsg)
    57  		}
    58  	}
    59  
    60  	var info modInfo
    61  	err = json.Unmarshal(buf, &info)
    62  	if err != nil {
    63  		return nil, fmt.Errorf("cannot parse Go command output: %w", err)
    64  	}
    65  
    66  	hash, hashType, err := golang.ModHash(info.Sum)
    67  	if err != nil {
    68  		return nil, fmt.Errorf("cannot decode module hash: %w", err)
    69  	}
    70  
    71  	return []*api.Artifact{artifact.ToApiArtifact(golang.AssetType, info.Path, info.Version, hash, hashType)}, nil
    72  }