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
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d8e2830107d4af8ea1786726bec39b1dca7fb5f1a1781c1a3920724051756cac
|
4
|
+
data.tar.gz: fd853b4548499189a52b54ebd43515260bbec6883ae96895e30aa5108d520deb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8c5ae04b3ee683f011ec62de58abaf5d859f7449e513a2ec66dc95d7d3baf55c6385d8c2743c0f96f3b730ae78e1f37610d3192b5bcaaff3fb21d7fea27e5a8a
|
7
|
+
data.tar.gz: 49b5202b66e8dbc1b1c77f207e5e6d7b0b4e69927a162083db94b0012815e6e892ea43df287c71285c97d9f9223e4ceca449c992a09e33be10d6b2cd901657f0
|
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
|