github.com/anchore/syft@v1.38.2/syft/pkg/cataloger/nix/package.go (about) 1 package nix 2 3 import ( 4 "path" 5 "sort" 6 7 "github.com/anchore/packageurl-go" 8 "github.com/anchore/syft/syft/file" 9 "github.com/anchore/syft/syft/pkg" 10 ) 11 12 type nixStorePackage struct { 13 Location *file.Location 14 Files []string 15 *derivationFile 16 nixStorePath 17 } 18 19 func newNixStorePackage(pp nixStorePackage, catalogerName string) pkg.Package { 20 locations := file.NewLocationSet(pp.Location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation)) 21 22 var derivationPath string 23 if pp.derivationFile != nil { 24 derivationPath = pp.derivationFile.Location.RealPath 25 locations.Add(pp.derivationFile.Location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.SupportingEvidenceAnnotation)) 26 } 27 28 p := pkg.Package{ 29 Name: pp.Name, 30 Version: pp.Version, 31 FoundBy: catalogerName, 32 Locations: locations, 33 Type: pkg.NixPkg, 34 PURL: packageURL(pp.nixStorePath, derivationPath), 35 Metadata: pkg.NixStoreEntry{ 36 Path: pp.StorePath, 37 Derivation: newDerivation(pp.derivationFile), 38 OutputHash: pp.OutputHash, 39 Output: pp.Output, 40 Files: pp.Files, 41 }, 42 } 43 44 p.SetID() 45 46 return p 47 } 48 49 func newDBPackage(entry *dbPackageEntry, catalogerName string) pkg.Package { 50 locations := file.NewLocationSet( 51 entry.Location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), 52 file.NewLocation(entry.StorePath).WithAnnotation(pkg.EvidenceAnnotationKey, pkg.SupportingEvidenceAnnotation), 53 ) 54 if entry.derivationFile != nil { 55 locations.Add(entry.derivationFile.Location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.SupportingEvidenceAnnotation)) 56 } 57 58 p := pkg.Package{ 59 Name: entry.Name, 60 Version: entry.Version, 61 FoundBy: catalogerName, 62 Locations: locations, 63 Type: pkg.NixPkg, 64 PURL: packageURL(entry.nixStorePath, entry.DeriverPath), 65 Metadata: pkg.NixStoreEntry{ 66 Path: entry.StorePath, 67 Derivation: newDerivation(entry.derivationFile), 68 OutputHash: entry.OutputHash, 69 Output: entry.Output, 70 Files: entry.Files, 71 }, 72 } 73 74 p.SetID() 75 76 return p 77 } 78 79 func newDerivation(df *derivationFile) pkg.NixDerivation { 80 if df == nil { 81 return pkg.NixDerivation{} 82 } 83 84 var inputDerivations []pkg.NixDerivationReference 85 for drvPath, names := range df.InputDerivations { 86 sort.Strings(names) 87 inputDerivations = append(inputDerivations, pkg.NixDerivationReference{ 88 Path: drvPath, 89 Outputs: names, 90 }) 91 } 92 sort.Slice(inputDerivations, func(i, j int) bool { 93 return inputDerivations[i].Path < inputDerivations[j].Path 94 }) 95 96 sources := df.InputSources 97 sort.Strings(sources) 98 99 return pkg.NixDerivation{ 100 Path: df.Location.RealPath, 101 System: df.Platform, 102 InputDerivations: inputDerivations, 103 InputSources: sources, 104 } 105 } 106 107 func packageURL(storePath nixStorePath, drvPath string) string { 108 var qualifiers packageurl.Qualifiers 109 if storePath.Output != "" { 110 // since there is no nix pURL type yet, this is a guess, however, it is reasonable to assume that 111 // if only a single output is installed the pURL should be able to express this. 112 qualifiers = append(qualifiers, 113 packageurl.Qualifier{ 114 Key: "output", 115 Value: storePath.Output, 116 }, 117 ) 118 } 119 if storePath.OutputHash != "" { 120 qualifiers = append(qualifiers, 121 packageurl.Qualifier{ 122 Key: "outputhash", 123 Value: storePath.OutputHash, 124 }, 125 ) 126 } 127 128 if drvPath != "" { 129 qualifiers = append(qualifiers, 130 packageurl.Qualifier{ 131 Key: "drvpath", 132 Value: path.Base(drvPath), 133 }, 134 ) 135 } 136 pURL := packageurl.NewPackageURL( 137 // TODO: nix pURL type has not been accepted yet (only proposed at this time) 138 "nix", 139 "", 140 storePath.Name, 141 storePath.Version, 142 qualifiers, 143 "") 144 return pURL.ToString() 145 }