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
|
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
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "ox"
|
2
4
|
|
3
5
|
# Known shortcomings and unimplemented Maven features:
|
@@ -26,7 +28,7 @@ module Bibliothecary
|
|
26
28
|
|
27
29
|
# Builtin methods: https://docs.gradle.org/current/userguide/java_plugin.html#tab:configurations
|
28
30
|
# Deprecated methods: https://docs.gradle.org/current/userguide/upgrading_version_6.html#sec:configuration_removal
|
29
|
-
GRADLE_DEPENDENCY_METHODS = %w
|
31
|
+
GRADLE_DEPENDENCY_METHODS = %w[api compile compileClasspath compileOnly compileOnlyApi implementation runtime runtimeClasspath runtimeOnly testCompile testCompileOnly testImplementation testRuntime testRuntimeOnly].freeze
|
30
32
|
|
31
33
|
# Intentionally overly-simplified regexes to scrape deps from build.gradle (Groovy) and build.gradle.kts (Kotlin) files.
|
32
34
|
# To be truly useful bibliothecary would need full Groovy / Kotlin parsers that speaks Gradle,
|
@@ -34,7 +36,7 @@ module Bibliothecary
|
|
34
36
|
GRADLE_VERSION_REGEXP = /[\w.-]+/ # e.g. '1.2.3'
|
35
37
|
GRADLE_VAR_INTERPOLATION_REGEXP = /\$\w+/ # e.g. '$myVersion'
|
36
38
|
GRADLE_CODE_INTERPOLATION_REGEXP = /\$\{.*\}/ # e.g. '${my-project-settings["version"]}'
|
37
|
-
GRADLE_GAV_REGEXP = /([\w.-]+)
|
39
|
+
GRADLE_GAV_REGEXP = /([\w.-]+):([\w.-]+)(?::(#{GRADLE_VERSION_REGEXP}|#{GRADLE_VAR_INTERPOLATION_REGEXP}|#{GRADLE_CODE_INTERPOLATION_REGEXP}))?/ # e.g. "group:artifactId:1.2.3"
|
38
40
|
GRADLE_GROOVY_SIMPLE_REGEXP = /(#{GRADLE_DEPENDENCY_METHODS.join('|')})\s*\(?\s*['"]#{GRADLE_GAV_REGEXP}['"]/m
|
39
41
|
GRADLE_KOTLIN_SIMPLE_REGEXP = /(#{GRADLE_DEPENDENCY_METHODS.join('|')})\s*\(\s*"#{GRADLE_GAV_REGEXP}"/m
|
40
42
|
|
@@ -56,7 +58,6 @@ module Bibliothecary
|
|
56
58
|
# e.g. "[info] "
|
57
59
|
SBT_IGNORE_REGEXP = /^\[info\]\s*$/
|
58
60
|
|
59
|
-
|
60
61
|
# Copied from the "strings-ansi" gem, because it seems abandoned: https://github.com/piotrmurach/strings-ansi/pull/2
|
61
62
|
# From: https://github.com/piotrmurach/strings-ansi/blob/35d0c9430cf0a8022dc12bdab005bce296cb9f00/lib/strings/ansi.rb#L14-L29
|
62
63
|
# License: MIT
|
@@ -75,8 +76,8 @@ module Bibliothecary
|
|
75
76
|
|
|
76
77
|
\]8;[^;]*;.*?(\033\\|\07) # hyperlink
|
77
78
|
))
|
78
|
-
}x
|
79
|
-
|
79
|
+
}x
|
80
|
+
|
80
81
|
def self.mapping
|
81
82
|
{
|
82
83
|
match_filename("ivy.xml", case_insensitive: true) => {
|
@@ -123,7 +124,7 @@ module Bibliothecary
|
|
123
124
|
add_multi_parser(Bibliothecary::MultiParsers::Spdx)
|
124
125
|
add_multi_parser(Bibliothecary::MultiParsers::DependenciesCSV)
|
125
126
|
|
126
|
-
def self.parse_ivy_manifest(file_contents, options: {})
|
127
|
+
def self.parse_ivy_manifest(file_contents, options: {})
|
127
128
|
manifest = Ox.parse file_contents
|
128
129
|
manifest.dependencies.locate("dependency").map do |dependency|
|
129
130
|
attrs = dependency.attributes
|
@@ -131,6 +132,7 @@ module Bibliothecary
|
|
131
132
|
name: "#{attrs[:org]}:#{attrs[:name]}",
|
132
133
|
requirement: attrs[:rev],
|
133
134
|
type: "runtime",
|
135
|
+
source: options.fetch(:filename, nil)
|
134
136
|
)
|
135
137
|
end
|
136
138
|
end
|
@@ -138,7 +140,7 @@ module Bibliothecary
|
|
138
140
|
def self.ivy_report?(file_contents)
|
139
141
|
doc = Ox.parse file_contents
|
140
142
|
root = doc&.locate("ivy-report")&.first
|
141
|
-
|
143
|
+
!root.nil?
|
142
144
|
rescue Exception # rubocop:disable Lint/RescueException
|
143
145
|
# We rescue exception here since native libs can throw a non-StandardError
|
144
146
|
# We don't want to throw errors during the matching phase, only during
|
@@ -146,12 +148,14 @@ module Bibliothecary
|
|
146
148
|
false
|
147
149
|
end
|
148
150
|
|
149
|
-
def self.parse_ivy_report(file_contents, options: {})
|
151
|
+
def self.parse_ivy_report(file_contents, options: {})
|
150
152
|
doc = Ox.parse file_contents
|
151
153
|
root = doc.locate("ivy-report").first
|
152
154
|
raise "ivy-report document does not have ivy-report at the root" if root.nil?
|
155
|
+
|
153
156
|
info = doc.locate("ivy-report/info").first
|
154
157
|
raise "ivy-report document lacks <info> element" if info.nil?
|
158
|
+
|
155
159
|
type = info.attributes[:conf]
|
156
160
|
type = "unknown" if type.nil?
|
157
161
|
modules = doc.locate("ivy-report/dependencies/module")
|
@@ -159,19 +163,20 @@ module Bibliothecary
|
|
159
163
|
attrs = mod.attributes
|
160
164
|
org = attrs[:organisation]
|
161
165
|
name = attrs[:name]
|
162
|
-
version = mod.locate("revision").first&.attributes[:name
|
166
|
+
version = mod.locate("revision").first&.attributes&.[](:name)
|
163
167
|
|
164
|
-
next nil if org.nil?
|
168
|
+
next nil if org.nil? || name.nil? || version.nil?
|
165
169
|
|
166
170
|
Dependency.new(
|
167
171
|
name: "#{org}:#{name}",
|
168
172
|
requirement: version,
|
169
173
|
type: type,
|
174
|
+
source: options.fetch(:filename, nil)
|
170
175
|
)
|
171
176
|
end.compact
|
172
177
|
end
|
173
178
|
|
174
|
-
def self.parse_gradle_resolved(file_contents, options: {})
|
179
|
+
def self.parse_gradle_resolved(file_contents, options: {})
|
175
180
|
current_type = nil
|
176
181
|
|
177
182
|
file_contents.split("\n").map do |line|
|
@@ -190,7 +195,7 @@ module Bibliothecary
|
|
190
195
|
next if project_match[1].nil?
|
191
196
|
|
192
197
|
# project names can have colons (e.g. for gradle projects in subfolders), which breaks maven artifact naming assumptions, so just replace them with hyphens.
|
193
|
-
project_name = project_match[1].gsub(
|
198
|
+
project_name = project_match[1].gsub(":", "-")
|
194
199
|
line = line.sub(GRADLE_PROJECT_REGEXP, "internal:#{project_name}:1.0.0")
|
195
200
|
end
|
196
201
|
|
@@ -209,20 +214,22 @@ module Bibliothecary
|
|
209
214
|
if dep.count == 6
|
210
215
|
# get name from renamed package resolution "org:name:version -> renamed_org:name:version"
|
211
216
|
Dependency.new(
|
212
|
-
original_name: dep[0,2].join(":"),
|
217
|
+
original_name: dep[0, 2].join(":"),
|
213
218
|
original_requirement: dep[2],
|
214
219
|
name: dep[-3..-2].join(":"),
|
215
220
|
requirement: dep[-1],
|
216
221
|
type: current_type,
|
222
|
+
source: options.fetch(:filename, nil)
|
217
223
|
)
|
218
224
|
elsif dep.count == 5
|
219
225
|
# get name from renamed package resolution "org:name -> renamed_org:name:version"
|
220
226
|
Dependency.new(
|
221
|
-
original_name: dep[0,2].join(":"),
|
227
|
+
original_name: dep[0, 2].join(":"),
|
222
228
|
original_requirement: "*",
|
223
229
|
name: dep[-3..-2].join(":"),
|
224
230
|
requirement: dep[-1],
|
225
231
|
type: current_type,
|
232
|
+
source: options.fetch(:filename, nil)
|
226
233
|
)
|
227
234
|
else
|
228
235
|
# get name from version conflict resolution ("org:name:version -> version") and no-resolution ("org:name:version")
|
@@ -230,6 +237,7 @@ module Bibliothecary
|
|
230
237
|
name: dep[0..1].join(":"),
|
231
238
|
requirement: dep[-1],
|
232
239
|
type: current_type,
|
240
|
+
source: options.fetch(:filename, nil)
|
233
241
|
)
|
234
242
|
end
|
235
243
|
end
|
@@ -237,16 +245,16 @@ module Bibliothecary
|
|
237
245
|
.uniq { |item| [item.name, item.requirement, item.type, item.original_name, item.original_requirement] }
|
238
246
|
end
|
239
247
|
|
240
|
-
def self.parse_maven_resolved(file_contents, options: {})
|
248
|
+
def self.parse_maven_resolved(file_contents, options: {})
|
241
249
|
file_contents
|
242
250
|
.gsub(ANSI_MATCHER, "")
|
243
251
|
.split("\n")
|
244
|
-
.map(
|
252
|
+
.map { |line| parse_resolved_dep_line(line, options: options) }
|
245
253
|
.compact
|
246
254
|
.uniq
|
247
255
|
end
|
248
256
|
|
249
|
-
def self.parse_maven_tree(file_contents, options: {})
|
257
|
+
def self.parse_maven_tree(file_contents, options: {})
|
250
258
|
captures = file_contents
|
251
259
|
.gsub(ANSI_MATCHER, "")
|
252
260
|
.gsub(/\r\n?/, "\n")
|
@@ -267,68 +275,71 @@ module Bibliothecary
|
|
267
275
|
name: parts[0..1].join(":"),
|
268
276
|
requirement: version,
|
269
277
|
type: type,
|
278
|
+
source: options.fetch(:filename, nil)
|
270
279
|
)
|
271
280
|
end
|
272
281
|
|
273
282
|
# First dep line will be the package itself (unless we're only analyzing a single line)
|
274
283
|
package = deps[0]
|
275
|
-
deps.size < 2 ? deps : deps[1
|
284
|
+
deps.size < 2 ? deps : deps[1..].reject { |d| d.name == package.name && d.requirement == package.requirement }
|
276
285
|
end
|
277
286
|
|
278
|
-
def self.parse_resolved_dep_line(line)
|
287
|
+
def self.parse_resolved_dep_line(line, options: {})
|
279
288
|
# filter out anything that doesn't look like a
|
280
289
|
# resolved dep line
|
281
290
|
return unless line[/ .*:[^-]+-- /]
|
282
291
|
|
283
292
|
dep_parts = line.strip.split(":")
|
284
293
|
return unless dep_parts.length == 5
|
294
|
+
|
285
295
|
# org.springframework.boot:spring-boot-starter-web:jar:2.0.3.RELEASE:compile[36m -- module spring.boot.starter.web[0;1m [auto][m
|
286
296
|
Dependency.new(
|
287
297
|
name: dep_parts[0, 2].join(":"),
|
288
298
|
requirement: dep_parts[3],
|
289
299
|
type: dep_parts[4].split("--").first.strip,
|
300
|
+
source: options.fetch(:filename, nil)
|
290
301
|
)
|
291
302
|
end
|
292
303
|
|
293
304
|
def self.parse_standalone_pom_manifest(file_contents, options: {})
|
294
|
-
parse_pom_manifest(file_contents, {}, options:
|
305
|
+
parse_pom_manifest(file_contents, {}, options:)
|
295
306
|
end
|
296
307
|
|
297
|
-
def self.parse_pom_manifest(file_contents, parent_properties = {}, options: {})
|
298
|
-
parse_pom_manifests([file_contents], parent_properties)
|
308
|
+
def self.parse_pom_manifest(file_contents, parent_properties = {}, options: {})
|
309
|
+
parse_pom_manifests([file_contents], parent_properties, options.fetch(:filename, nil))
|
299
310
|
end
|
300
311
|
|
301
312
|
# @param files [Array<String>] Ordered array of strings containing the
|
302
313
|
# pom.xml bodies. The first element should be the child file.
|
303
314
|
# @param merged_properties [Hash]
|
304
|
-
def self.parse_pom_manifests(files, merged_properties)
|
315
|
+
def self.parse_pom_manifests(files, merged_properties, source = nil)
|
305
316
|
documents = files.map do |file|
|
306
317
|
doc = Ox.parse(file)
|
307
318
|
doc.respond_to?("project") ? doc.project : doc
|
308
319
|
end
|
309
320
|
|
310
|
-
|
321
|
+
merged_dependency_managements = {}
|
311
322
|
documents.each do |document|
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
323
|
+
document.locate("dependencyManagement/dependencies/dependency").each do |dep|
|
324
|
+
group_id = extract_pom_dep_info(document, dep, "groupId", merged_properties)
|
325
|
+
artifact_id = extract_pom_dep_info(document, dep, "artifactId", merged_properties)
|
326
|
+
key = "#{group_id}:#{artifact_id}"
|
327
|
+
merged_dependency_managements[key] ||=
|
328
|
+
{
|
329
|
+
groupId: group_id,
|
330
|
+
artifactId: artifact_id,
|
331
|
+
version: extract_pom_dep_info(document, dep, "version", merged_properties),
|
332
|
+
scope: extract_pom_dep_info(document, dep, "scope", merged_properties),
|
333
|
+
}
|
334
|
+
end
|
324
335
|
end
|
325
336
|
|
326
337
|
dep_hashes = {}
|
327
338
|
documents.each do |document|
|
328
339
|
document.locate("dependencies/dependency").each do |dep|
|
329
|
-
|
330
|
-
|
331
|
-
key = "#{
|
340
|
+
group_id = extract_pom_dep_info(document, dep, "groupId", merged_properties)
|
341
|
+
artifact_id = extract_pom_dep_info(document, dep, "artifactId", merged_properties)
|
342
|
+
key = "#{group_id}:#{artifact_id}"
|
332
343
|
unless dep_hashes.key?(key)
|
333
344
|
dep_hashes[key] = {
|
334
345
|
name: key,
|
@@ -353,41 +364,44 @@ module Bibliothecary
|
|
353
364
|
# Anything that wasn't covered by a dependency version, get from the
|
354
365
|
# dependencyManagements
|
355
366
|
dep_hashes.each do |key, dep_hash|
|
356
|
-
if (
|
357
|
-
dep_hash[:requirement] ||=
|
358
|
-
dep_hash[:type] ||=
|
367
|
+
if (dependency_management = merged_dependency_managements[key])
|
368
|
+
dep_hash[:requirement] ||= dependency_management[:version]
|
369
|
+
dep_hash[:type] ||= dependency_management[:scope]
|
359
370
|
end
|
360
371
|
|
361
372
|
dep_hash[:type] ||= "runtime"
|
373
|
+
dep_hash[:source] = source
|
362
374
|
end
|
363
375
|
|
364
|
-
dep_hashes.map{|
|
376
|
+
dep_hashes.map { |_key, dep_hash| Dependency.new(**dep_hash) }
|
365
377
|
end
|
366
378
|
|
367
|
-
def self.parse_gradle(file_contents, options: {})
|
379
|
+
def self.parse_gradle(file_contents, options: {})
|
368
380
|
file_contents
|
369
|
-
.scan(GRADLE_GROOVY_SIMPLE_REGEXP)
|
370
|
-
.reject { |(_type, group,
|
371
|
-
.map
|
381
|
+
.scan(GRADLE_GROOVY_SIMPLE_REGEXP) # match 'implementation "group:artifactId:version"'
|
382
|
+
.reject { |(_type, group, artifact_id, _version)| group.nil? || artifact_id.nil? } # remove any matches with missing group/artifactId
|
383
|
+
.map do |(type, group, artifact_id, version)|
|
372
384
|
Dependency.new(
|
373
|
-
name: [group,
|
385
|
+
name: [group, artifact_id].join(":"),
|
374
386
|
requirement: version,
|
375
387
|
type: type,
|
388
|
+
source: options.fetch(:filename, nil)
|
376
389
|
)
|
377
|
-
|
390
|
+
end
|
378
391
|
end
|
379
392
|
|
380
|
-
def self.parse_gradle_kts(file_contents, options: {})
|
393
|
+
def self.parse_gradle_kts(file_contents, options: {})
|
381
394
|
file_contents
|
382
|
-
.scan(GRADLE_KOTLIN_SIMPLE_REGEXP)
|
383
|
-
.reject { |(_type, group,
|
384
|
-
.map
|
395
|
+
.scan(GRADLE_KOTLIN_SIMPLE_REGEXP) # match 'implementation("group:artifactId:version")'
|
396
|
+
.reject { |(_type, group, artifact_id, _version)| group.nil? || artifact_id.nil? } # remove any matches with missing group/artifactId
|
397
|
+
.map do |(type, group, artifact_id, version)|
|
385
398
|
Dependency.new(
|
386
|
-
name: [group,
|
399
|
+
name: [group, artifact_id].join(":"),
|
387
400
|
requirement: version,
|
388
401
|
type: type,
|
402
|
+
source: options.fetch(:filename, nil)
|
389
403
|
)
|
390
|
-
|
404
|
+
end
|
391
405
|
end
|
392
406
|
|
393
407
|
def self.gradle_dependency_name(group, name)
|
@@ -420,11 +434,9 @@ module Bibliothecary
|
|
420
434
|
# whitespace in dependency tags should be ignored
|
421
435
|
value = value&.strip
|
422
436
|
match = value&.match(MAVEN_PROPERTY_REGEXP)
|
423
|
-
if match
|
424
|
-
|
425
|
-
|
426
|
-
return value
|
427
|
-
end
|
437
|
+
return extract_property(xml, match[1], value, parent_properties) if match
|
438
|
+
|
439
|
+
value
|
428
440
|
end
|
429
441
|
|
430
442
|
def self.replace_value_with_prop(original_value, property_value, property_name)
|
@@ -434,17 +446,16 @@ module Bibliothecary
|
|
434
446
|
def self.extract_property(xml, property_name, value, parent_properties = {}, depth = 0)
|
435
447
|
prop_value = property_value(xml, property_name, parent_properties)
|
436
448
|
return value unless prop_value
|
449
|
+
|
437
450
|
# don't resolve more than 5 levels deep to avoid potential circular references
|
438
451
|
|
439
452
|
resolved_value = replace_value_with_prop(value, prop_value, property_name)
|
440
453
|
# check to see if we just resolved to another property name
|
441
454
|
match = resolved_value.match(MAVEN_PROPERTY_REGEXP)
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
return resolved_value
|
447
|
-
end
|
455
|
+
return resolved_value unless match && depth < MAX_DEPTH
|
456
|
+
|
457
|
+
depth += 1
|
458
|
+
extract_property(xml, match[1], resolved_value, parent_properties, depth)
|
448
459
|
end
|
449
460
|
|
450
461
|
def self.property_value(xml, property_name, parent_properties)
|
@@ -453,9 +464,9 @@ module Bibliothecary
|
|
453
464
|
non_prop_name = property_name.gsub(".", "/").gsub("project/", "")
|
454
465
|
|
455
466
|
prop_field = xml.properties.locate(property_name).first if xml.respond_to?("properties")
|
456
|
-
parent_prop = parent_properties[property_name] ||
|
457
|
-
|
458
|
-
|
467
|
+
parent_prop = parent_properties[property_name] || # e.g. "${foo}"
|
468
|
+
parent_properties[property_name.sub(/^project\./, "")] || # e.g. "${project.foo}"
|
469
|
+
parent_properties[property_name.sub(/^project\.parent\./, "")] # e.g. "${project.parent.foo}"
|
459
470
|
|
460
471
|
if prop_field
|
461
472
|
prop_field.nodes.first
|
@@ -472,7 +483,7 @@ module Bibliothecary
|
|
472
483
|
end
|
473
484
|
end
|
474
485
|
|
475
|
-
def self.parse_sbt_update_full(file_contents, options: {})
|
486
|
+
def self.parse_sbt_update_full(file_contents, options: {})
|
476
487
|
all_deps = []
|
477
488
|
lines = file_contents.split("\n")
|
478
489
|
while lines.any?
|
@@ -480,6 +491,7 @@ module Bibliothecary
|
|
480
491
|
|
481
492
|
type_match = SBT_TYPE_REGEXP.match(line)
|
482
493
|
next unless type_match
|
494
|
+
|
483
495
|
type = type_match.captures[0]
|
484
496
|
|
485
497
|
deps = parse_sbt_deps(type, lines)
|
@@ -487,8 +499,8 @@ module Bibliothecary
|
|
487
499
|
end
|
488
500
|
|
489
501
|
# strip out evicted dependencies
|
490
|
-
all_deps.
|
491
|
-
dep[:fields]["evicted"]
|
502
|
+
all_deps.reject! do |dep|
|
503
|
+
dep[:fields]["evicted"] == "true"
|
492
504
|
end
|
493
505
|
|
494
506
|
# in the future, we could use "callers" in the fields to
|
@@ -498,19 +510,23 @@ module Bibliothecary
|
|
498
510
|
|
499
511
|
# clean out any duplicates (I'm pretty sure sbt will have done this for
|
500
512
|
# us so this is paranoia, basically)
|
501
|
-
squished = all_deps.compact.uniq {|item| [item[:name], item[:requirement], item[:type]]}
|
513
|
+
squished = all_deps.compact.uniq { |item| [item[:name], item[:requirement], item[:type]] }
|
502
514
|
|
503
515
|
# get rid of the fields
|
504
516
|
squished.each do |dep|
|
505
517
|
dep.delete(:fields)
|
506
518
|
end
|
507
519
|
|
508
|
-
|
520
|
+
squished.map do |dep_kvs|
|
521
|
+
Dependency.new(
|
522
|
+
**dep_kvs, source: options.fetch(:filename, nil)
|
523
|
+
)
|
524
|
+
end
|
509
525
|
end
|
510
526
|
|
511
527
|
def self.parse_sbt_deps(type, lines)
|
512
528
|
deps = []
|
513
|
-
while lines.any?
|
529
|
+
while lines.any? && !SBT_TYPE_REGEXP.match(lines[0])
|
514
530
|
line = lines.shift
|
515
531
|
|
516
532
|
next if SBT_IGNORE_REGEXP.match(line)
|
@@ -530,7 +546,7 @@ module Bibliothecary
|
|
530
546
|
|
531
547
|
def self.parse_sbt_versions(type, name, lines)
|
532
548
|
versions = []
|
533
|
-
while lines.any?
|
549
|
+
while lines.any? && !SBT_TYPE_REGEXP.match(lines[0])
|
534
550
|
line = lines.shift
|
535
551
|
|
536
552
|
version_match = SBT_VERSION_REGEXP.match(line)
|
@@ -547,7 +563,7 @@ module Bibliothecary
|
|
547
563
|
|
548
564
|
def self.parse_sbt_version(type, name, version, lines)
|
549
565
|
fields = {}
|
550
|
-
while lines.any?
|
566
|
+
while lines.any? && !SBT_TYPE_REGEXP.match(lines[0])
|
551
567
|
line = lines.shift
|
552
568
|
|
553
569
|
field_match = SBT_FIELD_REGEXP.match(line)
|