bibliothecary 12.0.0 → 12.1.1
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 +13 -0
- data/Gemfile +16 -1
- data/Rakefile +2 -0
- data/bibliothecary.gemspec +11 -13
- 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 -8
- 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 +20 -18
- 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 +89 -75
- 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 -29
- data/lib/bibliothecary/parsers/rubygems.rb +16 -12
- data/lib/bibliothecary/parsers/shard.rb +10 -7
- data/lib/bibliothecary/purl_util.rb +2 -1
- data/lib/bibliothecary/related_files_info.rb +7 -8
- data/lib/bibliothecary/runner/multi_manifest_filter.rb +5 -4
- data/lib/bibliothecary/runner.rb +13 -10
- data/lib/bibliothecary/version.rb +3 -1
- data/lib/bibliothecary.rb +7 -4
- data/lib/sdl_parser.rb +11 -6
- metadata +19 -106
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "json"
|
2
4
|
|
3
5
|
module Bibliothecary
|
@@ -37,29 +39,29 @@ module Bibliothecary
|
|
37
39
|
add_multi_parser(Bibliothecary::MultiParsers::Spdx)
|
38
40
|
add_multi_parser(Bibliothecary::MultiParsers::DependenciesCSV)
|
39
41
|
|
40
|
-
def self.parse_package_lock(file_contents, options: {})
|
42
|
+
def self.parse_package_lock(file_contents, options: {})
|
41
43
|
manifest = JSON.parse(file_contents)
|
42
44
|
# https://docs.npmjs.com/cli/v9/configuring-npm/package-lock-json#lockfileversion
|
43
45
|
if manifest["lockfileVersion"].to_i <= 1
|
44
46
|
# lockfileVersion 1 uses the "dependencies" object
|
45
|
-
parse_package_lock_v1(manifest)
|
47
|
+
parse_package_lock_v1(manifest, options.fetch(:filename, nil))
|
46
48
|
else
|
47
49
|
# lockfileVersion 2 has backwards-compatability by including both "packages" and the legacy "dependencies" object
|
48
50
|
# lockfileVersion 3 has no backwards-compatibility and only includes the "packages" object
|
49
|
-
parse_package_lock_v2(manifest)
|
51
|
+
parse_package_lock_v2(manifest, options.fetch(:filename, nil))
|
50
52
|
end
|
51
53
|
end
|
52
54
|
|
53
55
|
class << self
|
54
56
|
# "package-lock.json" and "npm-shrinkwrap.json" have same format, so use same parsing logic
|
55
|
-
|
57
|
+
alias parse_shrinkwrap parse_package_lock
|
56
58
|
end
|
57
59
|
|
58
|
-
def self.parse_package_lock_v1(manifest)
|
59
|
-
parse_package_lock_deps_recursively(manifest.fetch("dependencies", []))
|
60
|
+
def self.parse_package_lock_v1(manifest, source = nil)
|
61
|
+
parse_package_lock_deps_recursively(manifest.fetch("dependencies", []), source)
|
60
62
|
end
|
61
63
|
|
62
|
-
def self.parse_package_lock_v2(manifest)
|
64
|
+
def self.parse_package_lock_v2(manifest, source = nil)
|
63
65
|
# "packages" is a flat object where each key is the installed location of the dep, e.g. node_modules/foo/node_modules/bar.
|
64
66
|
manifest
|
65
67
|
.fetch("packages")
|
@@ -73,33 +75,39 @@ module Bibliothecary
|
|
73
75
|
Dependency.new(
|
74
76
|
name: name.split("node_modules/").last,
|
75
77
|
requirement: dep["version"],
|
76
|
-
type: dep.fetch("dev", false) || dep.fetch("devOptional", false)
|
78
|
+
type: dep.fetch("dev", false) || dep.fetch("devOptional", false) ? "development" : "runtime",
|
77
79
|
local: dep.fetch("link", false),
|
80
|
+
source: source
|
78
81
|
)
|
79
82
|
end
|
80
83
|
end
|
81
84
|
|
82
|
-
def self.parse_package_lock_deps_recursively(dependencies, depth=1)
|
85
|
+
def self.parse_package_lock_deps_recursively(dependencies, source = nil, depth = 1)
|
83
86
|
dependencies.flat_map do |name, requirement|
|
84
87
|
type = requirement.fetch("dev", false) ? "development" : "runtime"
|
85
88
|
version = requirement.key?("from") ? requirement["from"][/#(?:semver:)?v?(.*)/, 1] : nil
|
86
89
|
version ||= requirement["version"].split("#").last
|
87
90
|
child_dependencies = if depth >= PACKAGE_LOCK_JSON_MAX_DEPTH
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
+
[]
|
92
|
+
else
|
93
|
+
parse_package_lock_deps_recursively(requirement.fetch("dependencies", []), source, depth + 1)
|
91
94
|
end
|
92
95
|
|
93
96
|
[Dependency.new(
|
94
97
|
name: name,
|
95
98
|
requirement: version,
|
96
99
|
type: type,
|
100
|
+
source: source
|
97
101
|
)] + child_dependencies
|
98
102
|
end
|
99
103
|
end
|
100
104
|
|
101
|
-
def self.parse_manifest(file_contents, options: {})
|
105
|
+
def self.parse_manifest(file_contents, options: {})
|
106
|
+
# on ruby 3.2 we suddenly get this JSON error, so detect and return early: "package.json: unexpected token at ''"
|
107
|
+
return [] if file_contents.empty?
|
108
|
+
|
102
109
|
manifest = JSON.parse(file_contents)
|
110
|
+
|
103
111
|
raise "appears to be a lockfile rather than manifest format" if manifest.key?("lockfileVersion")
|
104
112
|
|
105
113
|
dependencies = manifest.fetch("dependencies", [])
|
@@ -109,7 +117,8 @@ module Bibliothecary
|
|
109
117
|
name: name,
|
110
118
|
requirement: requirement,
|
111
119
|
type: "runtime",
|
112
|
-
local: requirement.start_with?("file:")
|
120
|
+
local: requirement.start_with?("file:"),
|
121
|
+
source: options.fetch(:filename, nil)
|
113
122
|
)
|
114
123
|
end
|
115
124
|
|
@@ -120,19 +129,20 @@ module Bibliothecary
|
|
120
129
|
name: name,
|
121
130
|
requirement: requirement,
|
122
131
|
type: "development",
|
123
|
-
local: requirement.start_with?("file:")
|
132
|
+
local: requirement.start_with?("file:"),
|
133
|
+
source: options.fetch(:filename, nil)
|
124
134
|
)
|
125
135
|
end
|
126
136
|
|
127
137
|
dependencies
|
128
138
|
end
|
129
139
|
|
130
|
-
def self.parse_yarn_lock(file_contents, options: {})
|
140
|
+
def self.parse_yarn_lock(file_contents, options: {})
|
131
141
|
dep_hash = if file_contents.match(/__metadata:/)
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
142
|
+
parse_v2_yarn_lock(file_contents, options.fetch(:filename, nil))
|
143
|
+
else
|
144
|
+
parse_v1_yarn_lock(file_contents, options.fetch(:filename, nil))
|
145
|
+
end
|
136
146
|
|
137
147
|
dep_hash.map do |dep|
|
138
148
|
Dependency.new(
|
@@ -140,67 +150,70 @@ module Bibliothecary
|
|
140
150
|
requirement: dep[:version],
|
141
151
|
type: "runtime", # lockfile doesn't tell us more about the type of dep
|
142
152
|
local: dep[:requirements]&.first&.start_with?("file:"),
|
153
|
+
source: options.fetch(:filename, nil)
|
143
154
|
)
|
144
155
|
end
|
145
|
-
|
156
|
+
end
|
146
157
|
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
158
|
+
# Returns a hash representation of the deps in yarn.lock, eg:
|
159
|
+
# [{
|
160
|
+
# name: "foo",
|
161
|
+
# requirements: [["foo", "^1.0.0"], ["foo", "^1.0.1"]],
|
162
|
+
# version: "1.2.0",
|
163
|
+
# }, ...]
|
164
|
+
def self.parse_v1_yarn_lock(contents, source = nil)
|
165
|
+
contents
|
166
|
+
.gsub(/^#.*/, "")
|
167
|
+
.strip
|
168
|
+
.split("\n\n")
|
169
|
+
.map do |chunk|
|
170
|
+
requirements = chunk
|
171
|
+
.lines
|
172
|
+
.find { |l| !l.start_with?(" ") && l.strip.end_with?(":") } # first line, eg: '"@bar/foo@1.0.0", "@bar/foo@^1.0.1":'
|
173
|
+
.strip
|
174
|
+
.gsub(/"|:$/, "") # don't need quotes or trailing colon
|
175
|
+
.split(",") # split the list of requirements
|
176
|
+
.map { |d| d.strip.split(/(?<!^)@/, 2) } # split each requirement on name/version "@"", not on leading namespace "@"
|
177
|
+
version = chunk.match(/version "?([^"]*)"?/)[1]
|
178
|
+
|
179
|
+
{
|
180
|
+
name: requirements.first.first,
|
181
|
+
requirements: requirements.map { |x| x[1] },
|
182
|
+
version: version,
|
183
|
+
source: source,
|
184
|
+
}
|
185
|
+
end
|
186
|
+
end
|
175
187
|
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
188
|
+
def self.parse_v2_yarn_lock(contents, source = nil)
|
189
|
+
parsed = YAML.load(contents)
|
190
|
+
parsed = parsed.except("__metadata")
|
191
|
+
parsed
|
192
|
+
.reject do |packages, info|
|
193
|
+
# yarn v4+ creates a lockfile entry: "myproject@workspace" with a "use.local" version
|
194
|
+
# this lockfile entry is a reference to the project to which the lockfile belongs
|
195
|
+
# skip this self-referential package
|
196
|
+
info["version"].to_s.include?("use.local") && packages.include?("workspace")
|
197
|
+
end
|
198
|
+
.map do |packages, info|
|
199
|
+
packages = packages.split(", ")
|
200
|
+
# use first requirement's name, assuming that deps will always resolve from deps of the same name
|
201
|
+
name = packages.first.rpartition("@").first
|
202
|
+
requirements = packages.map { |p| p.rpartition("@").last.gsub(/^.*:/, "") }
|
191
203
|
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
204
|
+
{
|
205
|
+
name: name,
|
206
|
+
requirements: requirements,
|
207
|
+
version: info["version"].to_s,
|
208
|
+
source: source,
|
209
|
+
}
|
210
|
+
end
|
211
|
+
end
|
199
212
|
|
200
|
-
def self.parse_ls(file_contents, options: {})
|
213
|
+
def self.parse_ls(file_contents, options: {})
|
201
214
|
manifest = JSON.parse(file_contents)
|
202
215
|
|
203
|
-
transform_tree_to_array(manifest.fetch("dependencies", {}))
|
216
|
+
transform_tree_to_array(manifest.fetch("dependencies", {}), options.fetch(:filename, nil))
|
204
217
|
end
|
205
218
|
|
206
219
|
def self.lockfile_preference_order(file_infos)
|
@@ -215,15 +228,16 @@ module Bibliothecary
|
|
215
228
|
end
|
216
229
|
end
|
217
230
|
|
218
|
-
private_class_method def self.transform_tree_to_array(deps_by_name)
|
231
|
+
private_class_method def self.transform_tree_to_array(deps_by_name, source = nil)
|
219
232
|
deps_by_name.map do |name, metadata|
|
220
233
|
[
|
221
234
|
Dependency.new(
|
222
235
|
name: name,
|
223
236
|
requirement: metadata["version"],
|
224
237
|
type: "runtime",
|
238
|
+
source: source
|
225
239
|
),
|
226
|
-
] + transform_tree_to_array(metadata.fetch("dependencies", {}))
|
240
|
+
] + transform_tree_to_array(metadata.fetch("dependencies", {}), source)
|
227
241
|
end.flatten(1)
|
228
242
|
end
|
229
243
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "ox"
|
2
4
|
require "json"
|
3
5
|
|
@@ -48,23 +50,24 @@ module Bibliothecary
|
|
48
50
|
add_multi_parser(Bibliothecary::MultiParsers::DependenciesCSV)
|
49
51
|
add_multi_parser(Bibliothecary::MultiParsers::Spdx)
|
50
52
|
|
51
|
-
def self.parse_project_lock_json(file_contents, options: {})
|
53
|
+
def self.parse_project_lock_json(file_contents, options: {})
|
52
54
|
manifest = JSON.parse file_contents
|
53
|
-
manifest.fetch("libraries",[]).map do |name, _requirement|
|
55
|
+
manifest.fetch("libraries", []).map do |name, _requirement|
|
54
56
|
dep = name.split("/")
|
55
57
|
Dependency.new(
|
56
58
|
name: dep[0],
|
57
59
|
requirement: dep[1],
|
58
60
|
type: "runtime",
|
61
|
+
source: options.fetch(:filename, nil)
|
59
62
|
)
|
60
63
|
end
|
61
64
|
end
|
62
65
|
|
63
|
-
def self.parse_packages_lock_json(file_contents, options: {})
|
66
|
+
def self.parse_packages_lock_json(file_contents, options: {})
|
64
67
|
manifest = JSON.parse file_contents
|
65
68
|
|
66
69
|
frameworks = {}
|
67
|
-
manifest.fetch("dependencies",[]).each do |framework, deps|
|
70
|
+
manifest.fetch("dependencies", []).each do |framework, deps|
|
68
71
|
frameworks[framework] = deps
|
69
72
|
.reject { |_name, details| details["type"] == "Project" } # Projects do not have versions
|
70
73
|
.map do |name, details|
|
@@ -74,44 +77,46 @@ module Bibliothecary
|
|
74
77
|
# so fallback to requested is pure paranoia
|
75
78
|
requirement: details.fetch("resolved", details.fetch("requested", "*")),
|
76
79
|
type: "runtime",
|
80
|
+
source: options.fetch(:filename, nil)
|
77
81
|
)
|
78
82
|
end
|
79
83
|
end
|
80
84
|
|
81
|
-
|
85
|
+
unless frameworks.empty?
|
82
86
|
# we should really return multiple manifests, but bibliothecary doesn't
|
83
87
|
# do that yet so at least pick deterministically.
|
84
88
|
|
85
89
|
# Note, frameworks can be empty, so remove empty ones and then return the last sorted item if any
|
86
90
|
frameworks = frameworks.delete_if { |_k, v| v.empty? }
|
87
|
-
return frameworks[frameworks.keys.
|
91
|
+
return frameworks[frameworks.keys.max] unless frameworks.empty?
|
88
92
|
end
|
89
93
|
[]
|
90
94
|
end
|
91
95
|
|
92
|
-
def self.parse_packages_config(file_contents, options: {})
|
96
|
+
def self.parse_packages_config(file_contents, options: {})
|
93
97
|
manifest = Ox.parse file_contents
|
94
98
|
manifest.packages.locate("package").map do |dependency|
|
95
99
|
Dependency.new(
|
96
100
|
name: dependency.id,
|
97
101
|
requirement: (dependency.version if dependency.respond_to? "version"),
|
98
102
|
type: dependency.respond_to?("developmentDependency") && dependency.developmentDependency == "true" ? "development" : "runtime",
|
103
|
+
source: options.fetch(:filename, nil)
|
99
104
|
)
|
100
105
|
end
|
101
|
-
rescue
|
106
|
+
rescue StandardError
|
102
107
|
[]
|
103
108
|
end
|
104
109
|
|
105
|
-
def self.parse_csproj(file_contents, options: {})
|
110
|
+
def self.parse_csproj(file_contents, options: {})
|
106
111
|
manifest = Ox.parse file_contents
|
107
112
|
|
108
|
-
packages = manifest.locate("ItemGroup/PackageReference").select{ |dep| dep.respond_to? "Include" }.map do |dependency|
|
113
|
+
packages = manifest.locate("ItemGroup/PackageReference").select { |dep| dep.respond_to? "Include" }.map do |dependency|
|
109
114
|
requirement = (dependency.Version if dependency.respond_to? "Version")
|
110
115
|
if requirement.is_a?(Ox::Element)
|
111
|
-
requirement = dependency.nodes.detect{ |n| n.value == "Version" }&.text
|
116
|
+
requirement = dependency.nodes.detect { |n| n.value == "Version" }&.text
|
112
117
|
end
|
113
118
|
|
114
|
-
type = if dependency.nodes.first
|
119
|
+
type = if (dependency.nodes.first&.nodes&.include?("all") && dependency.nodes.first.value.include?("PrivateAssets")) || dependency.attributes[:PrivateAssets] == "All"
|
115
120
|
"development"
|
116
121
|
else
|
117
122
|
"runtime"
|
@@ -121,27 +126,29 @@ module Bibliothecary
|
|
121
126
|
name: dependency.Include,
|
122
127
|
requirement: requirement,
|
123
128
|
type: type,
|
129
|
+
source: options.fetch(:filename, nil)
|
124
130
|
)
|
125
131
|
end
|
126
|
-
packages.uniq
|
127
|
-
rescue
|
132
|
+
packages.uniq(&:name)
|
133
|
+
rescue StandardError
|
128
134
|
[]
|
129
135
|
end
|
130
136
|
|
131
|
-
def self.parse_nuspec(file_contents, options: {})
|
137
|
+
def self.parse_nuspec(file_contents, options: {})
|
132
138
|
manifest = Ox.parse file_contents
|
133
139
|
manifest.package.metadata.dependencies.locate("dependency").map do |dependency|
|
134
140
|
Dependency.new(
|
135
141
|
name: dependency.id,
|
136
142
|
requirement: dependency.attributes[:version],
|
137
143
|
type: dependency.respond_to?("developmentDependency") && dependency.developmentDependency == "true" ? "development" : "runtime",
|
144
|
+
source: options.fetch(:filename, nil)
|
138
145
|
)
|
139
146
|
end
|
140
|
-
rescue
|
147
|
+
rescue StandardError
|
141
148
|
[]
|
142
149
|
end
|
143
150
|
|
144
|
-
def self.parse_paket_lock(file_contents, options: {})
|
151
|
+
def self.parse_paket_lock(file_contents, options: {})
|
145
152
|
lines = file_contents.split("\n")
|
146
153
|
package_version_re = /\s+(?<name>\S+)\s\((?<version>\d+\.\d+[\.\d+[\.\d+]*]*)\)/
|
147
154
|
packages = lines.select { |line| package_version_re.match(line) }.map { |line| package_version_re.match(line) }.map do |match|
|
@@ -149,36 +156,38 @@ module Bibliothecary
|
|
149
156
|
name: match[:name].strip,
|
150
157
|
requirement: match[:version],
|
151
158
|
type: "runtime",
|
159
|
+
source: options.fetch(:filename, nil)
|
152
160
|
)
|
153
161
|
end
|
154
162
|
# we only have to enforce uniqueness by name because paket ensures that there is only the single version globally in the project
|
155
|
-
packages.uniq
|
163
|
+
packages.uniq(&:name)
|
156
164
|
end
|
157
165
|
|
158
|
-
def self.parse_project_assets_json(file_contents, options: {})
|
166
|
+
def self.parse_project_assets_json(file_contents, options: {})
|
159
167
|
manifest = JSON.parse file_contents
|
160
168
|
|
161
169
|
frameworks = {}
|
162
|
-
manifest.fetch("targets",[]).each do |framework, deps|
|
170
|
+
manifest.fetch("targets", []).each do |framework, deps|
|
163
171
|
frameworks[framework] = deps
|
164
172
|
.select { |_name, details| details["type"] == "package" }
|
165
173
|
.map do |name, _details|
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
174
|
+
name_split = name.split("/")
|
175
|
+
Dependency.new(
|
176
|
+
name: name_split[0],
|
177
|
+
requirement: name_split[1],
|
178
|
+
type: "runtime",
|
179
|
+
source: options.fetch(:filename, nil)
|
180
|
+
)
|
172
181
|
end
|
173
182
|
end
|
174
183
|
|
175
|
-
|
184
|
+
unless frameworks.empty?
|
176
185
|
# we should really return multiple manifests, but bibliothecary doesn't
|
177
186
|
# do that yet so at least pick deterministically.
|
178
187
|
|
179
188
|
# Note, frameworks can be empty, so remove empty ones and then return the last sorted item if any
|
180
189
|
frameworks = frameworks.delete_if { |_k, v| v.empty? }
|
181
|
-
return frameworks[frameworks.keys.
|
190
|
+
return frameworks[frameworks.keys.max] unless frameworks.empty?
|
182
191
|
end
|
183
192
|
[]
|
184
193
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "json"
|
2
4
|
|
3
5
|
module Bibliothecary
|
@@ -22,39 +24,47 @@ module Bibliothecary
|
|
22
24
|
add_multi_parser(Bibliothecary::MultiParsers::DependenciesCSV)
|
23
25
|
add_multi_parser(Bibliothecary::MultiParsers::Spdx)
|
24
26
|
|
25
|
-
def self.parse_lockfile(file_contents, options: {})
|
27
|
+
def self.parse_lockfile(file_contents, options: {})
|
26
28
|
manifest = JSON.parse file_contents
|
27
|
-
manifest.fetch("packages",[]).map do |dependency|
|
29
|
+
manifest.fetch("packages", []).map do |dependency|
|
28
30
|
requirement = dependency["version"]
|
29
31
|
|
30
32
|
# Store Drupal version if Drupal, but include the original manifest version for reference
|
31
|
-
|
33
|
+
if drupal_module?(dependency)
|
34
|
+
original_requirement = requirement
|
35
|
+
requirement = dependency.dig("source", "reference")
|
36
|
+
end
|
32
37
|
|
33
38
|
Dependency.new(
|
34
39
|
name: dependency["name"],
|
35
40
|
requirement: requirement,
|
36
41
|
type: "runtime",
|
37
|
-
original_requirement: original_requirement
|
42
|
+
original_requirement: original_requirement,
|
43
|
+
source: options.fetch(:filename, nil)
|
38
44
|
)
|
39
|
-
end + manifest.fetch("packages-dev",[]).map do |dependency|
|
45
|
+
end + manifest.fetch("packages-dev", []).map do |dependency|
|
40
46
|
requirement = dependency["version"]
|
41
47
|
|
42
48
|
# Store Drupal version if Drupal, but include the original manifest version for reference
|
43
|
-
|
49
|
+
if drupal_module?(dependency)
|
50
|
+
original_requirement = requirement
|
51
|
+
requirement = dependency.dig("source", "reference")
|
52
|
+
end
|
44
53
|
|
45
54
|
Dependency.new(
|
46
55
|
name: dependency["name"],
|
47
56
|
requirement: requirement,
|
48
57
|
type: "development",
|
49
|
-
original_requirement: original_requirement
|
58
|
+
original_requirement: original_requirement,
|
59
|
+
source: options.fetch(:filename, nil)
|
50
60
|
)
|
51
61
|
end
|
52
62
|
end
|
53
63
|
|
54
|
-
def self.parse_manifest(file_contents, options: {})
|
64
|
+
def self.parse_manifest(file_contents, options: {})
|
55
65
|
manifest = JSON.parse file_contents
|
56
|
-
map_dependencies(manifest, "require", "runtime") +
|
57
|
-
|
66
|
+
map_dependencies(manifest, "require", "runtime", options.fetch(:filename, nil)) +
|
67
|
+
map_dependencies(manifest, "require-dev", "development", options.fetch(:filename, nil))
|
58
68
|
end
|
59
69
|
|
60
70
|
# Drupal hosts its own Composer repository, where its "modules" are indexed and searchable. The best way to
|
@@ -65,7 +75,7 @@ module Bibliothecary
|
|
65
75
|
# (https://www.drupal.org/project/project_composer/issues/2622450),
|
66
76
|
# so we return the Drupal requirement instead of semver requirement if it's here
|
67
77
|
# (https://www.drupal.org/docs/develop/using-composer/using-composer-to-install-drupal-and-manage-dependencies#s-about-semantic-versioning)
|
68
|
-
private_class_method def self.
|
78
|
+
private_class_method def self.drupal_module?(dependency)
|
69
79
|
dependency["type"] =~ /drupal/ && dependency.dig("source", "reference")
|
70
80
|
end
|
71
81
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "yaml"
|
2
4
|
|
3
5
|
module Bibliothecary
|
@@ -23,7 +25,7 @@ module Bibliothecary
|
|
23
25
|
def self.parse_yaml_manifest(file_contents, options: {}) # rubocop:disable Lint/UnusedMethodArgument
|
24
26
|
manifest = YAML.load file_contents
|
25
27
|
map_dependencies(manifest, "dependencies", "runtime") +
|
26
|
-
|
28
|
+
map_dependencies(manifest, "dev_dependencies", "development")
|
27
29
|
end
|
28
30
|
|
29
31
|
def self.parse_yaml_lockfile(file_contents, options: {}) # rubocop:disable Lint/UnusedMethodArgument
|
@@ -32,7 +34,7 @@ module Bibliothecary
|
|
32
34
|
Dependency.new(
|
33
35
|
name: name,
|
34
36
|
requirement: dep["version"],
|
35
|
-
type: "runtime"
|
37
|
+
type: "runtime"
|
36
38
|
)
|
37
39
|
end
|
38
40
|
end
|