bibliothecary 11.0.1 → 12.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.circleci/config.yml +2 -1
- data/.rubocop.yml +10 -2
- data/.ruby-version +1 -1
- data/CHANGELOG.md +24 -0
- data/Gemfile +16 -1
- data/Rakefile +2 -0
- data/bibliothecary.gemspec +11 -14
- data/bin/bibliothecary +2 -1
- data/bin/console +1 -0
- data/lib/bibliothecary/analyser/analysis.rb +13 -8
- data/lib/bibliothecary/analyser/determinations.rb +2 -0
- data/lib/bibliothecary/analyser/matchers.rb +17 -17
- data/lib/bibliothecary/analyser.rb +11 -8
- data/lib/bibliothecary/cli.rb +3 -1
- data/lib/bibliothecary/configuration.rb +3 -11
- data/lib/bibliothecary/dependency.rb +17 -15
- data/lib/bibliothecary/exceptions.rb +6 -2
- data/lib/bibliothecary/file_info.rb +9 -11
- data/lib/bibliothecary/multi_parsers/bundler_like_manifest.rb +13 -10
- data/lib/bibliothecary/multi_parsers/cyclonedx.rb +10 -8
- data/lib/bibliothecary/multi_parsers/dependencies_csv.rb +11 -4
- data/lib/bibliothecary/multi_parsers/json_runtime.rb +5 -2
- data/lib/bibliothecary/multi_parsers/spdx.rb +24 -19
- data/lib/bibliothecary/parsers/bower.rb +5 -3
- data/lib/bibliothecary/parsers/cargo.rb +10 -4
- data/lib/bibliothecary/parsers/cocoapods.rb +15 -11
- data/lib/bibliothecary/parsers/conda.rb +56 -33
- data/lib/bibliothecary/parsers/cpan.rb +6 -4
- data/lib/bibliothecary/parsers/cran.rb +10 -6
- data/lib/bibliothecary/parsers/dub.rb +4 -2
- data/lib/bibliothecary/parsers/elm.rb +4 -1
- data/lib/bibliothecary/parsers/go.rb +51 -43
- data/lib/bibliothecary/parsers/haxelib.rb +2 -1
- data/lib/bibliothecary/parsers/julia.rb +5 -1
- data/lib/bibliothecary/parsers/maven.rb +93 -77
- data/lib/bibliothecary/parsers/meteor.rb +2 -0
- data/lib/bibliothecary/parsers/npm.rb +97 -34
- data/lib/bibliothecary/parsers/nuget.rb +37 -28
- data/lib/bibliothecary/parsers/packagist.rb +21 -11
- data/lib/bibliothecary/parsers/pub.rb +4 -2
- data/lib/bibliothecary/parsers/pypi.rb +48 -37
- data/lib/bibliothecary/parsers/rubygems.rb +16 -12
- data/lib/bibliothecary/parsers/shard.rb +10 -7
- data/lib/bibliothecary/purl_util.rb +2 -4
- data/lib/bibliothecary/related_files_info.rb +7 -8
- data/lib/bibliothecary/runner/multi_manifest_filter.rb +5 -4
- data/lib/bibliothecary/runner.rb +12 -10
- data/lib/bibliothecary/version.rb +3 -1
- data/lib/bibliothecary.rb +7 -4
- data/lib/sdl_parser.rb +11 -6
- metadata +18 -120
- data/lib/bibliothecary/parsers/carthage.rb +0 -52
- data/lib/bibliothecary/parsers/clojars.rb +0 -38
- data/lib/bibliothecary/parsers/hackage.rb +0 -53
- data/lib/bibliothecary/parsers/hex.rb +0 -54
- data/lib/bibliothecary/parsers/swift_pm.rb +0 -35
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "yaml"
|
2
4
|
require "json"
|
3
5
|
|
@@ -74,60 +76,63 @@ module Bibliothecary
|
|
74
76
|
add_multi_parser(Bibliothecary::MultiParsers::Spdx)
|
75
77
|
add_multi_parser(Bibliothecary::MultiParsers::DependenciesCSV)
|
76
78
|
|
77
|
-
def self.parse_godep_json(file_contents, options: {})
|
79
|
+
def self.parse_godep_json(file_contents, options: {})
|
78
80
|
manifest = JSON.parse file_contents
|
79
|
-
map_dependencies(manifest, "Deps", "ImportPath", "Rev", "runtime")
|
81
|
+
map_dependencies(manifest, "Deps", "ImportPath", "Rev", "runtime", options.fetch(:filename, nil))
|
80
82
|
end
|
81
83
|
|
82
|
-
def self.parse_gpm(file_contents, options: {})
|
84
|
+
def self.parse_gpm(file_contents, options: {})
|
83
85
|
deps = []
|
84
86
|
file_contents.split("\n").each do |line|
|
85
87
|
match = line.gsub(/(\#(.*))/, "").match(GPM_REGEXP)
|
86
88
|
next unless match
|
89
|
+
|
87
90
|
deps << Dependency.new(
|
88
91
|
name: match[1].strip,
|
89
92
|
requirement: match[2].strip,
|
90
93
|
type: "runtime",
|
94
|
+
source: options.fetch(:filename, nil)
|
91
95
|
)
|
92
96
|
end
|
93
97
|
deps
|
94
98
|
end
|
95
99
|
|
96
|
-
def self.parse_govendor(file_contents, options: {})
|
97
|
-
manifest = JSON.
|
98
|
-
map_dependencies(manifest, "package", "path", "revision", "runtime")
|
100
|
+
def self.parse_govendor(file_contents, options: {})
|
101
|
+
manifest = JSON.parse file_contents
|
102
|
+
map_dependencies(manifest, "package", "path", "revision", "runtime", options.fetch(:filename, nil))
|
99
103
|
end
|
100
104
|
|
101
|
-
def self.parse_glide_yaml(file_contents, options: {})
|
105
|
+
def self.parse_glide_yaml(file_contents, options: {})
|
102
106
|
manifest = YAML.load file_contents
|
103
|
-
map_dependencies(manifest, "import", "package", "version", "runtime") +
|
104
|
-
|
107
|
+
map_dependencies(manifest, "import", "package", "version", "runtime", options.fetch(:filename, nil)) +
|
108
|
+
map_dependencies(manifest, "devImports", "package", "version", "development", options.fetch(:filename, nil))
|
105
109
|
end
|
106
110
|
|
107
|
-
def self.parse_glide_lockfile(file_contents, options: {})
|
108
|
-
|
109
|
-
|
111
|
+
def self.parse_glide_lockfile(file_contents, options: {})
|
112
|
+
# glide.lock files contain an "updated" Time field, but Ruby 3.2+ requires us to safelist that class
|
113
|
+
manifest = YAML.load file_contents, permitted_classes: [Time]
|
114
|
+
map_dependencies(manifest, "imports", "name", "version", "runtime", options.fetch(:filename, nil))
|
110
115
|
end
|
111
116
|
|
112
|
-
def self.parse_gb_manifest(file_contents, options: {})
|
117
|
+
def self.parse_gb_manifest(file_contents, options: {})
|
113
118
|
manifest = JSON.parse file_contents
|
114
|
-
map_dependencies(manifest, "dependencies", "importpath", "revision", "runtime")
|
119
|
+
map_dependencies(manifest, "dependencies", "importpath", "revision", "runtime", options.fetch(:filename, nil))
|
115
120
|
end
|
116
121
|
|
117
|
-
def self.parse_dep_toml(file_contents, options: {})
|
122
|
+
def self.parse_dep_toml(file_contents, options: {})
|
118
123
|
manifest = Tomlrb.parse file_contents
|
119
|
-
map_dependencies(manifest, "constraint", "name", "version", "runtime")
|
124
|
+
map_dependencies(manifest, "constraint", "name", "version", "runtime", options.fetch(:filename, nil))
|
120
125
|
end
|
121
126
|
|
122
|
-
def self.parse_dep_lockfile(file_contents, options: {})
|
127
|
+
def self.parse_dep_lockfile(file_contents, options: {})
|
123
128
|
manifest = Tomlrb.parse file_contents
|
124
|
-
map_dependencies(manifest, "projects", "name", "revision", "runtime")
|
129
|
+
map_dependencies(manifest, "projects", "name", "revision", "runtime", options.fetch(:filename, nil))
|
125
130
|
end
|
126
131
|
|
127
|
-
def self.parse_go_mod(file_contents, options: {})
|
128
|
-
categorized_deps = parse_go_mod_categorized_deps(file_contents)
|
132
|
+
def self.parse_go_mod(file_contents, options: {})
|
133
|
+
categorized_deps = parse_go_mod_categorized_deps(file_contents, options.fetch(:filename, nil))
|
129
134
|
|
130
|
-
|
135
|
+
categorized_deps["require"]
|
131
136
|
.map do |dep|
|
132
137
|
# NOTE: A "replace" directive doesn't add the dep to the module graph unless the original dep is also in a "require" directive,
|
133
138
|
# so we need to track down replacements here and use those instead of the originals, if present.
|
@@ -143,11 +148,9 @@ module Bibliothecary
|
|
143
148
|
|
144
149
|
replaced_dep || dep
|
145
150
|
end
|
146
|
-
|
147
|
-
return deps
|
148
151
|
end
|
149
152
|
|
150
|
-
def self.parse_go_mod_categorized_deps(file_contents)
|
153
|
+
def self.parse_go_mod_categorized_deps(file_contents, source)
|
151
154
|
current_multiline_category = nil
|
152
155
|
# docs: https://go.dev/ref/mod#go-mod-file-require
|
153
156
|
categorized_deps = {
|
@@ -159,38 +162,39 @@ module Bibliothecary
|
|
159
162
|
file_contents
|
160
163
|
.lines
|
161
164
|
.map(&:strip)
|
162
|
-
.
|
165
|
+
.grep_v(/^#{GOMOD_COMMENT_REGEXP}/) # ignore comment lines
|
163
166
|
.each do |line|
|
164
167
|
if line.match(GOMOD_MULTILINE_END_REGEXP) # detect the end of a multiline
|
165
168
|
current_multiline_category = nil
|
166
169
|
elsif (match = line.match(GOMOD_MULTILINE_START_REGEXP)) # or, detect the start of a multiline
|
167
170
|
current_multiline_category = match[1]
|
168
171
|
elsif (match = line.match(GOMOD_SINGLELINE_DEP_REGEXP)) # or, detect a singleline dep
|
169
|
-
categorized_deps[match[:category]] << go_mod_category_relative_dep(category: match[:category], line: line, match: match)
|
170
|
-
elsif
|
171
|
-
categorized_deps[current_multiline_category] << go_mod_category_relative_dep(category: current_multiline_category, line: line, match: match)
|
172
|
+
categorized_deps[match[:category]] << go_mod_category_relative_dep(category: match[:category], line: line, match: match, source: source)
|
173
|
+
elsif current_multiline_category && (match = line.match(GOMOD_MULTILINE_DEP_REGEXP)) # otherwise, parse the multiline dep
|
174
|
+
categorized_deps[current_multiline_category] << go_mod_category_relative_dep(category: current_multiline_category, line: line, match: match, source: source)
|
172
175
|
end
|
173
176
|
end
|
174
177
|
categorized_deps
|
175
178
|
end
|
176
179
|
|
177
|
-
def self.parse_go_sum(file_contents, options: {})
|
180
|
+
def self.parse_go_sum(file_contents, options: {})
|
178
181
|
deps = []
|
179
182
|
file_contents.lines.map(&:strip).each do |line|
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
183
|
+
next unless (match = line.match(GOSUM_REGEXP))
|
184
|
+
|
185
|
+
deps << Dependency.new(
|
186
|
+
name: match[1].strip,
|
187
|
+
requirement: match[2].strip.split("/").first,
|
188
|
+
type: "runtime",
|
189
|
+
source: options.fetch(:filename, nil)
|
190
|
+
)
|
187
191
|
end
|
188
192
|
deps.uniq
|
189
193
|
end
|
190
194
|
|
191
|
-
def self.parse_go_resolved(file_contents, options: {})
|
195
|
+
def self.parse_go_resolved(file_contents, options: {})
|
192
196
|
JSON.parse(file_contents)
|
193
|
-
.
|
197
|
+
.reject { |dep| dep["Main"] == "true" }
|
194
198
|
.map do |dep|
|
195
199
|
if dep["Replace"].is_a?(String) && dep["Replace"] != "<nil>" && dep["Replace"] != ""
|
196
200
|
# NOTE: The "replace" directive doesn't actually change the version reported from Go (e.g. "go mod graph"), it only changes
|
@@ -199,28 +203,29 @@ module Bibliothecary
|
|
199
203
|
name, requirement = dep["Replace"].split(" ", 2)
|
200
204
|
requirement = "*" if requirement.to_s.strip == ""
|
201
205
|
Dependency.new(
|
202
|
-
name: name, requirement: requirement, original_name: dep["Path"], original_requirement: dep["Version"], type: dep.fetch("Scope"
|
206
|
+
name: name, requirement: requirement, original_name: dep["Path"], original_requirement: dep["Version"], type: dep.fetch("Scope", "runtime"), source: options.fetch(:filename, nil)
|
203
207
|
)
|
204
208
|
else
|
205
209
|
Dependency.new(
|
206
|
-
name: dep["Path"], requirement: dep["Version"], type: dep.fetch("Scope"
|
210
|
+
name: dep["Path"], requirement: dep["Version"], type: dep.fetch("Scope", "runtime"), source: options.fetch(:filename, nil)
|
207
211
|
)
|
208
212
|
end
|
209
213
|
end
|
210
214
|
end
|
211
215
|
|
212
|
-
def self.map_dependencies(manifest, attr_name, dep_attr_name, version_attr_name, type)
|
213
|
-
manifest.fetch(attr_name,[]).map do |dependency|
|
216
|
+
def self.map_dependencies(manifest, attr_name, dep_attr_name, version_attr_name, type, source = nil)
|
217
|
+
manifest.fetch(attr_name, []).map do |dependency|
|
214
218
|
Dependency.new(
|
215
219
|
name: dependency[dep_attr_name],
|
216
220
|
requirement: dependency[version_attr_name],
|
217
221
|
type: type,
|
222
|
+
source: source
|
218
223
|
)
|
219
224
|
end
|
220
225
|
end
|
221
226
|
|
222
227
|
# Returns our standard-ish dep Hash based on the category of dep matched ("require", "replace", etc.)
|
223
|
-
def self.go_mod_category_relative_dep(category:, line:, match:)
|
228
|
+
def self.go_mod_category_relative_dep(category:, line:, match:, source: nil)
|
224
229
|
case category
|
225
230
|
when "replace"
|
226
231
|
replacement_dep = line.split(GOMOD_REPLACEMENT_SEPARATOR_REGEXP, 2).last
|
@@ -232,6 +237,7 @@ module Bibliothecary
|
|
232
237
|
requirement: replacement_match[:requirement],
|
233
238
|
type: "runtime",
|
234
239
|
direct: !match[:indirect],
|
240
|
+
source: source
|
235
241
|
)
|
236
242
|
when "retract"
|
237
243
|
Dependency.new(
|
@@ -240,6 +246,7 @@ module Bibliothecary
|
|
240
246
|
type: "runtime",
|
241
247
|
deprecated: true,
|
242
248
|
direct: !match[:indirect],
|
249
|
+
source: source
|
243
250
|
)
|
244
251
|
else
|
245
252
|
Dependency.new(
|
@@ -247,6 +254,7 @@ module Bibliothecary
|
|
247
254
|
requirement: match[:requirement],
|
248
255
|
type: "runtime",
|
249
256
|
direct: !match[:indirect],
|
257
|
+
source: source
|
250
258
|
)
|
251
259
|
end
|
252
260
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Bibliothecary
|
2
4
|
module Parsers
|
3
5
|
class Julia
|
@@ -14,10 +16,11 @@ module Bibliothecary
|
|
14
16
|
|
15
17
|
add_multi_parser(Bibliothecary::MultiParsers::DependenciesCSV)
|
16
18
|
|
17
|
-
def self.parse_require(file_contents, options: {})
|
19
|
+
def self.parse_require(file_contents, options: {})
|
18
20
|
deps = []
|
19
21
|
file_contents.split("\n").each do |line|
|
20
22
|
next if line.match(/^#/) || line.empty?
|
23
|
+
|
21
24
|
split = line.split(/\s/)
|
22
25
|
if line.match(/^@/)
|
23
26
|
name = split[1]
|
@@ -33,6 +36,7 @@ module Bibliothecary
|
|
33
36
|
name: name,
|
34
37
|
requirement: reqs,
|
35
38
|
type: "runtime",
|
39
|
+
source: options.fetch(:filename, nil)
|
36
40
|
)
|
37
41
|
end
|
38
42
|
deps
|