github.com/anchore/syft@v1.4.2-0.20240516191711-1bec1fc5d397/syft/pkg/cataloger/golang/package.go (about)

     1  package golang
     2  
     3  import (
     4  	"runtime/debug"
     5  	"strings"
     6  
     7  	"github.com/anchore/packageurl-go"
     8  	"github.com/anchore/syft/internal/log"
     9  	"github.com/anchore/syft/syft/file"
    10  	"github.com/anchore/syft/syft/pkg"
    11  )
    12  
    13  func (c *goBinaryCataloger) newGoBinaryPackage(resolver file.Resolver, dep *debug.Module, mainModule, goVersion, architecture string, buildSettings pkg.KeyValues, cryptoSettings []string, locations ...file.Location) pkg.Package {
    14  	if dep.Replace != nil {
    15  		dep = dep.Replace
    16  	}
    17  
    18  	licenses, err := c.licenses.getLicenses(resolver, dep.Path, dep.Version)
    19  	if err != nil {
    20  		log.Tracef("error getting licenses for golang package: %s %v", dep.Path, err)
    21  	}
    22  
    23  	p := pkg.Package{
    24  		Name:      dep.Path,
    25  		Version:   dep.Version,
    26  		Licenses:  pkg.NewLicenseSet(licenses...),
    27  		PURL:      packageURL(dep.Path, dep.Version),
    28  		Language:  pkg.Go,
    29  		Type:      pkg.GoModulePkg,
    30  		Locations: file.NewLocationSet(locations...),
    31  		Metadata: pkg.GolangBinaryBuildinfoEntry{
    32  			GoCompiledVersion: goVersion,
    33  			H1Digest:          dep.Sum,
    34  			Architecture:      architecture,
    35  			BuildSettings:     buildSettings,
    36  			MainModule:        mainModule,
    37  			GoCryptoSettings:  cryptoSettings,
    38  		},
    39  	}
    40  
    41  	p.SetID()
    42  
    43  	return p
    44  }
    45  
    46  func packageURL(moduleName, moduleVersion string) string {
    47  	// source: https://github.com/package-url/purl-spec/blob/master/PURL-TYPES.rst#golang
    48  	// note: "The version is often empty when a commit is not specified and should be the commit in most cases when available."
    49  
    50  	fields := strings.Split(moduleName, "/")
    51  	if len(fields) == 0 {
    52  		return ""
    53  	}
    54  
    55  	namespace := ""
    56  	name := ""
    57  	// The subpath is used to point to a subpath inside a package (e.g. pkg:golang/google.golang.org/genproto#googleapis/api/annotations)
    58  	subpath := ""
    59  
    60  	switch len(fields) {
    61  	case 1:
    62  		name = fields[0]
    63  	case 2:
    64  		name = fields[1]
    65  		namespace = fields[0]
    66  	default:
    67  		name = fields[2]
    68  		namespace = strings.Join(fields[0:2], "/")
    69  		subpath = strings.Join(fields[3:], "/")
    70  	}
    71  
    72  	return packageurl.NewPackageURL(
    73  		packageurl.TypeGolang,
    74  		namespace,
    75  		name,
    76  		moduleVersion,
    77  		nil,
    78  		subpath,
    79  	).ToString()
    80  }