Class: Bibliothecary::MultiParsers::Spdx
- Inherits:
-
Object
- Object
- Bibliothecary::MultiParsers::Spdx
- Extended by:
- Analyser::TryCache
- Includes:
- Analyser
- Defined in:
- lib/bibliothecary/multi_parsers/spdx.rb
Constant Summary collapse
- WELLFORMED_LINE_REGEXP =
e.g. ‘SomeText:’ (allowing for leading whitespace)
/^\s*[a-zA-Z]+:/- PACKAGE_NAME_REGEXP =
e.g. ‘PackageName: (allowing for excessive whitespace)
/^\s*PackageName:\s*(.*)/- PACKAGE_VERSION_REGEXP =
e.g. ‘PackageVersion:’ (allowing for excessive whitespace)
/^\s*PackageVersion:\s*(.*)/- PURL_REGEXP =
e.g. “ExternalRef: PACKAGE-MANAGER purl (allowing for excessive whitespace)
/^\s*ExternalRef:\s*PACKAGE[-|_]MANAGER\s*purl\s*(.*)/- NoEntries =
Class.new(StandardError)
- MalformedFile =
Class.new(StandardError)
Class Method Summary collapse
- .add_entry(entries:, platform:, purl_name:, spdx_name:, purl_version:, spdx_version:, source: nil, purl_type: nil) ⇒ Object
- .mapping ⇒ Object
- .parse_spdx_json(file_contents, options: {}) ⇒ Object
- .parse_spdx_json_file_contents(file_contents, source = nil) ⇒ Object
- .parse_spdx_tag_value(file_contents, options: {}) ⇒ Object
- .parse_spdx_tag_value_file_contents(file_contents, source = nil) ⇒ Object
- .platform_name ⇒ Object
- .skip_tag_value_line?(stripped_line) ⇒ Boolean
Methods included from Analyser::TryCache
Methods included from Analyser
create_analysis, create_error_analysis, included
Class Method Details
.add_entry(entries:, platform:, purl_name:, spdx_name:, purl_version:, spdx_version:, source: nil, purl_type: nil) ⇒ Object
146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 |
# File 'lib/bibliothecary/multi_parsers/spdx.rb', line 146 def self.add_entry(entries:, platform:, purl_name:, spdx_name:, purl_version:, spdx_version:, source: nil, purl_type: nil) package_name = purl_name || spdx_name package_version = purl_version || spdx_version return unless package_name && package_version return unless platform entries << Dependency.new( platform: platform ? platform.to_s : purl_type, name: package_name, requirement: package_version, type: "lockfile", source: source ) end |
.mapping ⇒ Object
31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
# File 'lib/bibliothecary/multi_parsers/spdx.rb', line 31 def self.mapping { match_extension(".spdx") => { kind: "lockfile", parser: :parse_spdx_tag_value, ungroupable: true, }, match_extension(".spdx.json") => { kind: "lockfile", parser: :parse_spdx_json, ungroupable: true, }, } end |
.parse_spdx_json(file_contents, options: {}) ⇒ Object
109 110 111 112 113 114 115 116 117 118 119 120 |
# File 'lib/bibliothecary/multi_parsers/spdx.rb', line 109 def self.parse_spdx_json(file_contents, options: {}) entries = try_cache(, [:filename]) do parse_spdx_json_file_contents( file_contents, .fetch(:filename, nil) ) end raise NoEntries if entries.empty? Bibliothecary::ParserResult.new(dependencies: entries.to_a) end |
.parse_spdx_json_file_contents(file_contents, source = nil) ⇒ Object
122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 |
# File 'lib/bibliothecary/multi_parsers/spdx.rb', line 122 def self.parse_spdx_json_file_contents(file_contents, source = nil) entries = Set.new manifest = JSON.parse(file_contents) manifest["packages"]&.each do |package| spdx_name = package["name"] spdx_version = package["versionInfo"] first_purl_string = package["externalRefs"]&.find { |ref| ref["referenceType"] == "purl" }&.dig("referenceLocator") purl = first_purl_string && PackageURL.parse(first_purl_string) purl_type = purl&.type # Use the mapped purl->bibliothecary platform, or else fall back to original platform itself. platform = PurlUtil::PURL_TYPE_MAPPING.fetch(purl_type, purl_type) purl_name = PurlUtil.full_name(purl) purl_version = purl&.version add_entry(entries: entries, platform: platform, purl_name: purl_name, spdx_name: spdx_name, purl_version: purl_version, spdx_version: spdx_version, source: source, purl_type: purl_type) end entries end |
.parse_spdx_tag_value(file_contents, options: {}) ⇒ Object
50 51 52 53 54 55 56 57 58 59 60 61 |
# File 'lib/bibliothecary/multi_parsers/spdx.rb', line 50 def self.parse_spdx_tag_value(file_contents, options: {}) entries = try_cache(, [:filename]) do parse_spdx_tag_value_file_contents( file_contents, .fetch(:filename, nil) ) end raise NoEntries if entries.empty? Bibliothecary::ParserResult.new(dependencies: entries.to_a) end |
.parse_spdx_tag_value_file_contents(file_contents, source = nil) ⇒ Object
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 |
# File 'lib/bibliothecary/multi_parsers/spdx.rb', line 63 def self.parse_spdx_tag_value_file_contents(file_contents, source = nil) entries = Set.new spdx_name = spdx_version = platform = purl_name = purl_version = purl_type = nil file_contents.each_line do |line| stripped_line = line.strip next if skip_tag_value_line?(stripped_line) raise MalformedFile unless stripped_line.match?(WELLFORMED_LINE_REGEXP) if (match = stripped_line.match(PACKAGE_NAME_REGEXP)) # Per the spec: # > A new package Information section is denoted by the package name (7.1) field. add_entry(entries: entries, platform: platform, purl_name: purl_name, spdx_name: spdx_name, purl_version: purl_version, spdx_version: spdx_version, source: source, purl_type: purl_type) # reset for this new package spdx_name = spdx_version = platform = purl_name = purl_version = purl_type = nil # capture the new package's name spdx_name = match[1] elsif (match = stripped_line.match(PACKAGE_VERSION_REGEXP)) spdx_version = match[1] elsif (match = stripped_line.match(PURL_REGEXP)) purl = PackageURL.parse(match[1]) purl_type ||= purl&.type # Use the mapped purl->bibliothecary platform, or else fall back to original platform itself. platform = PurlUtil::PURL_TYPE_MAPPING.fetch(purl_type, purl_type) purl_name ||= PurlUtil.full_name(purl) purl_version ||= purl&.version end end add_entry(entries: entries, platform: platform, purl_name: purl_name, spdx_name: spdx_name, purl_version: purl_version, spdx_version: spdx_version, source: source, purl_type: purl_type) entries end |
.platform_name ⇒ Object
46 47 48 |
# File 'lib/bibliothecary/multi_parsers/spdx.rb', line 46 def self.platform_name raise "Spdx is a multi-parser and does not have a platform name." end |
.skip_tag_value_line?(stripped_line) ⇒ Boolean
104 105 106 107 |
# File 'lib/bibliothecary/multi_parsers/spdx.rb', line 104 def self.skip_tag_value_line?(stripped_line) # Ignore blank lines and comments stripped_line.empty? || stripped_line.start_with?("#") end |