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

     1  package erlang
     2  
     3  import (
     4  	"context"
     5  
     6  	"github.com/anchore/syft/internal/log"
     7  	"github.com/anchore/syft/syft/artifact"
     8  	"github.com/anchore/syft/syft/file"
     9  	"github.com/anchore/syft/syft/pkg"
    10  	"github.com/anchore/syft/syft/pkg/cataloger/generic"
    11  )
    12  
    13  // parseRebarLock parses a rebar.lock and returns the discovered Elixir packages.
    14  //
    15  //nolint:funlen
    16  func parseRebarLock(_ context.Context, _ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
    17  	doc, err := parseErlang(reader)
    18  	if err != nil {
    19  		return nil, nil, err
    20  	}
    21  
    22  	pkgMap := make(map[string]*pkg.Package)
    23  
    24  	// rebar.lock structure is:
    25  	// [
    26  	//   ["version", [
    27  	//     [<<"package-name">>, ["version-type", "version"]...
    28  	//   ],
    29  	//   [
    30  	//     [pkg_hash, [
    31  	//       [<<"package-name">>, <<"package-hash">>]
    32  	//     ],
    33  	//     [pkg_hash_ext, [
    34  	//       [<<"package-name">>, <<"package-hash">>]
    35  	//     ]
    36  	//   ]
    37  	// ]
    38  
    39  	versions := doc.Get(0)
    40  	deps := versions.Get(1)
    41  
    42  	for _, dep := range deps.Slice() {
    43  		name := dep.Get(0).String()
    44  		versionNode := dep.Get(1)
    45  		versionType := versionNode.Get(0).String()
    46  		version := versionNode.Get(2).String()
    47  
    48  		// capture git hashes if no version specified
    49  		if versionType == "git" {
    50  			version = versionNode.Get(2).Get(1).String()
    51  		}
    52  
    53  		p := newPackageFromRebar(
    54  			pkg.ErlangRebarLockEntry{
    55  				Name:    name,
    56  				Version: version,
    57  			},
    58  			reader.Location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation),
    59  		)
    60  
    61  		pkgMap[name] = &p
    62  	}
    63  
    64  	hashes := doc.Get(1)
    65  	for _, hashStruct := range hashes.Slice() {
    66  		hashType := hashStruct.Get(0).String()
    67  
    68  		for _, hashValue := range hashStruct.Get(1).Slice() {
    69  			name := hashValue.Get(0).String()
    70  			hash := hashValue.Get(1).String()
    71  
    72  			sourcePkg := pkgMap[name]
    73  			if sourcePkg == nil {
    74  				log.WithFields("package", name).Warn("unable find source package")
    75  				continue
    76  			}
    77  			metadata, ok := sourcePkg.Metadata.(pkg.ErlangRebarLockEntry)
    78  			if !ok {
    79  				log.WithFields("package", name).Warn("unable to extract rebar.lock metadata to add hash metadata")
    80  				continue
    81  			}
    82  
    83  			switch hashType {
    84  			case "pkg_hash":
    85  				metadata.PkgHash = hash
    86  			case "pkg_hash_ext":
    87  				metadata.PkgHashExt = hash
    88  			}
    89  			sourcePkg.Metadata = metadata
    90  		}
    91  	}
    92  
    93  	var packages []pkg.Package
    94  	for _, p := range pkgMap {
    95  		p.SetID()
    96  		packages = append(packages, *p)
    97  	}
    98  	return packages, nil, nil
    99  }
   100  
   101  // integrity check
   102  var _ generic.Parser = parseRebarLock