bibliothecary 11.0.0 → 12.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ed25de135032f95b602569a3ad5c1476f36be42599c0cd1b29032ecf7de8a47b
4
- data.tar.gz: 6401e84f7ce40b499b4da8274f775813fe1dcfa41843e7cbcc761293ff287c0d
3
+ metadata.gz: 12b592879fc7f4fbe3622f495e8ef989b541c81487915b693d02907cedeb62a0
4
+ data.tar.gz: fd266f3924f202a864017c52ff1c2eb84fd68c4451b16b95e6aa44d80b850598
5
5
  SHA512:
6
- metadata.gz: 8f0cedd4ebe9e4248ac0151b4073fa2671466cb4c4e04b2b1dc7e9a8daecbfca34126fa870cab97d3e95e231dcc8f1e01295a7c3b9b907bf64db1443dfa2ff7e
7
- data.tar.gz: c44115bb427765889d363e59685dfe3bd7fff63b27bca352f453b74da2ddf269d75a526453eb0bdfcfdb219d073cea5172fbfdc4731f38a1d86d8748a7c030b9
6
+ metadata.gz: e4622e4be1424fd679fac201929bcdf77ed02f0f5782799cf506c93af1d21b803a7e8319e8f471b4747eb5d1a02dba3c0bf8914bae3c4a7a9c95c1b49c37c7b8
7
+ data.tar.gz: 16950d0fdfcf98cbef1b0faeb61fe1e398816b5499a2fe7af02ea3380975fce4bf85e81a64bfc2d9bb382753f2bdd538e2a46896e8a7e08476716a777adc32aa
data/.circleci/config.yml CHANGED
@@ -5,7 +5,7 @@ orbs:
5
5
  executors:
6
6
  bibliothecary:
7
7
  docker:
8
- - image: cimg/ruby:3.0.7
8
+ - image: cimg/ruby:3.2.4
9
9
  working_directory: ~/bibliothecary
10
10
 
11
11
 
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- 3.2.5
1
+ 3.2.4
data/CHANGELOG.md CHANGED
@@ -13,6 +13,24 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
13
13
 
14
14
  ### Removed
15
15
 
16
+ ## [12.0.0] - 2025-01-27
17
+
18
+ ### Removed
19
+
20
+ - This is a MAJOR release in that it removes support for hackage, carthage, hex, clojar, and swiftpm
21
+ from Bibliothecary. We are no longer doing any network calls when using Bibliothecary and reimplementing
22
+ parsing for those file types natively is non-trivial. Patches welcome :-)
23
+
24
+ ### Changed
25
+
26
+ - Rewrote conda and yarn parsers to be in process vs calling out over the network
27
+
28
+ ## [11.0.1] - 2024-12-20
29
+
30
+ ### Changed
31
+
32
+ - Alow retrieving maven versions from parent poms
33
+
16
34
  ## [11.0.0] - 2024-11-22
17
35
 
18
36
  ### Changed
@@ -31,7 +31,6 @@ Gem::Specification.new do |spec|
31
31
  spec.add_development_dependency "rake", "~> 12.0"
32
32
  spec.add_development_dependency "rspec", "~> 3.0"
33
33
  spec.add_development_dependency "webmock"
34
- spec.add_development_dependency "vcr"
35
34
  spec.add_development_dependency "rubocop"
36
35
  spec.add_development_dependency "rubocop-rails"
37
36
  end
@@ -5,7 +5,6 @@ module Bibliothecary
5
5
  attr_accessor :carthage_parser_host
6
6
  attr_accessor :clojars_parser_host
7
7
  attr_accessor :mix_parser_host
8
- attr_accessor :yarn_parser_host
9
8
  attr_accessor :conda_parser_host
10
9
  attr_accessor :swift_parser_host
11
10
  attr_accessor :cabal_parser_host
@@ -16,8 +15,6 @@ module Bibliothecary
16
15
  @carthage_parser_host = "https://carthage.libraries.io"
17
16
  @clojars_parser_host = "https://clojars.libraries.io"
18
17
  @mix_parser_host = "https://mix.libraries.io"
19
- @yarn_parser_host = "https://yarn-parser.libraries.io"
20
- @conda_parser_host = "https://conda-parser.libraries.io"
21
18
  @swift_parser_host = "http://swift.libraries.io"
22
19
  @cabal_parser_host = "http://cabal.libraries.io"
23
20
  end
@@ -1,4 +1,4 @@
1
- require "json"
1
+ require "yaml"
2
2
 
3
3
  module Bibliothecary
4
4
  module Parsers
@@ -15,14 +15,6 @@ module Bibliothecary
15
15
  parser: :parse_conda,
16
16
  kind: "manifest",
17
17
  },
18
- match_filename("environment.yml.lock") => {
19
- parser: :parse_conda_lockfile,
20
- kind: "lockfile",
21
- },
22
- match_filename("environment.yaml.lock") => {
23
- parser: :parse_conda_lockfile,
24
- kind: "lockfile",
25
- },
26
18
  }
27
19
  end
28
20
 
@@ -31,34 +23,63 @@ module Bibliothecary
31
23
  add_multi_parser(Bibliothecary::MultiParsers::Spdx)
32
24
 
33
25
  def self.parse_conda(file_contents, options: {}) # rubocop:disable Lint/UnusedMethodArgument
34
- parse_conda_with_kind(file_contents, "manifest")
35
- end
26
+ manifest = YAML.load(file_contents)
27
+ deps = manifest.dig("dependencies")
28
+ deps.map do |dep|
29
+ next unless dep.is_a? String # only deal with strings to skip parsing pip stuff
36
30
 
37
- def self.parse_conda_lockfile(file_contents, options: {}) # rubocop:disable Lint/UnusedMethodArgument
38
- parse_conda_with_kind(file_contents, "lockfile")
31
+ parsed = parse_name_requirement_from_matchspec(dep)
32
+ Dependency.new(**parsed.merge(type: "runtime"))
33
+ end.compact
39
34
  end
40
35
 
41
- def self.parse_conda_with_kind(info, kind)
42
- dependencies = call_conda_parser_web(info, kind)[kind.to_sym]
43
- dependencies.map { |dep_kv| Dependency.new(**dep_kv.merge(type: "runtime")) }
44
- end
36
+ def self.parse_name_requirement_from_matchspec(ms)
37
+ # simplified version of the implementation in conda to handle what we care about
38
+ # https://github.com/conda/conda/blob/main/conda/models/match_spec.py#L598
39
+ # (channel(/subdir):(namespace):)name(version(build))[key1=value1,key2=value2]
40
+ return if ms.end_with?("@")
45
41
 
46
- private_class_method def self.call_conda_parser_web(file_contents, kind)
47
- host = Bibliothecary.configuration.conda_parser_host
48
- response = Typhoeus.post(
49
- "#{host}/parse",
50
- headers: {
51
- ContentType: "multipart/form-data",
52
- },
53
- body: {
54
- file: file_contents,
55
- # Unfortunately we do not get the filename in the mapping parsers, so hardcoding the file name depending on the kind
56
- filename: kind == "manifest" ? "environment.yml" : "environment.yml.lock",
57
- }
58
- )
59
- raise Bibliothecary::RemoteParsingError.new("Http Error #{response.response_code} when contacting: #{host}/parse", response.response_code) unless response.success?
42
+ # strip off comments and optional features
43
+ ms = ms.split(/#/, 2).first
44
+ ms = ms.split(/ if /, 2).first
45
+
46
+ # strip off brackets
47
+ ms = ms.match(/^(.*)(?:\[(.*)\])?$/)[1]
60
48
 
61
- JSON.parse(response.body, symbolize_names: true)
49
+ # strip off any parens
50
+ ms = ms.match(/^(.*)(?:(\(.*\)))?$/)[1]
51
+
52
+ # deal with channel and namespace, I wish there was rsplit in ruby
53
+ split = ms.reverse.split(":", 2)
54
+ ms = split.last.reverse
55
+
56
+ # split the name from the version/build combo
57
+ matches = ms.match(/([^ =<>!~]+)?([><!=~ ].+)?/)
58
+ name = matches[1]
59
+ version_build = matches[2]
60
+
61
+ version = nil
62
+ if matches && matches[2]
63
+ version_build = matches[2]
64
+ # and now deal with getting the version from version/build
65
+ matches = version_build.match(/((?:.+?)[^><!,|]?)(?:(?<![=!|,<>~])(?:[ =])([^-=,|<>~]+?))?$/)
66
+ version = if matches
67
+ matches[1].strip
68
+ else
69
+ version_build.strip
70
+ end
71
+ end
72
+ # if it's an exact requirement, lose the =
73
+ if version&.start_with?("==")
74
+ version = version[2..]
75
+ elsif version&.start_with?("=")
76
+ version = version[1..]
77
+ end
78
+
79
+ return {
80
+ name: name,
81
+ requirement: version || "", # NOTE: this ignores build info
82
+ }
62
83
  end
63
84
  end
64
85
  end
@@ -105,7 +105,7 @@ module Bibliothecary
105
105
  end
106
106
 
107
107
  def self.parse_glide_lockfile(file_contents, options: {}) # rubocop:disable Lint/UnusedMethodArgument
108
- manifest = YAML.load file_contents
108
+ manifest = YAML.load(file_contents, permitted_classes: [Time])
109
109
  map_dependencies(manifest, "imports", "name", "version", "runtime")
110
110
  end
111
111
 
@@ -294,48 +294,74 @@ module Bibliothecary
294
294
  parse_pom_manifest(file_contents, {}, options: options)
295
295
  end
296
296
 
297
- # parent_properties is used by Libraries:
298
- # https://github.com/librariesio/libraries.io/blob/e970925aade2596a03268b6e1be785eba8502c62/app/models/package_manager/maven.rb#L129
299
297
  def self.parse_pom_manifest(file_contents, parent_properties = {}, options: {}) # rubocop:disable Lint/UnusedMethodArgument
300
- manifest = Ox.parse file_contents
301
- xml = manifest.respond_to?("project") ? manifest.project : manifest
302
- [].tap do |deps|
303
- # <dependencyManagement> is a namespace to specify artifact configuration (e.g. version), but it doesn't
304
- # actually add dependencies to your project. Grab these and keep them for reference while parsing <dependencies>
305
- # Ref: https://maven.apache.org/pom.html#Dependency_Management
306
- # Ref: https://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html#transitive-dependencies
307
- dependencyManagement = xml.locate("dependencyManagement/dependencies/dependency").map do |dep|
308
- {
309
- groupId: extract_pom_dep_info(xml, dep, "groupId", parent_properties),
310
- artifactId: extract_pom_dep_info(xml, dep, "artifactId", parent_properties),
311
- version: extract_pom_dep_info(xml, dep, "version", parent_properties),
312
- scope: extract_pom_dep_info(xml, dep, "scope", parent_properties),
313
- }
314
- end
315
- # <dependencies> is the namespace that will add dependencies to your project.
316
- xml.locate("dependencies/dependency").each do |dep|
317
- groupId = extract_pom_dep_info(xml, dep, "groupId", parent_properties)
318
- artifactId = extract_pom_dep_info(xml, dep, "artifactId", parent_properties)
319
- version = extract_pom_dep_info(xml, dep, "version", parent_properties)
320
- scope = extract_pom_dep_info(xml, dep, "scope", parent_properties)
321
-
322
- # Use any dep configurations from <dependencyManagement> as fallbacks
323
- if (depConfig = dependencyManagement.find { |d| d[:groupId] == groupId && d[:artifactId] == artifactId })
324
- version ||= depConfig[:version]
325
- scope ||= depConfig[:scope]
298
+ parse_pom_manifests([file_contents], parent_properties)
299
+ end
300
+
301
+ # @param files [Array<String>] Ordered array of strings containing the
302
+ # pom.xml bodies. The first element should be the child file.
303
+ # @param merged_properties [Hash]
304
+ def self.parse_pom_manifests(files, merged_properties)
305
+ documents = files.map do |file|
306
+ doc = Ox.parse(file)
307
+ doc.respond_to?("project") ? doc.project : doc
308
+ end
309
+
310
+ mergedDependencyManagements = {}
311
+ documents.each do |document|
312
+ document.locate("dependencyManagement/dependencies/dependency").each do |dep|
313
+ groupId = extract_pom_dep_info(document, dep, "groupId", merged_properties)
314
+ artifactId = extract_pom_dep_info(document, dep, "artifactId", merged_properties)
315
+ key = "#{groupId}:#{artifactId}"
316
+ mergedDependencyManagements[key] ||=
317
+ {
318
+ groupId: groupId,
319
+ artifactId: artifactId,
320
+ version: extract_pom_dep_info(document, dep, "version", merged_properties),
321
+ scope: extract_pom_dep_info(document, dep, "scope", merged_properties),
322
+ }
323
+ end
324
+ end
325
+
326
+ dep_hashes = {}
327
+ documents.each do |document|
328
+ document.locate("dependencies/dependency").each do |dep|
329
+ groupId = extract_pom_dep_info(document, dep, "groupId", merged_properties)
330
+ artifactId = extract_pom_dep_info(document, dep, "artifactId", merged_properties)
331
+ key = "#{groupId}:#{artifactId}"
332
+ unless dep_hashes.key?(key)
333
+ dep_hashes[key] = {
334
+ name: key,
335
+ requirement: nil,
336
+ type: nil,
337
+ optional: nil,
338
+ }
326
339
  end
340
+ dep_hash = dep_hashes[key]
341
+
342
+ dep_hash[:requirement] ||= extract_pom_dep_info(document, dep, "version", merged_properties)
343
+ dep_hash[:type] ||= extract_pom_dep_info(document, dep, "scope", merged_properties)
327
344
 
328
- dep_hash = {
329
- name: "#{groupId}:#{artifactId}",
330
- requirement: version,
331
- type: scope || "runtime",
332
- }
333
345
  # optional field is, itself, optional, and will be either "true" or "false"
334
- optional = extract_pom_dep_info(xml, dep, "optional", parent_properties)
335
- dep_hash[:optional] = optional == "true" unless optional.nil?
336
- deps.push(Dependency.new(**dep_hash))
346
+ optional = extract_pom_dep_info(document, dep, "optional", merged_properties)
347
+ if dep_hash[:optional].nil? && !optional.nil?
348
+ dep_hash[:optional] = optional == "true"
349
+ end
350
+ end
351
+ end
352
+
353
+ # Anything that wasn't covered by a dependency version, get from the
354
+ # dependencyManagements
355
+ dep_hashes.each do |key, dep_hash|
356
+ if (dependencyManagement = mergedDependencyManagements[key])
357
+ dep_hash[:requirement] ||= dependencyManagement[:version]
358
+ dep_hash[:type] ||= dependencyManagement[:scope]
337
359
  end
360
+
361
+ dep_hash[:type] ||= "runtime"
338
362
  end
363
+
364
+ dep_hashes.map{|key, dep_hash| Dependency.new(**dep_hash)}
339
365
  end
340
366
 
341
367
  def self.parse_gradle(file_contents, options: {}) # rubocop:disable Lint/UnusedMethodArgument
@@ -128,25 +128,74 @@ module Bibliothecary
128
128
  end
129
129
 
130
130
  def self.parse_yarn_lock(file_contents, options: {}) # rubocop:disable Lint/UnusedMethodArgument
131
- response = Typhoeus.post("#{Bibliothecary.configuration.yarn_parser_host}/parse", body: file_contents)
131
+ dep_hash = if file_contents.match(/__metadata:/)
132
+ parse_v2_yarn_lock(file_contents)
133
+ else
134
+ parse_v1_yarn_lock(file_contents)
135
+ end
132
136
 
133
- raise Bibliothecary::RemoteParsingError.new("Http Error #{response.response_code} when contacting: #{Bibliothecary.configuration.yarn_parser_host}/parse", response.response_code) unless response.success?
137
+ dep_hash.map do |dep|
138
+ Dependency.new(
139
+ name: dep[:name],
140
+ requirement: dep[:version],
141
+ type: "runtime", # lockfile doesn't tell us more about the type of dep
142
+ local: dep[:requirements]&.first&.start_with?("file:"),
143
+ )
144
+ end
145
+ end
134
146
 
135
- json = JSON.parse(response.body, symbolize_names: true)
136
- json
137
- .uniq
138
- .reject do |dep|
139
- dep[:requirement]&.include?("workspace") && dep[:version].include?("use.local")
140
- end
141
- .map do |dep|
142
- Dependency.new(
143
- name: dep[:name],
144
- requirement: dep[:version],
145
- type: dep[:type],
146
- local: dep[:requirement]&.start_with?("file:"),
147
- )
148
- end
149
- end
147
+ # Returns a hash representation of the deps in yarn.lock, eg:
148
+ # [{
149
+ # name: "foo",
150
+ # requirements: [["foo", "^1.0.0"], ["foo", "^1.0.1"]],
151
+ # version: "1.2.0",
152
+ # }, ...]
153
+ def self.parse_v1_yarn_lock(contents)
154
+ contents
155
+ .gsub(/^#.*/, "")
156
+ .strip
157
+ .split("\n\n")
158
+ .map do |chunk|
159
+ requirements = chunk
160
+ .lines
161
+ .find { |l| !l.start_with?(" ") && l.strip.end_with?(":") } # first line, eg: '"@bar/foo@1.0.0", "@bar/foo@^1.0.1":'
162
+ .strip
163
+ .gsub(/"|:$/, "") # don't need quotes or trailing colon
164
+ .split(",") # split the list of requirements
165
+ .map { |d| d.strip.split(/(?<!^)@/, 2) } # split each requirement on name/version "@"", not on leading namespace "@"
166
+ version = chunk.match(/version "?([^"]*)"?/)[1]
167
+
168
+ {
169
+ name: requirements.first.first,
170
+ requirements: requirements.map { |x| x[1] },
171
+ version: version,
172
+ }
173
+ end
174
+ end
175
+
176
+ def self.parse_v2_yarn_lock(contents)
177
+ parsed = YAML.load(contents)
178
+ parsed = parsed.except("__metadata")
179
+ parsed
180
+ .reject do |packages, info|
181
+ # yarn v4+ creates a lockfile entry: "myproject@workspace" with a "use.local" version
182
+ # this lockfile entry is a reference to the project to which the lockfile belongs
183
+ # skip this self-referential package
184
+ info["version"].to_s.include?("use.local") && packages.include?("workspace")
185
+ end
186
+ .map do |packages, info|
187
+ packages = packages.split(", ")
188
+ # use first requirement's name, assuming that deps will always resolve from deps of the same name
189
+ name = packages.first.rpartition("@").first
190
+ requirements = packages.map { |p| p.rpartition("@").last.gsub(/^.*:/, "") }
191
+
192
+ {
193
+ name: name,
194
+ requirements: requirements,
195
+ version: info["version"].to_s,
196
+ }
197
+ end
198
+ end
150
199
 
151
200
  def self.parse_ls(file_contents, options: {}) # rubocop:disable Lint/UnusedMethodArgument
152
201
  manifest = JSON.parse(file_contents)
@@ -79,14 +79,6 @@ module Bibliothecary
79
79
  parser: :parse_conda,
80
80
  kind: "manifest",
81
81
  },
82
- match_filename("environment.yml.lock") => {
83
- parser: :parse_conda,
84
- kind: "lockfile",
85
- },
86
- match_filename("environment.yaml.lock") => {
87
- parser: :parse_conda,
88
- kind: "lockfile",
89
- },
90
82
  }
91
83
  end
92
84
 
@@ -13,11 +13,8 @@ module Bibliothecary
13
13
  "conda" => :conda,
14
14
  "cran" => :cran,
15
15
  "gem" => :rubygems,
16
- "hackage" => :hackage,
17
- "hex" => :hex,
18
16
  "nuget" => :nuget,
19
17
  "pypi" => :pypi,
20
- "swift" => :swift_pm,
21
18
  }.freeze
22
19
 
23
20
 
@@ -1,3 +1,3 @@
1
1
  module Bibliothecary
2
- VERSION = "11.0.0"
2
+ VERSION = "12.0.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bibliothecary
3
3
  version: !ruby/object:Gem::Version
4
- version: 11.0.0
4
+ version: 12.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Nesbitt
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-11-25 00:00:00.000000000 Z
11
+ date: 2025-01-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: tomlrb
@@ -178,20 +178,6 @@ dependencies:
178
178
  - - ">="
179
179
  - !ruby/object:Gem::Version
180
180
  version: '0'
181
- - !ruby/object:Gem::Dependency
182
- name: vcr
183
- requirement: !ruby/object:Gem::Requirement
184
- requirements:
185
- - - ">="
186
- - !ruby/object:Gem::Version
187
- version: '0'
188
- type: :development
189
- prerelease: false
190
- version_requirements: !ruby/object:Gem::Requirement
191
- requirements:
192
- - - ">="
193
- - !ruby/object:Gem::Version
194
- version: '0'
195
181
  - !ruby/object:Gem::Dependency
196
182
  name: rubocop
197
183
  requirement: !ruby/object:Gem::Requirement
@@ -265,8 +251,6 @@ files:
265
251
  - lib/bibliothecary/multi_parsers/spdx.rb
266
252
  - lib/bibliothecary/parsers/bower.rb
267
253
  - lib/bibliothecary/parsers/cargo.rb
268
- - lib/bibliothecary/parsers/carthage.rb
269
- - lib/bibliothecary/parsers/clojars.rb
270
254
  - lib/bibliothecary/parsers/cocoapods.rb
271
255
  - lib/bibliothecary/parsers/conda.rb
272
256
  - lib/bibliothecary/parsers/cpan.rb
@@ -274,9 +258,7 @@ files:
274
258
  - lib/bibliothecary/parsers/dub.rb
275
259
  - lib/bibliothecary/parsers/elm.rb
276
260
  - lib/bibliothecary/parsers/go.rb
277
- - lib/bibliothecary/parsers/hackage.rb
278
261
  - lib/bibliothecary/parsers/haxelib.rb
279
- - lib/bibliothecary/parsers/hex.rb
280
262
  - lib/bibliothecary/parsers/julia.rb
281
263
  - lib/bibliothecary/parsers/maven.rb
282
264
  - lib/bibliothecary/parsers/meteor.rb
@@ -287,7 +269,6 @@ files:
287
269
  - lib/bibliothecary/parsers/pypi.rb
288
270
  - lib/bibliothecary/parsers/rubygems.rb
289
271
  - lib/bibliothecary/parsers/shard.rb
290
- - lib/bibliothecary/parsers/swift_pm.rb
291
272
  - lib/bibliothecary/purl_util.rb
292
273
  - lib/bibliothecary/related_files_info.rb
293
274
  - lib/bibliothecary/runner.rb
@@ -1,52 +0,0 @@
1
- module Bibliothecary
2
- module Parsers
3
- class Carthage
4
- include Bibliothecary::Analyser
5
-
6
- def self.mapping
7
- {
8
- match_filename("Cartfile") => {
9
- kind: "manifest",
10
- parser: :parse_cartfile,
11
- },
12
- match_filename("Cartfile.private") => {
13
- kind: "manifest",
14
- parser: :parse_cartfile_private,
15
- },
16
- match_filename("Cartfile.resolved") => {
17
- kind: "lockfile",
18
- parser: :parse_cartfile_resolved,
19
- },
20
- }
21
- end
22
-
23
- add_multi_parser(Bibliothecary::MultiParsers::DependenciesCSV)
24
-
25
- def self.parse_cartfile(file_contents, options: {}) # rubocop:disable Lint/UnusedMethodArgument
26
- map_dependencies(file_contents, "cartfile")
27
- end
28
-
29
- def self.parse_cartfile_private(file_contents, options: {}) # rubocop:disable Lint/UnusedMethodArgument
30
- map_dependencies(file_contents, "cartfile.private")
31
- end
32
-
33
- def self.parse_cartfile_resolved(file_contents, options: {}) # rubocop:disable Lint/UnusedMethodArgument
34
- map_dependencies(file_contents, "cartfile.resolved")
35
- end
36
-
37
- def self.map_dependencies(manifest, path)
38
- response = Typhoeus.post("#{Bibliothecary.configuration.carthage_parser_host}/#{path}", params: { body: manifest })
39
- raise Bibliothecary::RemoteParsingError.new("Http Error #{response.response_code} when contacting: #{Bibliothecary.configuration.carthage_parser_host}/#{path}", response.response_code) unless response.success?
40
- json = JSON.parse(response.body)
41
-
42
- json.map do |dependency|
43
- Dependency.new(
44
- name: dependency["name"],
45
- requirement: dependency["version"],
46
- type: dependency["type"],
47
- )
48
- end
49
- end
50
- end
51
- end
52
- end
@@ -1,38 +0,0 @@
1
- require "json"
2
- require "typhoeus"
3
-
4
- module Bibliothecary
5
- module Parsers
6
- class Clojars
7
- include Bibliothecary::Analyser
8
-
9
- def self.mapping
10
- {
11
- match_filename("project.clj") => {
12
- kind: "manifest",
13
- parser: :parse_manifest,
14
- },
15
- }
16
- end
17
-
18
- add_multi_parser(Bibliothecary::MultiParsers::DependenciesCSV)
19
-
20
- def self.parse_manifest(file_contents, options: {}) # rubocop:disable Lint/UnusedMethodArgument
21
- response = Typhoeus.post("#{Bibliothecary.configuration.clojars_parser_host}/project.clj", body: file_contents)
22
- raise Bibliothecary::RemoteParsingError.new("Http Error #{response.response_code} when contacting: #{Bibliothecary.configuration.clojars_parser_host}/project.clj", response.response_code) unless response.success?
23
- json = JSON.parse response.body
24
- index = json.index("dependencies")
25
-
26
- return [] unless index;
27
- dependencies = json[index + 1]
28
- dependencies.map do |dependency|
29
- Dependency.new(
30
- name: dependency[0],
31
- requirement: dependency[1],
32
- type: "runtime",
33
- )
34
- end
35
- end
36
- end
37
- end
38
- end
@@ -1,53 +0,0 @@
1
- require "json"
2
- require "deb_control"
3
-
4
- module Bibliothecary
5
- module Parsers
6
- class Hackage
7
- include Bibliothecary::Analyser
8
-
9
- def self.mapping
10
- {
11
- match_extension(".cabal") => {
12
- kind: "manifest",
13
- parser: :parse_cabal,
14
- },
15
- match_extension("cabal.config") => {
16
- kind: "lockfile",
17
- parser: :parse_cabal_config,
18
- },
19
- }
20
- end
21
-
22
- add_multi_parser(Bibliothecary::MultiParsers::CycloneDX)
23
- add_multi_parser(Bibliothecary::MultiParsers::DependenciesCSV)
24
- add_multi_parser(Bibliothecary::MultiParsers::Spdx)
25
-
26
- def self.parse_cabal(file_contents, options: {}) # rubocop:disable Lint/UnusedMethodArgument
27
- headers = {
28
- "Content-Type" => "text/plain;charset=utf-8",
29
- }
30
-
31
- response = Typhoeus.post("#{Bibliothecary.configuration.cabal_parser_host}/parse", headers: headers, body: file_contents)
32
-
33
- raise Bibliothecary::RemoteParsingError.new("Http Error #{response.response_code} when contacting: #{Bibliothecary.configuration.cabal_parser_host}/parse", response.response_code) unless response.success?
34
- JSON
35
- .parse(response.body, symbolize_names: true)
36
- .map { |dep_kvs| Dependency.new(**dep_kvs) }
37
- end
38
-
39
- def self.parse_cabal_config(file_contents, options: {}) # rubocop:disable Lint/UnusedMethodArgument
40
- manifest = DebControl::ControlFileBase.parse(file_contents)
41
- deps = manifest.first["constraints"].delete("\n").split(",").map(&:strip)
42
- deps.map do |dependency|
43
- dep = dependency.delete("==").split(" ")
44
- Dependency.new(
45
- name: dep[0],
46
- requirement: dep[1],
47
- type: "runtime",
48
- )
49
- end
50
- end
51
- end
52
- end
53
- end
@@ -1,54 +0,0 @@
1
- require "json"
2
-
3
- module Bibliothecary
4
- module Parsers
5
- class Hex
6
- include Bibliothecary::Analyser
7
-
8
- def self.mapping
9
- {
10
- match_filename("mix.exs") => {
11
- kind: "manifest",
12
- parser: :parse_mix,
13
- },
14
- match_filename("mix.lock") => {
15
- kind: "lockfile",
16
- parser: :parse_mix_lock,
17
- },
18
- }
19
- end
20
-
21
- add_multi_parser(Bibliothecary::MultiParsers::CycloneDX)
22
- add_multi_parser(Bibliothecary::MultiParsers::DependenciesCSV)
23
- add_multi_parser(Bibliothecary::MultiParsers::Spdx)
24
-
25
- def self.parse_mix(file_contents, options: {}) # rubocop:disable Lint/UnusedMethodArgument
26
- response = Typhoeus.post("#{Bibliothecary.configuration.mix_parser_host}/", body: file_contents)
27
- raise Bibliothecary::RemoteParsingError.new("Http Error #{response.response_code} when contacting: #{Bibliothecary.configuration.mix_parser_host}/", response.response_code) unless response.success?
28
- json = JSON.parse response.body
29
-
30
- json.map do |name, version|
31
- Dependency.new(
32
- name: name,
33
- requirement: version,
34
- type: "runtime",
35
- )
36
- end
37
- end
38
-
39
- def self.parse_mix_lock(file_contents, options: {}) # rubocop:disable Lint/UnusedMethodArgument
40
- response = Typhoeus.post("#{Bibliothecary.configuration.mix_parser_host}/lock", body: file_contents)
41
- raise Bibliothecary::RemoteParsingError.new("Http Error #{response.response_code} when contacting: #{Bibliothecary.configuration.mix_parser_host}/", response.response_code) unless response.success?
42
- json = JSON.parse response.body
43
-
44
- json.map do |name, info|
45
- Dependency.new(
46
- name: name,
47
- requirement: info["version"],
48
- type: "runtime",
49
- )
50
- end
51
- end
52
- end
53
- end
54
- end
@@ -1,35 +0,0 @@
1
- module Bibliothecary
2
- module Parsers
3
- class SwiftPM
4
- include Bibliothecary::Analyser
5
-
6
- def self.mapping
7
- {
8
- match_filename("Package.swift", case_insensitive: true) => {
9
- kind: "manifest",
10
- parser: :parse_package_swift,
11
- },
12
- }
13
- end
14
-
15
- add_multi_parser(Bibliothecary::MultiParsers::CycloneDX)
16
- add_multi_parser(Bibliothecary::MultiParsers::DependenciesCSV)
17
- add_multi_parser(Bibliothecary::MultiParsers::Spdx)
18
-
19
- def self.parse_package_swift(file_contents, options: {}) # rubocop:disable Lint/UnusedMethodArgument
20
- response = Typhoeus.post("#{Bibliothecary.configuration.swift_parser_host}/to-json", body: file_contents)
21
- raise Bibliothecary::RemoteParsingError.new("Http Error #{response.response_code} when contacting: #{Bibliothecary.configuration.swift_parser_host}/to-json", response.response_code) unless response.success?
22
- json = JSON.parse(response.body)
23
- json["dependencies"].map do |dependency|
24
- name = dependency["url"].gsub(/^https?:\/\//, "").gsub(/\.git$/,"")
25
- version = "#{dependency['version']['lowerBound']} - #{dependency['version']['upperBound']}"
26
- Dependency.new(
27
- name: name,
28
- requirement: version,
29
- type: "runtime",
30
- )
31
- end
32
- end
33
- end
34
- end
35
- end