bibliothecary 6.10.3 → 6.11.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: af1a007a1d21ef7ecfeffcbe97319185c31da96d252f27a58619e60afcc3faf8
4
- data.tar.gz: 64fb93438b9f3af750b2d69206ec7601e52b77bb5236a2783ad724a064125f33
3
+ metadata.gz: caaa965267d6272e22ec385e0ad56505f645cdc3437163ec2a9d40471c1e620b
4
+ data.tar.gz: a2ad1df3e6481e0faed3d27039557b5b248f73fe5fa9864cd7d9462e215af72a
5
5
  SHA512:
6
- metadata.gz: f4816e56d6cea72b20deaa2f2832a27ce1c2d99ffe5ac224e7259bb3595b699083ec32dbd2b2b756ec0ea8c82aa411908f4ab83eed366e41726f5d634e241630
7
- data.tar.gz: 1f5c52f3c4ad451a2c32e93bc129694580bb7f1c5af8769e859cfcc74ee928ea8a3ed0595c84c7a5ff13bad118ce4ff02bd519ee12bdd7c5f688dc2e98076e17
6
+ metadata.gz: 2a333bfa32d1c31abf164afd8a09b7060ffe2809b43199273e706e83dd01d9638e57f85787390deba7e923a9b26494e47074718df319bac159d9cfbb4bb32a26
7
+ data.tar.gz: 7a68137ae7f02721a2ae8ae94dad59783a07ba291c440cbc6469af0164b0f57a83b055dd16ac5ca58ba2a00de76e217a8fd778b30c98b1585760aa47f60c3ff1
@@ -0,0 +1,28 @@
1
+ version: 2.1
2
+ orbs:
3
+ ruby: circleci/ruby@0.1.2
4
+
5
+ jobs:
6
+ test:
7
+ docker:
8
+ - image: circleci/ruby:2.6.6-stretch-node
9
+ executor: ruby/default
10
+ steps:
11
+ - checkout
12
+ - run:
13
+ name: Which bundler?
14
+ command: bundle -v
15
+ - ruby/bundle-install
16
+ - run:
17
+ name: Run specs
18
+ command: bundle exec rake spec
19
+ - run:
20
+ name: CodeClimate
21
+ command: bundle exec codeclimate-test-reporter
22
+
23
+ workflows:
24
+ version: 2.1
25
+ test:
26
+ jobs:
27
+ - test
28
+
data/lib/bibliothecary.rb CHANGED
@@ -21,8 +21,8 @@ module Bibliothecary
21
21
  runner.load_file_list(path)
22
22
  end
23
23
 
24
- def self.init_package_manager(info)
25
- runner.init_package_manager(info)
24
+ def self.applicable_package_managers(info)
25
+ runner.applicable_package_managers(info)
26
26
  end
27
27
 
28
28
  def self.load_file_info_list(path)
@@ -26,14 +26,13 @@ module Bibliothecary
26
26
  }
27
27
  end
28
28
 
29
- def self.parse_conda(info)
30
- dependencies = call_conda_parser_web(info, "manifest")[:manifest]
29
+ def self.parse_conda(info, kind = "manifest")
30
+ dependencies = call_conda_parser_web(info, kind)[kind.to_sym]
31
31
  dependencies.map { |dep| dep.merge(type: "runtime") }
32
32
  end
33
33
 
34
34
  def self.parse_conda_lockfile(info)
35
- dependencies = call_conda_parser_web(info, "lockfile")[:lockfile]
36
- dependencies.map { |dep| dep.merge(type: "runtime") }
35
+ parse_conda(info, "lockfile")
37
36
  end
38
37
 
39
38
  private_class_method def self.call_conda_parser_web(file_contents, kind)
@@ -154,7 +154,7 @@ module Bibliothecary
154
154
  end
155
155
  def self.parse_maven_tree(file_contents)
156
156
  file_contents = file_contents.gsub(/\r\n?/, "\n")
157
- captures = file_contents.scan(/^\[INFO\][\s|+-\\]+([[\w.-]+:]+)(?=$|\s\(optional\)$)/).flatten.uniq
157
+ captures = file_contents.scan(/^\[INFO\](?:(?:\+-)|\||(?:\\-)|\s)+((?:[\w\.-]+:)+[\w\.\-${}]+)/).flatten.uniq
158
158
  captures.map do |item|
159
159
  parts = item.split(":")
160
160
  case parts.count
@@ -205,8 +205,8 @@ module Bibliothecary
205
205
  json = JSON.parse(response.body)
206
206
  return [] unless json['dependencies']
207
207
  json['dependencies'].map do |dependency|
208
- name = [dependency["group"], dependency["name"]].join(':')
209
- next unless name =~ (/[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+(\.[A-Za-z0-9_-])?\:[A-Za-z0-9_-]/)
208
+ name = gradle_dependency_name(dependency["group"], dependency["name"])
209
+ next unless name =~ /[\w-]+\.[\w_-]+(\.[\w-])?\:[\w-]/
210
210
  {
211
211
  name: name,
212
212
  requirement: dependency["version"],
@@ -215,6 +215,20 @@ module Bibliothecary
215
215
  end.compact
216
216
  end
217
217
 
218
+ def self.gradle_dependency_name(group, name)
219
+ if group.empty? && name.include?(":")
220
+ group, name = name.split(":", 2)
221
+ end
222
+
223
+ # Strip comments, and single/doublequotes
224
+ [group, name].map do |part|
225
+ part
226
+ .gsub(/\s*\/\/.*$/, "") # Comments
227
+ .gsub(/^["']/, "") # Beginning single/doublequotes
228
+ .gsub(/["']$/, "") # Ending single/doublequotes
229
+ end.join(":")
230
+ end
231
+
218
232
  def self.extract_pom_info(xml, location, parent_properties = {})
219
233
  extract_pom_dep_info(xml, xml, location, parent_properties)
220
234
  end
@@ -22,6 +22,10 @@ module Bibliothecary
22
22
  match_filename("package-lock.json") => {
23
23
  kind: 'lockfile',
24
24
  parser: :parse_package_lock
25
+ },
26
+ match_filename("npm-ls.json") => {
27
+ kind: 'lockfile',
28
+ parser: :parse_ls
25
29
  }
26
30
  }
27
31
  end
@@ -75,6 +79,25 @@ module Bibliothecary
75
79
  }
76
80
  end
77
81
  end
82
+
83
+ def self.parse_ls(file_contents)
84
+ manifest = JSON.parse(file_contents)
85
+
86
+ transform_tree_to_array(manifest.fetch('dependencies', {}))
87
+ end
88
+
89
+ private_class_method def self.transform_tree_to_array(deps_by_name)
90
+ deps_by_name.map do |name, metadata|
91
+ [
92
+ {
93
+ name: name,
94
+ requirement: metadata["version"],
95
+ lockfile_requirement: metadata.fetch("from", "").split('@').last,
96
+ type: "runtime"
97
+ }
98
+ ] + transform_tree_to_array(metadata.fetch("dependencies", {}))
99
+ end.flatten(1)
100
+ end
78
101
  end
79
102
  end
80
103
  end
@@ -39,7 +39,24 @@ module Bibliothecary
39
39
  match_filename("poetry.lock") => {
40
40
  kind: 'lockfile',
41
41
  parser: :parse_poetry_lock
42
- }
42
+ },
43
+ # Pip dependencies can be embedded in conda environment files
44
+ match_filename("environment.yml") => {
45
+ parser: :parse_conda,
46
+ kind: "manifest",
47
+ },
48
+ match_filename("environment.yaml") => {
49
+ parser: :parse_conda,
50
+ kind: "manifest",
51
+ },
52
+ match_filename("environment.yml.lock") => {
53
+ parser: :parse_conda,
54
+ kind: "lockfile",
55
+ },
56
+ match_filename("environment.yaml.lock") => {
57
+ parser: :parse_conda,
58
+ kind: "lockfile",
59
+ },
43
60
  }
44
61
  end
45
62
 
@@ -53,6 +70,17 @@ module Bibliothecary
53
70
  map_dependencies(manifest['dependencies'], 'runtime') + map_dependencies(manifest['dev-dependencies'], 'develop')
54
71
  end
55
72
 
73
+ def self.parse_conda(file_contents)
74
+ contents = YAML.safe_load(file_contents)
75
+ return [] unless contents
76
+
77
+ dependencies = contents["dependencies"]
78
+ pip = dependencies.find { |dep| dep.is_a?(Hash) && dep["pip"]}
79
+ return [] unless pip
80
+
81
+ Pypi.parse_requirements_txt(pip["pip"].join("\n"))
82
+ end
83
+
56
84
  def self.map_dependencies(packages, type)
57
85
  return [] unless packages
58
86
  packages.map do |name, info|
@@ -32,14 +32,9 @@ module Bibliothecary
32
32
  load_file_info_list(path).map { |info| info.full_path }
33
33
  end
34
34
 
35
- def init_package_manager(info)
36
- # set the package manager on each info
37
- matches = package_managers.select { |pm| pm.match_info?(info) }
38
-
39
- info.package_manager = matches[0] if matches.length == 1
40
-
41
- # this is a bug at the moment if it's raised (we don't handle it sensibly)
42
- raise "Multiple package managers fighting over #{info.relative_path}: #{matches.map(&:to_s)}" if matches.length > 1
35
+ def applicable_package_managers(info)
36
+ managers = package_managers.select { |pm| pm.match_info?(info) }
37
+ managers.length > 0 ? managers : [nil]
43
38
  end
44
39
 
45
40
  def package_managers
@@ -48,29 +43,41 @@ module Bibliothecary
48
43
 
49
44
  def load_file_info_list_from_paths(paths)
50
45
  file_list = []
46
+
51
47
  paths.each do |path|
52
48
  info = FileInfo.new(nil, path)
53
49
 
54
50
  next if ignored_files.include?(info.relative_path)
55
51
 
56
- init_package_manager(info)
57
- file_list.push(info)
52
+ applicable_package_managers(info).each do |package_manager|
53
+ file = info.dup
54
+ file.package_manager = package_manager
55
+
56
+ file_list.push(file)
57
+ end
58
58
  end
59
+
59
60
  file_list
60
61
  end
61
62
 
62
63
  def load_file_info_list(path)
63
64
  file_list = []
65
+
64
66
  Find.find(path) do |subpath|
65
67
  info = FileInfo.new(path, subpath)
68
+
66
69
  Find.prune if FileTest.directory?(subpath) && ignored_dirs.include?(info.relative_path)
67
70
  next unless FileTest.file?(subpath)
68
71
  next if ignored_files.include?(info.relative_path)
69
72
 
70
- init_package_manager(info)
73
+ applicable_package_managers(info).each do |package_manager|
74
+ file = info.dup
75
+ file.package_manager = package_manager
71
76
 
72
- file_list.push(info)
77
+ file_list.push(file)
78
+ end
73
79
  end
80
+
74
81
  file_list
75
82
  end
76
83
 
@@ -1,3 +1,3 @@
1
1
  module Bibliothecary
2
- VERSION = "6.10.3"
2
+ VERSION = "6.11.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: 6.10.3
4
+ version: 6.11.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: 2021-03-18 00:00:00.000000000 Z
11
+ date: 2021-05-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: toml-rb
@@ -216,6 +216,7 @@ executables:
216
216
  extensions: []
217
217
  extra_rdoc_files: []
218
218
  files:
219
+ - ".circleci/config.yml"
219
220
  - ".codeclimate.yml"
220
221
  - ".github/CONTRIBUTING.md"
221
222
  - ".gitignore"
@@ -288,7 +289,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
288
289
  - !ruby/object:Gem::Version
289
290
  version: '0'
290
291
  requirements: []
291
- rubygems_version: 3.0.3
292
+ rubygems_version: 3.1.2
292
293
  signing_key:
293
294
  specification_version: 4
294
295
  summary: Find and parse manifests