github.com/noqcks/syft@v0.0.0-20230920222752-a9e2c4e288e5/syft/pkg/cataloger/dotnet/parse_dotnet_deps.go (about)

     1  package dotnet
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"sort"
     7  
     8  	"github.com/anchore/syft/internal/log"
     9  	"github.com/anchore/syft/syft/artifact"
    10  	"github.com/anchore/syft/syft/file"
    11  	"github.com/anchore/syft/syft/pkg"
    12  	"github.com/anchore/syft/syft/pkg/cataloger/generic"
    13  )
    14  
    15  var _ generic.Parser = parseDotnetDeps
    16  
    17  type dotnetRuntimeTarget struct {
    18  	Name string `json:"name"`
    19  }
    20  
    21  type dotnetDepsTarget struct {
    22  	Dependencies map[string]string   `json:"dependencies"`
    23  	Runtime      map[string]struct{} `json:"runtime"`
    24  }
    25  type dotnetDeps struct {
    26  	RuntimeTarget dotnetRuntimeTarget                    `json:"runtimeTarget"`
    27  	Targets       map[string]map[string]dotnetDepsTarget `json:"targets"`
    28  	Libraries     map[string]dotnetDepsLibrary           `json:"libraries"`
    29  }
    30  
    31  type dotnetDepsLibrary struct {
    32  	Type     string `json:"type"`
    33  	Path     string `json:"path"`
    34  	Sha512   string `json:"sha512"`
    35  	HashPath string `json:"hashPath"`
    36  }
    37  
    38  //nolint:funlen
    39  func parseDotnetDeps(_ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
    40  	var pkgs []pkg.Package
    41  	var pkgMap = make(map[string]pkg.Package)
    42  	var relationships []artifact.Relationship
    43  
    44  	dec := json.NewDecoder(reader)
    45  
    46  	var p dotnetDeps
    47  	if err := dec.Decode(&p); err != nil {
    48  		return nil, nil, fmt.Errorf("failed to parse deps.json file: %w", err)
    49  	}
    50  
    51  	rootName := getDepsJSONFilePrefix(reader.AccessPath())
    52  	if rootName == "" {
    53  		return nil, nil, fmt.Errorf("unable to determine root package name from deps.json file: %s", reader.AccessPath())
    54  	}
    55  	var rootpkg *pkg.Package
    56  	for nameVersion, lib := range p.Libraries {
    57  		name, _ := extractNameAndVersion(nameVersion)
    58  		if lib.Type == "project" && name == rootName {
    59  			rootpkg = newDotnetDepsPackage(
    60  				nameVersion,
    61  				lib,
    62  				reader.Location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation),
    63  			)
    64  		}
    65  	}
    66  	if rootpkg == nil {
    67  		return nil, nil, fmt.Errorf("unable to determine root package from deps.json file: %s", reader.AccessPath())
    68  	}
    69  	pkgs = append(pkgs, *rootpkg)
    70  	pkgMap[createNameAndVersion(rootpkg.Name, rootpkg.Version)] = *rootpkg
    71  
    72  	var names []string
    73  	for nameVersion := range p.Libraries {
    74  		names = append(names, nameVersion)
    75  	}
    76  	// sort the names so that the order of the packages is deterministic
    77  	sort.Strings(names)
    78  
    79  	for _, nameVersion := range names {
    80  		// skip the root package
    81  		name, version := extractNameAndVersion(nameVersion)
    82  		if name == rootpkg.Name && version == rootpkg.Version {
    83  			continue
    84  		}
    85  
    86  		lib := p.Libraries[nameVersion]
    87  		dotnetPkg := newDotnetDepsPackage(
    88  			nameVersion,
    89  			lib,
    90  			reader.Location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation),
    91  		)
    92  
    93  		if dotnetPkg != nil {
    94  			pkgs = append(pkgs, *dotnetPkg)
    95  			pkgMap[nameVersion] = *dotnetPkg
    96  		}
    97  	}
    98  
    99  	for pkgNameVersion, target := range p.Targets[p.RuntimeTarget.Name] {
   100  		for depName, depVersion := range target.Dependencies {
   101  			depNameVersion := createNameAndVersion(depName, depVersion)
   102  			depPkg, ok := pkgMap[depNameVersion]
   103  			if !ok {
   104  				log.Debug("unable to find package in map", depNameVersion)
   105  				continue
   106  			}
   107  			pkg, ok := pkgMap[pkgNameVersion]
   108  			if !ok {
   109  				log.Debug("unable to find package in map", pkgNameVersion)
   110  				continue
   111  			}
   112  			rel := artifact.Relationship{
   113  				From: depPkg,
   114  				To:   pkg,
   115  				Type: artifact.DependencyOfRelationship,
   116  			}
   117  			relationships = append(relationships, rel)
   118  		}
   119  	}
   120  
   121  	pkg.Sort(pkgs)
   122  	pkg.SortRelationships(relationships)
   123  	return pkgs, relationships, nil
   124  }