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.
Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +2 -1
  3. data/.rubocop.yml +10 -2
  4. data/.ruby-version +1 -1
  5. data/CHANGELOG.md +13 -0
  6. data/Gemfile +16 -1
  7. data/Rakefile +2 -0
  8. data/bibliothecary.gemspec +11 -13
  9. data/bin/bibliothecary +2 -1
  10. data/bin/console +1 -0
  11. data/lib/bibliothecary/analyser/analysis.rb +13 -8
  12. data/lib/bibliothecary/analyser/determinations.rb +2 -0
  13. data/lib/bibliothecary/analyser/matchers.rb +17 -17
  14. data/lib/bibliothecary/analyser.rb +11 -8
  15. data/lib/bibliothecary/cli.rb +3 -1
  16. data/lib/bibliothecary/configuration.rb +3 -8
  17. data/lib/bibliothecary/dependency.rb +17 -15
  18. data/lib/bibliothecary/exceptions.rb +6 -2
  19. data/lib/bibliothecary/file_info.rb +9 -11
  20. data/lib/bibliothecary/multi_parsers/bundler_like_manifest.rb +13 -10
  21. data/lib/bibliothecary/multi_parsers/cyclonedx.rb +10 -8
  22. data/lib/bibliothecary/multi_parsers/dependencies_csv.rb +11 -4
  23. data/lib/bibliothecary/multi_parsers/json_runtime.rb +5 -2
  24. data/lib/bibliothecary/multi_parsers/spdx.rb +24 -19
  25. data/lib/bibliothecary/parsers/bower.rb +5 -3
  26. data/lib/bibliothecary/parsers/cargo.rb +10 -4
  27. data/lib/bibliothecary/parsers/cocoapods.rb +15 -11
  28. data/lib/bibliothecary/parsers/conda.rb +20 -18
  29. data/lib/bibliothecary/parsers/cpan.rb +6 -4
  30. data/lib/bibliothecary/parsers/cran.rb +10 -6
  31. data/lib/bibliothecary/parsers/dub.rb +4 -2
  32. data/lib/bibliothecary/parsers/elm.rb +4 -1
  33. data/lib/bibliothecary/parsers/go.rb +51 -43
  34. data/lib/bibliothecary/parsers/haxelib.rb +2 -1
  35. data/lib/bibliothecary/parsers/julia.rb +5 -1
  36. data/lib/bibliothecary/parsers/maven.rb +93 -77
  37. data/lib/bibliothecary/parsers/meteor.rb +2 -0
  38. data/lib/bibliothecary/parsers/npm.rb +89 -75
  39. data/lib/bibliothecary/parsers/nuget.rb +37 -28
  40. data/lib/bibliothecary/parsers/packagist.rb +21 -11
  41. data/lib/bibliothecary/parsers/pub.rb +4 -2
  42. data/lib/bibliothecary/parsers/pypi.rb +48 -29
  43. data/lib/bibliothecary/parsers/rubygems.rb +16 -12
  44. data/lib/bibliothecary/parsers/shard.rb +10 -7
  45. data/lib/bibliothecary/purl_util.rb +2 -1
  46. data/lib/bibliothecary/related_files_info.rb +7 -8
  47. data/lib/bibliothecary/runner/multi_manifest_filter.rb +5 -4
  48. data/lib/bibliothecary/runner.rb +13 -10
  49. data/lib/bibliothecary/version.rb +3 -1
  50. data/lib/bibliothecary.rb +7 -4
  51. data/lib/sdl_parser.rb +11 -6
  52. metadata +19 -106
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 12b592879fc7f4fbe3622f495e8ef989b541c81487915b693d02907cedeb62a0
4
- data.tar.gz: fd266f3924f202a864017c52ff1c2eb84fd68c4451b16b95e6aa44d80b850598
3
+ metadata.gz: d8e2830107d4af8ea1786726bec39b1dca7fb5f1a1781c1a3920724051756cac
4
+ data.tar.gz: fd853b4548499189a52b54ebd43515260bbec6883ae96895e30aa5108d520deb
5
5
  SHA512:
6
- metadata.gz: e4622e4be1424fd679fac201929bcdf77ed02f0f5782799cf506c93af1d21b803a7e8319e8f471b4747eb5d1a02dba3c0bf8914bae3c4a7a9c95c1b49c37c7b8
7
- data.tar.gz: 16950d0fdfcf98cbef1b0faeb61fe1e398816b5499a2fe7af02ea3380975fce4bf85e81a64bfc2d9bb382753f2bdd538e2a46896e8a7e08476716a777adc32aa
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.4
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
- DisabledByDefault: true
5
- TargetRubyVersion: 3.0
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.4
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
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "bundler/gem_tasks"
2
4
  require "rspec/core/rake_task"
3
5
 
@@ -1,9 +1,12 @@
1
- # coding: utf-8
2
- lib = File.expand_path("../lib", __FILE__)
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 "tomlrb", "~> 2.0"
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.add_development_dependency "pry"
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
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
 
3
- lib = File.expand_path("../../lib", __FILE__)
4
+ lib = File.expand_path("../lib", __dir__)
4
5
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
6
 
6
7
  require "bibliothecary/cli"
data/bin/console CHANGED
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
 
3
4
  require "bundler/setup"
4
5
  require "bibliothecary"
@@ -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::create_error_analysis(platform_name, info.relative_path, kind, e.message, e.location)
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 = dependencies || [] # work around any legacy parsers that return nil
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 { |d| d.delete(:platform); d }
55
- Bibliothecary::Analyser::create_analysis(platform, info.relative_path, kind, deplatformed_dependencies)
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::create_analysis(platform_name, info.relative_path, kind, dependencies)
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(manifest lockfile).reject { |k| k == kind })
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,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Bibliothecary
2
4
  module Analyser
3
5
  module Determinations
@@ -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
- lambda { |path| path.downcase == filename.downcase || path.downcase.end_with?("/" + filename.downcase) }
8
+ ->(path) { path.downcase == filename.downcase || path.downcase.end_with?("/#{filename.downcase}") }
7
9
  else
8
- lambda { |path| path == filename || path.end_with?("/" + filename) }
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?("/" + f) }
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
- lambda { |path| path.downcase.end_with?(filename.downcase) }
23
+ ->(path) { path.downcase.end_with?(filename.downcase) }
22
24
  else
23
- lambda { |path| path.end_with?(filename) }
25
+ ->(path) { path.end_with?(filename) }
24
26
  end
25
27
  end
26
28
 
27
29
  def mapping_entry_match?(matcher, details, info)
28
- if matcher.call(info.relative_path)
29
- # we only want to load contents if we don't have them already
30
- # and there's a content_matcher method to use
31
- return true if details[:content_matcher].nil?
32
- # this is the libraries.io case where we won't load all .xml
33
- # files (for example) just to look at their contents, we'll
34
- # assume they are not manifests.
35
- return false if info.contents.nil?
36
- return send(details[:content_matcher], info.contents)
37
- else
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
- require_relative "./analyser/matchers.rb"
2
- require_relative "./analyser/determinations.rb"
3
- require_relative "./analyser/analysis.rb"
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
- self.name.to_s.split("::").last.downcase
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 = self.mapping
81
+ original_mapping = mapping
79
82
 
80
83
  define_singleton_method(:mapping) do
81
84
  original_mapping.merge(klass.mapping)
@@ -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
- :name,
24
- :requirement,
25
- :original_requirement,
26
- :platform,
27
- :type,
28
- :direct,
29
- :deprecated,
30
- :local,
31
- :optional,
32
- :original_name,
33
- :source,
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 *FIELDS
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 :== :eql?
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
- def initialize(msg, filename, location=nil)
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("#{msg}")
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
- begin
15
- if @folder_path.nil?
16
- # if we have no folder_path then we aren't dealing with a
17
- # file that's actually on the filesystem
18
- nil
19
- else
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
- name: dep.name,
10
- requirement: dep
11
- .requirement
12
- .requirements
13
- .sort_by(&:last)
14
- .map { |op, version| "#{op} #{version}" }
15
- .join(", "),
16
- type: dep.type.to_s,
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 <<(purl)
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] << Dependency.new(
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
- while @parse_queue.length > 0
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
- self << purl
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.has_key?(:default)
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.has_key?(:default)
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 { |dep_kvs| Dependency.new(**dep_kvs) }
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: {}) # rubocop:disable Lint/UnusedMethodArgument
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