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 }