github.com/google/osv-scalibr@v0.4.1/semantic/parse.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 semantic provides version parsing and comparison for various ecosystems, 16 // matching the native versioning rules of each ecosystem. 17 package semantic 18 19 import ( 20 "errors" 21 "fmt" 22 "strings" 23 ) 24 25 // ErrUnsupportedEcosystem is returned for unsupported ecosystems. 26 var ErrUnsupportedEcosystem = errors.New("unsupported ecosystem") 27 28 // ErrInvalidVersion is returned for malformed version strings. 29 var ErrInvalidVersion = errors.New("invalid version") 30 31 // MustParse is like Parse but panics if the ecosystem is not supported. 32 func MustParse(str string, ecosystem string) Version { 33 v, err := Parse(str, ecosystem) 34 35 if err != nil { 36 panic(err) 37 } 38 39 return v 40 } 41 42 // Parse attempts to parse the given string as a version for the specified ecosystem, 43 // returning an ErrUnsupportedEcosystem error if the ecosystem is not supported. 44 func Parse(str string, ecosystem string) (Version, error) { 45 // Remove the version suffix from the ecosystem name. 46 parts := strings.Split(ecosystem, ":") 47 if len(parts) > 1 { 48 ecosystem = parts[0] 49 } 50 51 // TODO(#457): support more ecosystems 52 switch ecosystem { 53 case "AlmaLinux": 54 return parseRedHatVersion(str), nil 55 case "Alpaquita": 56 return parseAlpineVersion(str) 57 case "Alpine": 58 return parseAlpineVersion(str) 59 case "BellSoft Hardened Containers": 60 return parseAlpineVersion(str) 61 case "Bitnami": 62 return parseSemverVersion(str), nil 63 case "Bioconductor": 64 return parseSemverVersion(str), nil 65 case "Chainguard": 66 return parseAlpineVersion(str) 67 case "ConanCenter": 68 return parseSemverVersion(str), nil 69 case "CRAN": 70 return parseCRANVersion(str) 71 case "crates.io": 72 return parseSemverVersion(str), nil 73 case "Debian": 74 return parseDebianVersion(str) 75 case "GHC": 76 return parseSemverVersion(str), nil 77 case "Go": 78 return parseSemverVersion(str), nil 79 case "Hackage": 80 return parseHackageVersion(str) 81 case "Hex": 82 return parseSemverVersion(str), nil 83 case "Julia": 84 return parseSemverVersion(str), nil 85 case "Mageia": 86 return parseRedHatVersion(str), nil 87 case "Maven": 88 return parseMavenVersion(str), nil 89 case "MinimOS": 90 return parseAlpineVersion(str) 91 case "npm": 92 return parseSemverVersion(str), nil 93 case "NuGet": 94 return parseNuGetVersion(str), nil 95 case "openEuler": 96 return parseRedHatVersion(str), nil 97 case "openSUSE": 98 return parseRedHatVersion(str), nil 99 case "Packagist": 100 return parsePackagistVersion(str), nil 101 case "Pub": 102 return parsePubVersion(str), nil 103 case "PyPI": 104 return parsePyPIVersion(str) 105 case "Red Hat": 106 return parseRedHatVersion(str), nil 107 case "Rocky Linux": 108 return parseRedHatVersion(str), nil 109 case "RubyGems": 110 return parseRubyGemsVersion(str), nil 111 case "SUSE": 112 return parseRedHatVersion(str), nil 113 case "SwiftURL": 114 return parseSemverVersion(str), nil 115 case "Ubuntu": 116 return parseDebianVersion(str) 117 case "Wolfi": 118 return parseAlpineVersion(str) 119 } 120 121 return nil, fmt.Errorf("%w %s", ErrUnsupportedEcosystem, ecosystem) 122 }