github.com/anchore/syft@v1.38.2/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/syft/file"
     9  	"github.com/anchore/syft/syft/pkg"
    10  )
    11  
    12  func (c *goBinaryCataloger) newGoBinaryPackage(dep *debug.Module, m pkg.GolangBinaryBuildinfoEntry, licenses []pkg.License, locations ...file.Location) pkg.Package {
    13  	// Similar to syft/pkg/cataloger/golang/parse_go_mod.go logic - use original path for relative replacements
    14  	finalPath := dep.Path
    15  	if dep.Replace != nil {
    16  		if strings.HasPrefix(dep.Replace.Path, ".") || strings.HasPrefix(dep.Replace.Path, "/") {
    17  			finalPath = dep.Path
    18  		} else {
    19  			finalPath = dep.Replace.Path
    20  		}
    21  		dep = dep.Replace
    22  	}
    23  
    24  	version := dep.Version
    25  	if version == devel {
    26  		// this is a special case for the "devel" version, which is used when the module is built from source
    27  		// and there is no vcs tag info available. In this case, we remove the placeholder to indicate
    28  		// we don't know the version.
    29  		version = ""
    30  	}
    31  
    32  	p := pkg.Package{
    33  		Name:      finalPath,
    34  		Version:   version,
    35  		Licenses:  pkg.NewLicenseSet(licenses...),
    36  		PURL:      packageURL(finalPath, version),
    37  		Language:  pkg.Go,
    38  		Type:      pkg.GoModulePkg,
    39  		Locations: file.NewLocationSet(locations...),
    40  		Metadata:  m,
    41  	}
    42  
    43  	p.SetID()
    44  
    45  	return p
    46  }
    47  
    48  func newBinaryMetadata(dep *debug.Module, mainModule, goVersion, architecture string, buildSettings pkg.KeyValues, cryptoSettings, experiments []string) pkg.GolangBinaryBuildinfoEntry {
    49  	if dep.Replace != nil {
    50  		dep = dep.Replace
    51  	}
    52  
    53  	return pkg.GolangBinaryBuildinfoEntry{
    54  		GoCompiledVersion: goVersion,
    55  		H1Digest:          dep.Sum,
    56  		Architecture:      architecture,
    57  		BuildSettings:     buildSettings,
    58  		MainModule:        mainModule,
    59  		GoCryptoSettings:  cryptoSettings,
    60  		GoExperiments:     experiments,
    61  	}
    62  }
    63  
    64  func packageURL(moduleName, moduleVersion string) string {
    65  	// source: https://github.com/package-url/purl-spec/blob/master/PURL-TYPES.rst#golang
    66  	// note: "The version is often empty when a commit is not specified and should be the commit in most cases when available."
    67  
    68  	fields := strings.Split(moduleName, "/")
    69  	if len(fields) == 0 {
    70  		return ""
    71  	}
    72  
    73  	namespace := ""
    74  	name := ""
    75  	// The subpath is used to point to a subpath inside a package (e.g. pkg:golang/google.golang.org/genproto#googleapis/api/annotations)
    76  	subpath := ""
    77  
    78  	switch len(fields) {
    79  	case 1:
    80  		name = fields[0]
    81  	case 2:
    82  		name = fields[1]
    83  		namespace = fields[0]
    84  	default:
    85  		name = fields[2]
    86  		namespace = strings.Join(fields[0:2], "/")
    87  		subpath = strings.Join(fields[3:], "/")
    88  	}
    89  
    90  	return packageurl.NewPackageURL(
    91  		packageurl.TypeGolang,
    92  		namespace,
    93  		name,
    94  		moduleVersion,
    95  		nil,
    96  		subpath,
    97  	).ToString()
    98  }