bibliothecary 8.7.4 → 8.7.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +21 -4
  3. data/.rubocop.yml +32 -941
  4. data/Gemfile +1 -1
  5. data/Rakefile +10 -0
  6. data/bibliothecary.gemspec +2 -2
  7. data/lib/bibliothecary/analyser.rb +6 -6
  8. data/lib/bibliothecary/cli.rb +8 -8
  9. data/lib/bibliothecary/configuration.rb +8 -8
  10. data/lib/bibliothecary/file_info.rb +2 -2
  11. data/lib/bibliothecary/multi_parsers/bundler_like_manifest.rb +1 -1
  12. data/lib/bibliothecary/multi_parsers/cyclonedx.rb +16 -17
  13. data/lib/bibliothecary/multi_parsers/dependencies_csv.rb +16 -16
  14. data/lib/bibliothecary/multi_parsers/json_runtime.rb +3 -3
  15. data/lib/bibliothecary/multi_parsers/spdx.rb +14 -14
  16. data/lib/bibliothecary/parsers/bower.rb +7 -7
  17. data/lib/bibliothecary/parsers/cargo.rb +15 -15
  18. data/lib/bibliothecary/parsers/carthage.rb +16 -16
  19. data/lib/bibliothecary/parsers/clojars.rb +7 -7
  20. data/lib/bibliothecary/parsers/cocoapods.rb +20 -20
  21. data/lib/bibliothecary/parsers/conda.rb +9 -9
  22. data/lib/bibliothecary/parsers/cpan.rb +12 -12
  23. data/lib/bibliothecary/parsers/cran.rb +12 -12
  24. data/lib/bibliothecary/parsers/dub.rb +8 -8
  25. data/lib/bibliothecary/parsers/elm.rb +8 -8
  26. data/lib/bibliothecary/parsers/go.rb +131 -66
  27. data/lib/bibliothecary/parsers/hackage.rb +13 -13
  28. data/lib/bibliothecary/parsers/haxelib.rb +4 -4
  29. data/lib/bibliothecary/parsers/hex.rb +11 -11
  30. data/lib/bibliothecary/parsers/julia.rb +4 -4
  31. data/lib/bibliothecary/parsers/maven.rb +88 -89
  32. data/lib/bibliothecary/parsers/meteor.rb +4 -4
  33. data/lib/bibliothecary/parsers/npm.rb +31 -31
  34. data/lib/bibliothecary/parsers/nuget.rb +44 -44
  35. data/lib/bibliothecary/parsers/packagist.rb +14 -14
  36. data/lib/bibliothecary/parsers/pub.rb +13 -13
  37. data/lib/bibliothecary/parsers/pypi.rb +71 -71
  38. data/lib/bibliothecary/parsers/rubygems.rb +15 -15
  39. data/lib/bibliothecary/parsers/shard.rb +13 -13
  40. data/lib/bibliothecary/parsers/swift_pm.rb +6 -6
  41. data/lib/bibliothecary/purl_util.rb +1 -1
  42. data/lib/bibliothecary/runner.rb +4 -4
  43. data/lib/bibliothecary/version.rb +1 -1
  44. data/lib/bibliothecary.rb +3 -3
  45. data/lib/sdl_parser.rb +5 -5
  46. metadata +2 -2
@@ -1,4 +1,4 @@
1
- require 'json'
1
+ require "json"
2
2
 
3
3
  module Bibliothecary
4
4
  module Parsers
@@ -11,25 +11,25 @@ module Bibliothecary
11
11
  def self.mapping
12
12
  {
13
13
  match_filename("package.json") => {
14
- kind: 'manifest',
15
- parser: :parse_manifest
14
+ kind: "manifest",
15
+ parser: :parse_manifest,
16
16
  },
17
17
  match_filename("npm-shrinkwrap.json") => {
18
- kind: 'lockfile',
19
- parser: :parse_shrinkwrap
18
+ kind: "lockfile",
19
+ parser: :parse_shrinkwrap,
20
20
  },
21
21
  match_filename("yarn.lock") => {
22
- kind: 'lockfile',
23
- parser: :parse_yarn_lock
22
+ kind: "lockfile",
23
+ parser: :parse_yarn_lock,
24
24
  },
25
25
  match_filename("package-lock.json") => {
26
- kind: 'lockfile',
27
- parser: :parse_package_lock
26
+ kind: "lockfile",
27
+ parser: :parse_package_lock,
28
28
  },
29
29
  match_filename("npm-ls.json") => {
30
- kind: 'lockfile',
31
- parser: :parse_ls
32
- }
30
+ kind: "lockfile",
31
+ parser: :parse_ls,
32
+ },
33
33
  }
34
34
  end
35
35
 
@@ -37,7 +37,7 @@ module Bibliothecary
37
37
  add_multi_parser(Bibliothecary::MultiParsers::Spdx)
38
38
  add_multi_parser(Bibliothecary::MultiParsers::DependenciesCSV)
39
39
 
40
- def self.parse_package_lock(file_contents, options: {})
40
+ def self.parse_package_lock(file_contents, options: {}) # rubocop:disable Lint/UnusedMethodArgument
41
41
  manifest = JSON.parse(file_contents)
42
42
  # https://docs.npmjs.com/cli/v9/configuring-npm/package-lock-json#lockfileversion
43
43
  if manifest["lockfileVersion"].to_i <= 1
@@ -56,54 +56,54 @@ module Bibliothecary
56
56
  end
57
57
 
58
58
  def self.parse_package_lock_v1(manifest)
59
- parse_package_lock_deps_recursively(manifest.fetch('dependencies', []))
59
+ parse_package_lock_deps_recursively(manifest.fetch("dependencies", []))
60
60
  end
61
61
 
62
62
  def self.parse_package_lock_v2(manifest)
63
63
  # "packages" is a flat object where each key is the installed location of the dep, e.g. node_modules/foo/node_modules/bar.
64
64
  manifest
65
65
  .fetch("packages")
66
- .reject { |name, dep| name == "" } # this is the lockfile's package itself
66
+ .reject { |name, _dep| name == "" } # this is the lockfile's package itself
67
67
  .map do |name, dep|
68
68
  {
69
69
  name: name.split("node_modules/").last,
70
70
  requirement: dep["version"],
71
- type: dep.fetch("dev", false) || dep.fetch("devOptional", false) ? "development" : "runtime"
71
+ type: dep.fetch("dev", false) || dep.fetch("devOptional", false) ? "development" : "runtime",
72
72
  }
73
73
  end
74
74
  end
75
75
 
76
76
  def self.parse_package_lock_deps_recursively(dependencies, depth=1)
77
77
  dependencies.flat_map do |name, requirement|
78
- type = requirement.fetch("dev", false) ? 'development' : 'runtime'
78
+ type = requirement.fetch("dev", false) ? "development" : "runtime"
79
79
  version = requirement.key?("from") ? requirement["from"][/#(?:semver:)?v?(.*)/, 1] : nil
80
80
  version ||= requirement["version"].split("#").last
81
81
  child_dependencies = if depth >= PACKAGE_LOCK_JSON_MAX_DEPTH
82
82
  []
83
83
  else
84
- parse_package_lock_deps_recursively(requirement.fetch('dependencies', []), depth + 1)
85
- end
84
+ parse_package_lock_deps_recursively(requirement.fetch("dependencies", []), depth + 1)
85
+ end
86
86
 
87
87
  [{
88
88
  name: name,
89
89
  requirement: version,
90
- type: type
90
+ type: type,
91
91
  }] + child_dependencies
92
92
  end
93
93
  end
94
94
 
95
- def self.parse_manifest(file_contents, options: {})
95
+ def self.parse_manifest(file_contents, options: {}) # rubocop:disable Lint/UnusedMethodArgument
96
96
  manifest = JSON.parse(file_contents)
97
- raise "appears to be a lockfile rather than manifest format" if manifest.key?('lockfileVersion')
97
+ raise "appears to be a lockfile rather than manifest format" if manifest.key?("lockfileVersion")
98
98
 
99
99
  (
100
- map_dependencies(manifest, 'dependencies', 'runtime') +
101
- map_dependencies(manifest, 'devDependencies', 'development')
100
+ map_dependencies(manifest, "dependencies", "runtime") +
101
+ map_dependencies(manifest, "devDependencies", "development")
102
102
  )
103
103
  .reject { |dep| dep[:name].start_with?("//") } # Omit comment keys. They are valid in package.json: https://groups.google.com/g/nodejs/c/NmL7jdeuw0M/m/yTqI05DRQrIJ
104
104
  end
105
105
 
106
- def self.parse_yarn_lock(file_contents, options: {})
106
+ def self.parse_yarn_lock(file_contents, options: {}) # rubocop:disable Lint/UnusedMethodArgument
107
107
  response = Typhoeus.post("#{Bibliothecary.configuration.yarn_parser_host}/parse", body: file_contents)
108
108
 
109
109
  raise Bibliothecary::RemoteParsingError.new("Http Error #{response.response_code} when contacting: #{Bibliothecary.configuration.yarn_parser_host}/parse", response.response_code) unless response.success?
@@ -114,15 +114,15 @@ module Bibliothecary
114
114
  name: dep[:name],
115
115
  requirement: dep[:version],
116
116
  lockfile_requirement: dep[:requirement],
117
- type: dep[:type]
117
+ type: dep[:type],
118
118
  }
119
119
  end
120
120
  end
121
121
 
122
- def self.parse_ls(file_contents, options: {})
122
+ def self.parse_ls(file_contents, options: {}) # rubocop:disable Lint/UnusedMethodArgument
123
123
  manifest = JSON.parse(file_contents)
124
124
 
125
- transform_tree_to_array(manifest.fetch('dependencies', {}))
125
+ transform_tree_to_array(manifest.fetch("dependencies", {}))
126
126
  end
127
127
 
128
128
  def self.lockfile_preference_order(file_infos)
@@ -143,9 +143,9 @@ module Bibliothecary
143
143
  {
144
144
  name: name,
145
145
  requirement: metadata["version"],
146
- lockfile_requirement: metadata.fetch("from", "").split('@').last,
147
- type: "runtime"
148
- }
146
+ lockfile_requirement: metadata.fetch("from", "").split("@").last,
147
+ type: "runtime",
148
+ },
149
149
  ] + transform_tree_to_array(metadata.fetch("dependencies", {}))
150
150
  end.flatten(1)
151
151
  end
@@ -1,5 +1,5 @@
1
- require 'ox'
2
- require 'json'
1
+ require "ox"
2
+ require "json"
3
3
 
4
4
  module Bibliothecary
5
5
  module Parsers
@@ -10,37 +10,37 @@ module Bibliothecary
10
10
  def self.mapping
11
11
  {
12
12
  match_filename("Project.json") => {
13
- kind: 'manifest',
14
- parser: :parse_json_runtime_manifest
13
+ kind: "manifest",
14
+ parser: :parse_json_runtime_manifest,
15
15
  },
16
16
  match_filename("Project.lock.json") => {
17
- kind: 'lockfile',
18
- parser: :parse_project_lock_json
17
+ kind: "lockfile",
18
+ parser: :parse_project_lock_json,
19
19
  },
20
20
  match_filename("packages.lock.json") => {
21
- kind: 'lockfile',
22
- parser: :parse_packages_lock_json
21
+ kind: "lockfile",
22
+ parser: :parse_packages_lock_json,
23
23
  },
24
24
  match_filename("packages.config") => {
25
- kind: 'manifest',
26
- parser: :parse_packages_config
25
+ kind: "manifest",
26
+ parser: :parse_packages_config,
27
27
  },
28
28
  match_extension(".nuspec") => {
29
- kind: 'manifest',
30
- parser: :parse_nuspec
29
+ kind: "manifest",
30
+ parser: :parse_nuspec,
31
31
  },
32
32
  match_extension(".csproj") => {
33
- kind: 'manifest',
34
- parser: :parse_csproj
33
+ kind: "manifest",
34
+ parser: :parse_csproj,
35
35
  },
36
36
  match_filename("paket.lock") => {
37
- kind: 'lockfile',
38
- parser: :parse_paket_lock
37
+ kind: "lockfile",
38
+ parser: :parse_paket_lock,
39
39
  },
40
40
  match_filename("project.assets.json") => {
41
- kind: 'lockfile',
42
- parser: :parse_project_assets_json
43
- }
41
+ kind: "lockfile",
42
+ parser: :parse_project_assets_json,
43
+ },
44
44
  }
45
45
  end
46
46
 
@@ -48,23 +48,23 @@ module Bibliothecary
48
48
  add_multi_parser(Bibliothecary::MultiParsers::DependenciesCSV)
49
49
  add_multi_parser(Bibliothecary::MultiParsers::Spdx)
50
50
 
51
- def self.parse_project_lock_json(file_contents, options: {})
51
+ def self.parse_project_lock_json(file_contents, options: {}) # rubocop:disable Lint/UnusedMethodArgument
52
52
  manifest = JSON.parse file_contents
53
- manifest.fetch('libraries',[]).map do |name, _requirement|
54
- dep = name.split('/')
53
+ manifest.fetch("libraries",[]).map do |name, _requirement|
54
+ dep = name.split("/")
55
55
  {
56
56
  name: dep[0],
57
57
  requirement: dep[1],
58
- type: 'runtime'
58
+ type: "runtime",
59
59
  }
60
60
  end
61
61
  end
62
62
 
63
- def self.parse_packages_lock_json(file_contents, options: {})
63
+ def self.parse_packages_lock_json(file_contents, options: {}) # rubocop:disable Lint/UnusedMethodArgument
64
64
  manifest = JSON.parse file_contents
65
65
 
66
66
  frameworks = {}
67
- manifest.fetch('dependencies',[]).each do |framework, deps|
67
+ manifest.fetch("dependencies",[]).each do |framework, deps|
68
68
  frameworks[framework] = deps
69
69
  .reject { |_name, details| details["type"] == "Project" } # Projects do not have versions
70
70
  .map do |name, details|
@@ -72,8 +72,8 @@ module Bibliothecary
72
72
  name: name,
73
73
  # 'resolved' has been set in all examples so far
74
74
  # so fallback to requested is pure paranoia
75
- requirement: details.fetch('resolved', details.fetch('requested', '*')),
76
- type: 'runtime'
75
+ requirement: details.fetch("resolved", details.fetch("requested", "*")),
76
+ type: "runtime",
77
77
  }
78
78
  end
79
79
  end
@@ -89,23 +89,23 @@ module Bibliothecary
89
89
  []
90
90
  end
91
91
 
92
- def self.parse_packages_config(file_contents, options: {})
92
+ def self.parse_packages_config(file_contents, options: {}) # rubocop:disable Lint/UnusedMethodArgument
93
93
  manifest = Ox.parse file_contents
94
- manifest.packages.locate('package').map do |dependency|
94
+ manifest.packages.locate("package").map do |dependency|
95
95
  {
96
96
  name: dependency.id,
97
97
  requirement: (dependency.version if dependency.respond_to? "version") || "*",
98
- type: dependency.respond_to?("developmentDependency") && dependency.developmentDependency == "true" ? 'development' : 'runtime'
98
+ type: dependency.respond_to?("developmentDependency") && dependency.developmentDependency == "true" ? "development" : "runtime",
99
99
  }
100
100
  end
101
101
  rescue
102
102
  []
103
103
  end
104
104
 
105
- def self.parse_csproj(file_contents, options: {})
105
+ def self.parse_csproj(file_contents, options: {}) # rubocop:disable Lint/UnusedMethodArgument
106
106
  manifest = Ox.parse file_contents
107
107
 
108
- packages = manifest.locate('ItemGroup/PackageReference').select{ |dep| dep.respond_to? "Include" }.map do |dependency|
108
+ packages = manifest.locate("ItemGroup/PackageReference").select{ |dep| dep.respond_to? "Include" }.map do |dependency|
109
109
  requirement = (dependency.Version if dependency.respond_to? "Version") || "*"
110
110
  if requirement.is_a?(Ox::Element)
111
111
  requirement = dependency.nodes.detect{ |n| n.value == "Version" }&.text
@@ -120,7 +120,7 @@ module Bibliothecary
120
120
  {
121
121
  name: dependency.Include,
122
122
  requirement: requirement,
123
- type: type
123
+ type: type,
124
124
  }
125
125
  end
126
126
  packages.uniq {|package| package[:name] }
@@ -128,48 +128,48 @@ module Bibliothecary
128
128
  []
129
129
  end
130
130
 
131
- def self.parse_nuspec(file_contents, options: {})
131
+ def self.parse_nuspec(file_contents, options: {}) # rubocop:disable Lint/UnusedMethodArgument
132
132
  manifest = Ox.parse file_contents
133
- manifest.package.metadata.dependencies.locate('dependency').map do |dependency|
133
+ manifest.package.metadata.dependencies.locate("dependency").map do |dependency|
134
134
  {
135
135
  name: dependency.id,
136
- requirement: dependency.attributes[:version] || '*',
137
- type: dependency.respond_to?("developmentDependency") && dependency.developmentDependency == "true" ? 'development' : 'runtime'
136
+ requirement: dependency.attributes[:version] || "*",
137
+ type: dependency.respond_to?("developmentDependency") && dependency.developmentDependency == "true" ? "development" : "runtime",
138
138
  }
139
139
  end
140
140
  rescue
141
141
  []
142
142
  end
143
143
 
144
- def self.parse_paket_lock(file_contents, options: {})
144
+ def self.parse_paket_lock(file_contents, options: {}) # rubocop:disable Lint/UnusedMethodArgument
145
145
  lines = file_contents.split("\n")
146
146
  package_version_re = /\s+(?<name>\S+)\s\((?<version>\d+\.\d+[\.\d+[\.\d+]*]*)\)/
147
147
  packages = lines.select { |line| package_version_re.match(line) }.map { |line| package_version_re.match(line) }.map do |match|
148
148
  {
149
149
  name: match[:name].strip,
150
150
  requirement: match[:version],
151
- type: 'runtime'
151
+ type: "runtime",
152
152
  }
153
153
  end
154
154
  # we only have to enforce uniqueness by name because paket ensures that there is only the single version globally in the project
155
155
  packages.uniq {|package| package[:name] }
156
156
  end
157
157
 
158
- def self.parse_project_assets_json(file_contents, options: {})
158
+ def self.parse_project_assets_json(file_contents, options: {}) # rubocop:disable Lint/UnusedMethodArgument
159
159
  manifest = JSON.parse file_contents
160
160
 
161
161
  frameworks = {}
162
162
  manifest.fetch("targets",[]).each do |framework, deps|
163
163
  frameworks[framework] = deps
164
- .select { |_name, details| details["type"] == "package" }
165
- .map do |name, _details|
164
+ .select { |_name, details| details["type"] == "package" }
165
+ .map do |name, _details|
166
166
  name_split = name.split("/")
167
167
  {
168
168
  name: name_split[0],
169
169
  requirement: name_split[1],
170
- type: "runtime"
170
+ type: "runtime",
171
171
  }
172
- end
172
+ end
173
173
  end
174
174
 
175
175
  if frameworks.size > 0
@@ -1,4 +1,4 @@
1
- require 'json'
1
+ require "json"
2
2
 
3
3
  module Bibliothecary
4
4
  module Parsers
@@ -8,13 +8,13 @@ module Bibliothecary
8
8
  def self.mapping
9
9
  {
10
10
  match_filename("composer.json") => {
11
- kind: 'manifest',
12
- parser: :parse_manifest
11
+ kind: "manifest",
12
+ parser: :parse_manifest,
13
13
  },
14
14
  match_filename("composer.lock") => {
15
- kind: 'lockfile',
16
- parser: :parse_lockfile
17
- }
15
+ kind: "lockfile",
16
+ parser: :parse_lockfile,
17
+ },
18
18
  }
19
19
  end
20
20
 
@@ -22,22 +22,22 @@ module Bibliothecary
22
22
  add_multi_parser(Bibliothecary::MultiParsers::DependenciesCSV)
23
23
  add_multi_parser(Bibliothecary::MultiParsers::Spdx)
24
24
 
25
- def self.parse_lockfile(file_contents, options: {})
25
+ def self.parse_lockfile(file_contents, options: {}) # rubocop:disable Lint/UnusedMethodArgument
26
26
  manifest = JSON.parse file_contents
27
- manifest.fetch('packages',[]).map do |dependency|
27
+ manifest.fetch("packages",[]).map do |dependency|
28
28
  {
29
29
  name: dependency["name"],
30
30
  requirement: dependency["version"],
31
- type: "runtime"
31
+ type: "runtime",
32
32
  }.tap do |result|
33
33
  # Store Drupal version if Drupal, but include the original manifest version for reference
34
34
  result[:original_requirement], result[:requirement] = result[:requirement], dependency.dig("source", "reference") if is_drupal_module(dependency)
35
35
  end
36
- end + manifest.fetch('packages-dev',[]).map do |dependency|
36
+ end + manifest.fetch("packages-dev",[]).map do |dependency|
37
37
  {
38
38
  name: dependency["name"],
39
39
  requirement: dependency["version"],
40
- type: "development"
40
+ type: "development",
41
41
  }.tap do |result|
42
42
  # Store Drupal version if Drupal, but include the original manifest version for reference
43
43
  result[:original_requirement], result[:requirement] = result[:requirement], dependency.dig("source", "reference") if is_drupal_module(dependency)
@@ -45,10 +45,10 @@ module Bibliothecary
45
45
  end
46
46
  end
47
47
 
48
- def self.parse_manifest(file_contents, options: {})
48
+ def self.parse_manifest(file_contents, options: {}) # rubocop:disable Lint/UnusedMethodArgument
49
49
  manifest = JSON.parse file_contents
50
- map_dependencies(manifest, 'require', 'runtime') +
51
- map_dependencies(manifest, 'require-dev', 'development')
50
+ map_dependencies(manifest, "require", "runtime") +
51
+ map_dependencies(manifest, "require-dev", "development")
52
52
  end
53
53
 
54
54
  # Drupal hosts its own Composer repository, where its "modules" are indexed and searchable. The best way to
@@ -1,4 +1,4 @@
1
- require 'yaml'
1
+ require "yaml"
2
2
 
3
3
  module Bibliothecary
4
4
  module Parsers
@@ -8,31 +8,31 @@ module Bibliothecary
8
8
  def self.mapping
9
9
  {
10
10
  match_filename("pubspec.yaml", case_insensitive: true) => {
11
- kind: 'manifest',
12
- parser: :parse_yaml_manifest
11
+ kind: "manifest",
12
+ parser: :parse_yaml_manifest,
13
13
  },
14
14
  match_filename("pubspec.lock", case_insensitive: true) => {
15
- kind: 'lockfile',
16
- parser: :parse_yaml_lockfile
17
- }
15
+ kind: "lockfile",
16
+ parser: :parse_yaml_lockfile,
17
+ },
18
18
  }
19
19
  end
20
20
 
21
21
  add_multi_parser(Bibliothecary::MultiParsers::DependenciesCSV)
22
22
 
23
- def self.parse_yaml_manifest(file_contents, options: {})
23
+ def self.parse_yaml_manifest(file_contents, options: {}) # rubocop:disable Lint/UnusedMethodArgument
24
24
  manifest = YAML.load file_contents
25
- map_dependencies(manifest, 'dependencies', 'runtime') +
26
- map_dependencies(manifest, 'dev_dependencies', 'development')
25
+ map_dependencies(manifest, "dependencies", "runtime") +
26
+ map_dependencies(manifest, "dev_dependencies", "development")
27
27
  end
28
28
 
29
- def self.parse_yaml_lockfile(file_contents, options: {})
29
+ def self.parse_yaml_lockfile(file_contents, options: {}) # rubocop:disable Lint/UnusedMethodArgument
30
30
  manifest = YAML.load file_contents
31
- manifest.fetch('packages', []).map do |name, dep|
31
+ manifest.fetch("packages", []).map do |name, dep|
32
32
  {
33
33
  name: name,
34
- requirement: dep['version'],
35
- type: 'runtime'
34
+ requirement: dep["version"],
35
+ type: "runtime",
36
36
  }
37
37
  end
38
38
  end