bibliothecary 12.0.0 → 12.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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 +12 -10
- data/lib/bibliothecary/version.rb +3 -1
- data/lib/bibliothecary.rb +7 -4
- data/lib/sdl_parser.rb +11 -6
- metadata +18 -101
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a0dbcee666f0bade61cdab50c1adf3feccd919c961db92df409845b0d8930a8f
|
4
|
+
data.tar.gz: cff0b5d9c69db6d9438c7d976e503096d75f8ea8991f318e800fdbb8caccc323
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2e1299ec112f03c1322b7084c65e14685a74b778c11cd82c0bde376d7f3ca06be08a01f76139b4237d78671fcfd91779edf7f457e756c98f7344b3f4712594de
|
7
|
+
data.tar.gz: 82388cba64ac674b92b77d364c05787f4ab2effd2dcd244c860b06d2761be4ba30f42a70adf3b3e80cb2d48e11fa12deedac46323447bd887db4d703a8bd9467
|
data/.circleci/config.yml
CHANGED
@@ -5,7 +5,7 @@ orbs:
|
|
5
5
|
executors:
|
6
6
|
bibliothecary:
|
7
7
|
docker:
|
8
|
-
- image: cimg/ruby:3.2.
|
8
|
+
- image: cimg/ruby:3.2.6
|
9
9
|
working_directory: ~/bibliothecary
|
10
10
|
|
11
11
|
|
@@ -20,6 +20,7 @@ commands:
|
|
20
20
|
bundle lock --add-platform x86_64-linux
|
21
21
|
- ruby/install-deps:
|
22
22
|
bundler-version: "2.3"
|
23
|
+
key: gems-v3
|
23
24
|
|
24
25
|
|
25
26
|
jobs:
|
data/.rubocop.yml
CHANGED
@@ -1,8 +1,16 @@
|
|
1
1
|
---
|
2
2
|
|
3
|
+
# Without this, CI might pickup nested dep's rubocop files in vendor/
|
4
|
+
inherit_mode:
|
5
|
+
merge:
|
6
|
+
- Exclude
|
7
|
+
|
3
8
|
AllCops:
|
4
|
-
|
5
|
-
TargetRubyVersion: 3.
|
9
|
+
NewCops: enable
|
10
|
+
TargetRubyVersion: 3.2.6
|
11
|
+
Exclude:
|
12
|
+
- spec/fixtures/**/*
|
13
|
+
- vendor/bundle/**/* # This is actually needed for CI, not for biblio itself
|
6
14
|
|
7
15
|
|
8
16
|
Metrics/BlockLength:
|
data/.ruby-version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
3.2.
|
1
|
+
3.2.6
|
data/CHANGELOG.md
CHANGED
@@ -13,6 +13,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
13
13
|
|
14
14
|
### Removed
|
15
15
|
|
16
|
+
## [12.1.0] - 2025-01-30
|
17
|
+
|
18
|
+
### Added
|
19
|
+
|
20
|
+
- Populate Bibliothecary::Dependency#source field in all parsers. This makes the source field useful when consuming
|
21
|
+
from Bibliothecary, and removes a step from consumers having to populate this field themselves.
|
22
|
+
|
23
|
+
### Changed
|
24
|
+
|
25
|
+
- Improved Rubocop rules to make future spec changes easier via Rubocop auto-correcting formatting violations.
|
26
|
+
|
27
|
+
### Removed
|
28
|
+
|
16
29
|
## [12.0.0] - 2025-01-27
|
17
30
|
|
18
31
|
### Removed
|
data/Gemfile
CHANGED
@@ -1,9 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
source "https://rubygems.org"
|
2
4
|
|
3
5
|
# Specify your gem's dependencies in bibliothecary.gemspec
|
4
6
|
gemspec
|
5
7
|
|
8
|
+
group :development do
|
9
|
+
gem "pry"
|
10
|
+
end
|
11
|
+
|
12
|
+
group :development, :test do
|
13
|
+
gem "rake", "~> 12.0"
|
14
|
+
gem "rubocop", "~> 1.71"
|
15
|
+
gem "rubocop-rails"
|
16
|
+
gem "rubocop-rake" # This is needed by packageurl-ruby, until it reclassifies it as a dev dependency.
|
17
|
+
end
|
18
|
+
|
6
19
|
group :test do
|
7
|
-
gem "simplecov"
|
8
20
|
gem "codeclimate-test-reporter", "~> 1.0.0"
|
21
|
+
gem "rspec", "~> 3.0"
|
22
|
+
gem "simplecov"
|
23
|
+
gem "webmock"
|
9
24
|
end
|
data/Rakefile
CHANGED
data/bibliothecary.gemspec
CHANGED
@@ -1,9 +1,12 @@
|
|
1
|
-
#
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
lib = File.expand_path("lib", __dir__)
|
3
4
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
5
|
require "bibliothecary/version"
|
5
6
|
|
6
7
|
Gem::Specification.new do |spec|
|
8
|
+
spec.required_ruby_version = ">= 3.2.0"
|
9
|
+
|
7
10
|
spec.name = "bibliothecary"
|
8
11
|
spec.version = Bibliothecary::VERSION
|
9
12
|
spec.authors = ["Andrew Nesbitt"]
|
@@ -18,19 +21,14 @@ Gem::Specification.new do |spec|
|
|
18
21
|
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
19
22
|
spec.require_paths = ["lib"]
|
20
23
|
|
21
|
-
spec.add_dependency "
|
24
|
+
spec.add_dependency "commander"
|
25
|
+
spec.add_dependency "deb_control"
|
22
26
|
spec.add_dependency "librariesio-gem-parser"
|
23
27
|
spec.add_dependency "ox", ">= 2.8.1"
|
24
|
-
spec.add_dependency "typhoeus"
|
25
|
-
spec.add_dependency "deb_control"
|
26
|
-
spec.add_dependency "sdl4r"
|
27
|
-
spec.add_dependency "commander"
|
28
28
|
spec.add_dependency "packageurl-ruby"
|
29
|
+
spec.add_dependency "sdl4r"
|
30
|
+
spec.add_dependency "tomlrb", "~> 2.0"
|
31
|
+
spec.add_dependency "typhoeus"
|
29
32
|
|
30
|
-
spec.
|
31
|
-
spec.add_development_dependency "rake", "~> 12.0"
|
32
|
-
spec.add_development_dependency "rspec", "~> 3.0"
|
33
|
-
spec.add_development_dependency "webmock"
|
34
|
-
spec.add_development_dependency "rubocop"
|
35
|
-
spec.add_development_dependency "rubocop-rails"
|
33
|
+
spec.metadata["rubygems_mfa_required"] = "true"
|
36
34
|
end
|
data/bin/bibliothecary
CHANGED
data/bin/console
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Bibliothecary
|
2
4
|
module Analyser
|
3
5
|
module Analysis
|
@@ -42,25 +44,29 @@ module Bibliothecary
|
|
42
44
|
|
43
45
|
dependencies_to_analysis(info, kind, dependencies)
|
44
46
|
rescue Bibliothecary::FileParsingError => e
|
45
|
-
Bibliothecary::Analyser
|
47
|
+
Bibliothecary::Analyser.create_error_analysis(platform_name, info.relative_path, kind, e.message, e.location)
|
46
48
|
end
|
47
49
|
alias analyze_contents_from_info analyse_contents_from_info
|
48
50
|
|
49
51
|
def dependencies_to_analysis(info, kind, dependencies)
|
50
|
-
dependencies
|
52
|
+
dependencies ||= [] # work around any legacy parsers that return nil
|
51
53
|
if generic?
|
52
54
|
grouped = dependencies.group_by { |dep| dep[:platform] }
|
53
55
|
all_analyses = grouped.keys.map do |platform|
|
54
|
-
deplatformed_dependencies = grouped[platform].map
|
55
|
-
|
56
|
+
deplatformed_dependencies = grouped[platform].map do |d|
|
57
|
+
d.delete(:platform)
|
58
|
+
d
|
59
|
+
end
|
60
|
+
Bibliothecary::Analyser.create_analysis(platform, info.relative_path, kind, deplatformed_dependencies)
|
56
61
|
end
|
57
62
|
# this is to avoid a larger refactor for the time being. The larger refactor
|
58
63
|
# needs to make analyse_contents return multiple analysis, or add another
|
59
64
|
# method that can return multiple and deprecate analyse_contents, perhaps.
|
60
65
|
raise "File contains zero or multiple platforms, currently must have exactly one" if all_analyses.length != 1
|
66
|
+
|
61
67
|
all_analyses.first
|
62
68
|
else
|
63
|
-
Bibliothecary::Analyser
|
69
|
+
Bibliothecary::Analyser.create_analysis(platform_name, info.relative_path, kind, dependencies)
|
64
70
|
end
|
65
71
|
end
|
66
72
|
|
@@ -81,8 +87,7 @@ module Bibliothecary
|
|
81
87
|
# this comment, some of the parsers return [] or nil to mean an error
|
82
88
|
# which is confusing to users.
|
83
89
|
send(details[:parser], contents, options: options.merge(filename: filename))
|
84
|
-
|
85
|
-
rescue Exception => e # default is StandardError but C bindings throw Exceptions
|
90
|
+
rescue Exception => e # default is StandardError but C bindings throw Exceptions # rubocop:disable Lint/RescueException
|
86
91
|
# the C xml parser also puts a newline at the end of the message
|
87
92
|
location = e.backtrace_locations[0]
|
88
93
|
.to_s
|
@@ -97,7 +102,7 @@ module Bibliothecary
|
|
97
102
|
|
98
103
|
kind = determine_kind_from_info(info)
|
99
104
|
relate_to_kind = first_matching_mapping_details(info)
|
100
|
-
.fetch(:related_to, %w
|
105
|
+
.fetch(:related_to, %w[manifest lockfile].reject { |k| k == kind })
|
101
106
|
dirname = File.dirname(info.relative_path)
|
102
107
|
|
103
108
|
infos
|
@@ -1,42 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Bibliothecary
|
2
4
|
module Analyser
|
3
5
|
module Matchers
|
4
6
|
def match_filename(filename, case_insensitive: false)
|
5
7
|
if case_insensitive
|
6
|
-
|
8
|
+
->(path) { path.downcase == filename.downcase || path.downcase.end_with?("/#{filename.downcase}") }
|
7
9
|
else
|
8
|
-
|
10
|
+
->(path) { path == filename || path.end_with?("/#{filename}") }
|
9
11
|
end
|
10
12
|
end
|
11
13
|
|
12
14
|
def match_filenames(*filenames)
|
13
15
|
lambda do |path|
|
14
16
|
filenames.any? { |f| path == f } ||
|
15
|
-
filenames.any? { |f| path.end_with?("
|
17
|
+
filenames.any? { |f| path.end_with?("/#{f}") }
|
16
18
|
end
|
17
19
|
end
|
18
20
|
|
19
21
|
def match_extension(filename, case_insensitive: false)
|
20
22
|
if case_insensitive
|
21
|
-
|
23
|
+
->(path) { path.downcase.end_with?(filename.downcase) }
|
22
24
|
else
|
23
|
-
|
25
|
+
->(path) { path.end_with?(filename) }
|
24
26
|
end
|
25
27
|
end
|
26
28
|
|
27
29
|
def mapping_entry_match?(matcher, details, info)
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
return false
|
39
|
-
end
|
30
|
+
return false unless matcher.call(info.relative_path)
|
31
|
+
# we only want to load contents if we don't have them already
|
32
|
+
# and there's a content_matcher method to use
|
33
|
+
return true if details[:content_matcher].nil?
|
34
|
+
# this is the libraries.io case where we won't load all .xml
|
35
|
+
# files (for example) just to look at their contents, we'll
|
36
|
+
# assume they are not manifests.
|
37
|
+
return false if info.contents.nil?
|
38
|
+
|
39
|
+
send(details[:content_matcher], info.contents)
|
40
40
|
end
|
41
41
|
|
42
42
|
# this is broken with contents=nil because it can't look at file
|
@@ -1,10 +1,12 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require_relative "
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "analyser/matchers"
|
4
|
+
require_relative "analyser/determinations"
|
5
|
+
require_relative "analyser/analysis"
|
4
6
|
|
5
7
|
module Bibliothecary
|
6
8
|
module Analyser
|
7
|
-
def self.create_error_analysis(platform_name, relative_path, kind, message, location=nil)
|
9
|
+
def self.create_error_analysis(platform_name, relative_path, kind, message, location = nil)
|
8
10
|
{
|
9
11
|
platform: platform_name,
|
10
12
|
path: relative_path,
|
@@ -53,15 +55,16 @@ module Bibliothecary
|
|
53
55
|
end
|
54
56
|
|
55
57
|
def platform_name
|
56
|
-
|
58
|
+
name.to_s.split("::").last.downcase
|
57
59
|
end
|
58
60
|
|
59
|
-
def map_dependencies(hash, key, type)
|
60
|
-
hash.fetch(key,[]).map do |name, requirement|
|
61
|
+
def map_dependencies(hash, key, type, source = nil)
|
62
|
+
hash.fetch(key, []).map do |name, requirement|
|
61
63
|
Dependency.new(
|
62
64
|
name: name,
|
63
65
|
requirement: requirement,
|
64
66
|
type: type,
|
67
|
+
source: source
|
65
68
|
)
|
66
69
|
end
|
67
70
|
end
|
@@ -75,7 +78,7 @@ module Bibliothecary
|
|
75
78
|
def add_multi_parser(klass)
|
76
79
|
raise "No mapping found! You should place the add_multi_parser call below def self.mapping." unless respond_to?(:mapping)
|
77
80
|
|
78
|
-
original_mapping =
|
81
|
+
original_mapping = mapping
|
79
82
|
|
80
83
|
define_singleton_method(:mapping) do
|
81
84
|
original_mapping.merge(klass.mapping)
|
data/lib/bibliothecary/cli.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "bibliothecary/version"
|
2
4
|
require "bibliothecary"
|
3
5
|
require "commander"
|
@@ -20,7 +22,7 @@ module Bibliothecary
|
|
20
22
|
output = Bibliothecary.analyse(options.path)
|
21
23
|
output.each do |file_contents|
|
22
24
|
puts "#{file_contents[:path]} (#{file_contents[:platform]})"
|
23
|
-
file_contents[:dependencies].group_by{|d| d[:type] }.each do |type, deps|
|
25
|
+
file_contents[:dependencies].group_by { |d| d[:type] }.each do |type, deps|
|
24
26
|
puts " #{type}"
|
25
27
|
deps.each do |dep|
|
26
28
|
puts " #{dep[:name]} #{dep[:requirement]}"
|
@@ -1,13 +1,8 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Bibliothecary
|
2
4
|
class Configuration
|
3
|
-
attr_accessor :ignored_dirs
|
4
|
-
attr_accessor :ignored_files
|
5
|
-
attr_accessor :carthage_parser_host
|
6
|
-
attr_accessor :clojars_parser_host
|
7
|
-
attr_accessor :mix_parser_host
|
8
|
-
attr_accessor :conda_parser_host
|
9
|
-
attr_accessor :swift_parser_host
|
10
|
-
attr_accessor :cabal_parser_host
|
5
|
+
attr_accessor :ignored_dirs, :ignored_files, :carthage_parser_host, :clojars_parser_host, :mix_parser_host, :conda_parser_host, :swift_parser_host, :cabal_parser_host
|
11
6
|
|
12
7
|
def initialize
|
13
8
|
@ignored_dirs = [".git", "node_modules", "bower_components", "vendor", "dist"]
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Bibliothecary
|
2
4
|
# Dependency represents a single unique dependency that was parsed out of a manifest.
|
3
5
|
#
|
@@ -19,21 +21,21 @@ module Bibliothecary
|
|
19
21
|
# @source [String] source An optional string to store the location of the manifest that contained this
|
20
22
|
# dependency, e.g. "src/package.json".
|
21
23
|
class Dependency
|
22
|
-
FIELDS = [
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
]
|
24
|
+
FIELDS = %i[
|
25
|
+
name
|
26
|
+
requirement
|
27
|
+
original_requirement
|
28
|
+
platform
|
29
|
+
type
|
30
|
+
direct
|
31
|
+
deprecated
|
32
|
+
local
|
33
|
+
optional
|
34
|
+
original_name
|
35
|
+
source
|
36
|
+
].freeze
|
35
37
|
|
36
|
-
attr_reader
|
38
|
+
attr_reader(*FIELDS)
|
37
39
|
|
38
40
|
def initialize(
|
39
41
|
name:,
|
@@ -64,7 +66,7 @@ module Bibliothecary
|
|
64
66
|
def eql?(other)
|
65
67
|
FIELDS.all? { |f| public_send(f) == other.public_send(f) }
|
66
68
|
end
|
67
|
-
alias
|
69
|
+
alias == eql?
|
68
70
|
|
69
71
|
def [](key)
|
70
72
|
public_send(key)
|
@@ -1,6 +1,9 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Bibliothecary
|
2
4
|
class RemoteParsingError < StandardError
|
3
5
|
attr_accessor :code
|
6
|
+
|
4
7
|
def initialize(msg, code)
|
5
8
|
@code = code
|
6
9
|
super(msg)
|
@@ -9,11 +12,12 @@ module Bibliothecary
|
|
9
12
|
|
10
13
|
class FileParsingError < StandardError
|
11
14
|
attr_accessor :filename, :location
|
12
|
-
|
15
|
+
|
16
|
+
def initialize(msg, filename, location = nil)
|
13
17
|
@filename = filename
|
14
18
|
@location = location # source code location of the error, e.g. "lib/hi.rb:34"
|
15
19
|
msg = "#{filename}: #{msg}" unless msg.include?(filename)
|
16
|
-
super(
|
20
|
+
super(msg.to_s)
|
17
21
|
end
|
18
22
|
end
|
19
23
|
end
|
@@ -1,24 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "pathname"
|
2
4
|
|
3
5
|
module Bibliothecary
|
4
6
|
# A representation of a file on the filesystem, with location information
|
5
7
|
# and package manager information if needed.
|
6
8
|
class FileInfo
|
7
|
-
attr_reader :folder_path
|
8
|
-
attr_reader :relative_path
|
9
|
-
attr_reader :full_path
|
9
|
+
attr_reader :folder_path, :relative_path, :full_path
|
10
10
|
attr_accessor :package_manager
|
11
11
|
|
12
12
|
def contents
|
13
13
|
@contents ||=
|
14
|
-
|
15
|
-
if
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
Bibliothecary.utf8_string(File.open(@full_path).read)
|
21
|
-
end
|
14
|
+
if @folder_path.nil?
|
15
|
+
# if we have no folder_path then we aren't dealing with a
|
16
|
+
# file that's actually on the filesystem
|
17
|
+
nil
|
18
|
+
else
|
19
|
+
Bibliothecary.utf8_string(File.read(@full_path))
|
22
20
|
end
|
23
21
|
end
|
24
22
|
|
@@ -1,20 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Bibliothecary
|
2
4
|
module MultiParsers
|
3
5
|
module BundlerLikeManifest
|
4
6
|
# this takes parsed Bundler and Bundler-like (CocoaPods)
|
5
7
|
# manifests and turns them into a list of dependencies.
|
6
|
-
def parse_ruby_manifest(manifest)
|
8
|
+
def parse_ruby_manifest(manifest, source = nil)
|
7
9
|
manifest.dependencies.inject([]) do |deps, dep|
|
8
10
|
deps.push(Dependency.new(
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
11
|
+
name: dep.name,
|
12
|
+
requirement: dep
|
13
|
+
.requirement
|
14
|
+
.requirements
|
15
|
+
.sort_by(&:last)
|
16
|
+
.map { |op, version| "#{op} #{version}" }
|
17
|
+
.join(", "),
|
18
|
+
type: dep.type.to_s,
|
19
|
+
source: source
|
20
|
+
))
|
18
21
|
end.uniq
|
19
22
|
end
|
20
23
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "json"
|
2
4
|
require "ox"
|
3
5
|
|
@@ -28,23 +30,24 @@ module Bibliothecary
|
|
28
30
|
@parse_queue = parse_queue.dup
|
29
31
|
end
|
30
32
|
|
31
|
-
def
|
33
|
+
def add(purl, source = nil)
|
32
34
|
mapping = PurlUtil::PURL_TYPE_MAPPING[purl.type]
|
33
35
|
return unless mapping
|
34
36
|
|
35
37
|
@manifests[mapping] ||= Set.new
|
36
|
-
@manifests[mapping] <<
|
38
|
+
@manifests[mapping] << Dependency.new(
|
37
39
|
name: PurlUtil.full_name(purl),
|
38
40
|
requirement: purl.version,
|
39
41
|
type: "lockfile",
|
42
|
+
source: source
|
40
43
|
)
|
41
44
|
end
|
42
45
|
|
43
46
|
# Iterates over each manifest entry in the parse_queue, and accepts a block which will
|
44
47
|
# be called on each component. The block has two jobs: 1) add more sub-components
|
45
48
|
# to parse (if they exist), and 2) return the components purl.
|
46
|
-
def parse!(&block)
|
47
|
-
|
49
|
+
def parse!(source = nil, &block)
|
50
|
+
until @parse_queue.empty?
|
48
51
|
component = @parse_queue.shift
|
49
52
|
|
50
53
|
purl_text = block.call(component, @parse_queue)
|
@@ -53,7 +56,7 @@ module Bibliothecary
|
|
53
56
|
|
54
57
|
purl = PackageURL.parse(purl_text)
|
55
58
|
|
56
|
-
|
59
|
+
add(purl, source)
|
57
60
|
end
|
58
61
|
end
|
59
62
|
|
@@ -88,7 +91,6 @@ module Bibliothecary
|
|
88
91
|
end
|
89
92
|
|
90
93
|
def parse_cyclonedx_json(file_contents, options: {})
|
91
|
-
|
92
94
|
manifest = try_cache(options, options[:filename]) do
|
93
95
|
JSON.parse(file_contents)
|
94
96
|
end
|
@@ -97,7 +99,7 @@ module Bibliothecary
|
|
97
99
|
|
98
100
|
entries = ManifestEntries.new(parse_queue: manifest["components"])
|
99
101
|
|
100
|
-
entries.parse! do |component, parse_queue|
|
102
|
+
entries.parse!(options.fetch(:filename, nil)) do |component, parse_queue|
|
101
103
|
parse_queue.concat(component["components"]) if component["components"]
|
102
104
|
|
103
105
|
component["purl"]
|
@@ -120,7 +122,7 @@ module Bibliothecary
|
|
120
122
|
|
121
123
|
entries = ManifestEntries.new(parse_queue: root.locate("components/*"))
|
122
124
|
|
123
|
-
entries.parse! do |component, parse_queue|
|
125
|
+
entries.parse!(options.fetch(:filename, nil)) do |component, parse_queue|
|
124
126
|
# #locate returns an empty array if nothing is found, so we can
|
125
127
|
# always safely concatenate it to the parse queue.
|
126
128
|
parse_queue.concat(component.locate("components/*"))
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "csv"
|
2
4
|
|
3
5
|
module Bibliothecary
|
@@ -55,7 +57,7 @@ module Bibliothecary
|
|
55
57
|
/^(manifest |)type$/i,
|
56
58
|
],
|
57
59
|
},
|
58
|
-
}
|
60
|
+
}.freeze
|
59
61
|
|
60
62
|
attr_reader :result
|
61
63
|
|
@@ -79,7 +81,7 @@ module Bibliothecary
|
|
79
81
|
# some column have default data to fall back on
|
80
82
|
if row_data
|
81
83
|
obj[header.to_sym] = row_data
|
82
|
-
elsif info.
|
84
|
+
elsif info.key?(:default)
|
83
85
|
# if the default is nil, don't even add the key to the hash
|
84
86
|
obj[header.to_sym] = info[:default] if info[:default]
|
85
87
|
else
|
@@ -99,6 +101,7 @@ module Bibliothecary
|
|
99
101
|
unless header_examination_results[:missing].empty?
|
100
102
|
raise "Missing required headers #{header_examination_results[:missing].join(', ')} in CSV. Check to make sure header names are all lowercase."
|
101
103
|
end
|
104
|
+
|
102
105
|
@header_mappings = header_examination_results[:found]
|
103
106
|
|
104
107
|
table
|
@@ -114,7 +117,7 @@ module Bibliothecary
|
|
114
117
|
|
115
118
|
if results.empty?
|
116
119
|
# if a header has a default value it's optional
|
117
|
-
obj[:missing] << header unless info.
|
120
|
+
obj[:missing] << header unless info.key?(:default)
|
118
121
|
else
|
119
122
|
# select the highest priority header possible
|
120
123
|
obj[:found][header] ||= nil
|
@@ -139,7 +142,11 @@ module Bibliothecary
|
|
139
142
|
csv_file
|
140
143
|
.result
|
141
144
|
.find_all { |dependency| dependency[:platform] == platform_name.to_s }
|
142
|
-
.map
|
145
|
+
.map do |dep_kvs|
|
146
|
+
Dependency.new(
|
147
|
+
**dep_kvs, source: options.fetch(:filename, nil)
|
148
|
+
)
|
149
|
+
end
|
143
150
|
end
|
144
151
|
end
|
145
152
|
end
|
@@ -1,13 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Bibliothecary
|
2
4
|
module MultiParsers
|
3
5
|
# Provide JSON Runtime Manifest parsing
|
4
6
|
module JSONRuntime
|
5
|
-
def parse_json_runtime_manifest(file_contents, options: {})
|
6
|
-
JSON.parse(file_contents).fetch("dependencies",[]).map do |name, requirement|
|
7
|
+
def parse_json_runtime_manifest(file_contents, options: {})
|
8
|
+
JSON.parse(file_contents).fetch("dependencies", []).map do |name, requirement|
|
7
9
|
Dependency.new(
|
8
10
|
name: name,
|
9
11
|
requirement: requirement,
|
10
12
|
type: "runtime",
|
13
|
+
source: options.fetch(:filename, nil)
|
11
14
|
)
|
12
15
|
end
|
13
16
|
end
|