github.com/anchore/syft@v1.38.2/syft/pkg/cataloger/elixir/parse_mix_lock.go (about)

     1  package elixir
     2  
     3  import (
     4  	"bufio"
     5  	"context"
     6  	"errors"
     7  	"fmt"
     8  	"io"
     9  	"regexp"
    10  
    11  	"github.com/anchore/syft/internal/log"
    12  	"github.com/anchore/syft/internal/unknown"
    13  	"github.com/anchore/syft/syft/artifact"
    14  	"github.com/anchore/syft/syft/file"
    15  	"github.com/anchore/syft/syft/pkg"
    16  	"github.com/anchore/syft/syft/pkg/cataloger/generic"
    17  )
    18  
    19  // integrity check
    20  var _ generic.Parser = parseMixLock
    21  
    22  var mixLockDelimiter = regexp.MustCompile(`[%{}\n" ,:]+`)
    23  
    24  // parseMixLock parses a mix.lock and returns the discovered Elixir packages.
    25  func parseMixLock(_ context.Context, _ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
    26  	var errs error
    27  	r := bufio.NewReader(reader)
    28  
    29  	var packages []pkg.Package
    30  	lineNum := 0
    31  	for {
    32  		lineNum++
    33  		line, err := r.ReadString('\n')
    34  		switch {
    35  		case errors.Is(err, io.EOF):
    36  			if errs == nil {
    37  				errs = unknown.IfEmptyf(packages, "unable to determine packages")
    38  			}
    39  			return packages, nil, errs
    40  		case err != nil:
    41  			return nil, nil, fmt.Errorf("failed to parse mix.lock file: %w", err)
    42  		}
    43  		tokens := mixLockDelimiter.Split(line, -1)
    44  		if len(tokens) < 6 {
    45  			errs = unknown.Appendf(errs, reader, "unable to read mix lock line %d: %s", lineNum, line)
    46  			continue
    47  		}
    48  		name, version, hash, hashExt := tokens[1], tokens[4], tokens[5], tokens[len(tokens)-2]
    49  
    50  		if name == "" {
    51  			log.WithFields("path", reader.RealPath).Debug("skipping empty package name from mix.lock file")
    52  			errs = unknown.Appendf(errs, reader, "skipping empty package name from mix.lock file, for line: %d: %s", lineNum, line)
    53  			continue
    54  		}
    55  
    56  		packages = append(packages,
    57  			newPackage(
    58  				pkg.ElixirMixLockEntry{
    59  					Name:       name,
    60  					Version:    version,
    61  					PkgHash:    hash,
    62  					PkgHashExt: hashExt,
    63  				},
    64  				reader.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation),
    65  			),
    66  		)
    67  	}
    68  }