github.com/google/osv-scalibr@v0.4.1/extractor/filesystem/os/purl/purl.go (about) 1 // Copyright 2025 Google LLC 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 // Package purl converts OS package details into PackageURLs. 16 package purl 17 18 import ( 19 "strconv" 20 "strings" 21 22 apkmeta "github.com/google/osv-scalibr/extractor/filesystem/os/apk/metadata" 23 cosmeta "github.com/google/osv-scalibr/extractor/filesystem/os/cos/metadata" 24 dpkgmeta "github.com/google/osv-scalibr/extractor/filesystem/os/dpkg/metadata" 25 flatpakmeta "github.com/google/osv-scalibr/extractor/filesystem/os/flatpak/metadata" 26 nixmeta "github.com/google/osv-scalibr/extractor/filesystem/os/nix/metadata" 27 pacmanmeta "github.com/google/osv-scalibr/extractor/filesystem/os/pacman/metadata" 28 portagemeta "github.com/google/osv-scalibr/extractor/filesystem/os/portage/metadata" 29 rpmmeta "github.com/google/osv-scalibr/extractor/filesystem/os/rpm/metadata" 30 snapmeta "github.com/google/osv-scalibr/extractor/filesystem/os/snap/metadata" 31 "github.com/google/osv-scalibr/purl" 32 ) 33 34 // MakePackageURL returns a package URL that follows the specific OS's spec 35 // and includes OS version info. 36 func MakePackageURL(name string, version string, purlType string, metadata any) *purl.PackageURL { 37 q := map[string]string{} 38 var namespace string 39 switch m := metadata.(type) { 40 case *apkmeta.Metadata: 41 namespace = m.ToNamespace() 42 name = strings.ToLower(name) 43 if distro := m.ToDistro(); distro != "" { 44 q[purl.Distro] = distro 45 } 46 if m.OriginName != "" { 47 q[purl.Origin] = m.OriginName 48 } 49 if m.Architecture != "" { 50 q[purl.Arch] = m.Architecture 51 } 52 53 case *cosmeta.Metadata: 54 if distro := m.ToDistro(); distro != "" { 55 q[purl.Distro] = distro 56 } 57 58 case *dpkgmeta.Metadata: 59 namespace = m.ToNamespace() 60 name = m.PackageName 61 62 if distro := m.ToDistro(); distro != "" { 63 q[purl.Distro] = distro 64 } 65 if m.SourceName != "" { 66 q[purl.Source] = m.SourceName 67 } 68 if m.SourceVersion != "" { 69 q[purl.SourceVersion] = m.SourceVersion 70 } 71 if m.Architecture != "" { 72 q[purl.Arch] = m.Architecture 73 } 74 75 case *flatpakmeta.Metadata: 76 namespace = m.ToNamespace() 77 if distro := m.ToDistro(); distro != "" { 78 q[purl.Distro] = distro 79 } 80 81 case *rpmmeta.Metadata: 82 namespace = m.ToNamespace() 83 if m.Epoch > 0 { 84 q[purl.Epoch] = strconv.Itoa(m.Epoch) 85 } 86 if distro := m.ToDistro(); distro != "" { 87 q[purl.Distro] = distro 88 } 89 if m.SourceRPM != "" { 90 q[purl.SourceRPM] = m.SourceRPM 91 } 92 if m.Architecture != "" { 93 q[purl.Arch] = m.Architecture 94 } 95 96 case *snapmeta.Metadata: 97 namespace = m.ToNamespace() 98 if distro := m.ToDistro(); distro != "" { 99 q[purl.Distro] = distro 100 } 101 102 case *pacmanmeta.Metadata: 103 namespace = m.ToNamespace() 104 name = m.PackageName 105 if distro := m.ToDistro(); distro != "" { 106 q[purl.Distro] = distro 107 } 108 if m.PackageDependencies != "" { 109 q[purl.PackageDependencies] = m.PackageDependencies 110 } 111 112 case *portagemeta.Metadata: 113 namespace = m.ToNamespace() 114 name = m.PackageName 115 version = m.PackageVersion 116 if distro := m.ToDistro(); distro != "" { 117 q[purl.Distro] = distro 118 } 119 120 case *nixmeta.Metadata: 121 if distro := m.ToDistro(); distro != "" { 122 q[purl.Distro] = distro 123 } 124 125 default: 126 return nil 127 } 128 129 return &purl.PackageURL{ 130 Type: purlType, 131 Name: name, 132 Namespace: namespace, 133 Version: version, 134 Qualifiers: purl.QualifiersFromMap(q), 135 } 136 }