bibliothecary 6.10.6 → 6.12.2

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: 1b8ae8af99a91ccccfdaaf8a18aa03ff134856f4ff0bd3579ef0955ff28bb6b6
4
- data.tar.gz: 7eeb154cbcc23edb621e3a1f332264bac5fe716d4e5026c20c072f14e60156b2
3
+ metadata.gz: 2069ae9ebc8043003befa27dca84ff27d7fa693a4acb954b3f25989ad0d8bd85
4
+ data.tar.gz: 624af9ee05fd3c218feae6e97b90413d8f2b18c26c4d22ae5242aee3df4b13aa
5
5
  SHA512:
6
- metadata.gz: 4fb19ca3ce60f786ee92a013ac6cddd2b29f8400ae7f3dce1258794360f90f3afd4b9bd594e9da34c4da2b2cae5ebc8936cc288ec0341710836ef0d13bffd210
7
- data.tar.gz: f9e7a66faa72e61b47dff0b73a6e80af515746a1de3e333eed4930560f2eff9519f785e303412c9774a812080a4926f317f5c8a895c9d568f768f6c78ff9f67f
6
+ metadata.gz: 95c98a02c2f0791386b442096c3d0d755064ca7260e13c334af1bc37f4c0654331238fc20a9a5195fe2f08f05d3d350df9dbf716d578bdb0e371252fc3f8a4d5
7
+ data.tar.gz: 50b89d1c78aed8ae87d141f2429e9d9a03b1ddf731524ccb1c90dcefaeb8e3c094a7090e42bfd32250a085a1a133276e1add9b70b13f4fcdcb0a213c397b5807
@@ -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/README.md CHANGED
@@ -88,6 +88,7 @@ All available config options are in: https://github.com/librariesio/bibliothecar
88
88
  - *.nuspec
89
89
  - paket.lock
90
90
  - *.csproj
91
+ - project.assets.json
91
92
  - Bower
92
93
  - bower.json
93
94
  - CPAN
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)
@@ -63,6 +63,8 @@ module Bibliothecary
63
63
 
64
64
  class << self
65
65
  attr_writer :configuration
66
+ alias analyze analyse
67
+ alias analyze_file analyse_file
66
68
  end
67
69
 
68
70
  def self.runner
@@ -101,6 +101,7 @@ module Bibliothecary
101
101
  def analyse(folder_path, file_list)
102
102
  analyse_file_info(file_list.map { |full_path| FileInfo.new(folder_path, full_path) })
103
103
  end
104
+ alias analyze analyse
104
105
 
105
106
  def analyse_file_info(file_info_list)
106
107
  matching_info = file_info_list
@@ -111,10 +112,12 @@ module Bibliothecary
111
112
  .merge(related_paths: related_paths(info, matching_info))
112
113
  end
113
114
  end
115
+ alias analyze_file_info analyse_file_info
114
116
 
115
117
  def analyse_contents(filename, contents)
116
118
  analyse_contents_from_info(FileInfo.new(nil, filename, contents))
117
119
  end
120
+ alias analyze_contents analyse_contents
118
121
 
119
122
  def analyse_contents_from_info(info)
120
123
  # If your Parser needs to return multiple responses for one file, please override this method
@@ -126,6 +129,7 @@ module Bibliothecary
126
129
  rescue Bibliothecary::FileParsingError => e
127
130
  Bibliothecary::Analyser::create_error_analysis(platform_name, info.relative_path, kind, e.message)
128
131
  end
132
+ alias analyze_contents_from_info analyse_contents_from_info
129
133
 
130
134
  # calling this with contents=nil can produce less-informed
131
135
  # results, but kept for back compat
@@ -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)
@@ -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
@@ -224,6 +238,7 @@ module Bibliothecary
224
238
  return nil if field.nil?
225
239
 
226
240
  value = field.nodes.first
241
+ value = value.value if value.is_a?(Ox::CData)
227
242
  match = value&.match(MAVEN_PROPERTY_REGEX)
228
243
  if match
229
244
  return extract_property(xml, match[1], value, parent_properties)
@@ -35,7 +35,11 @@ module Bibliothecary
35
35
  match_filename("paket.lock") => {
36
36
  kind: 'lockfile',
37
37
  parser: :parse_paket_lock
38
- }
38
+ },
39
+ match_filename("project.assets.json") => {
40
+ kind: 'lockfile',
41
+ parser: :parse_project_assets_json
42
+ },
39
43
  }
40
44
  end
41
45
 
@@ -137,6 +141,34 @@ module Bibliothecary
137
141
  # we only have to enforce uniqueness by name because paket ensures that there is only the single version globally in the project
138
142
  packages.uniq {|package| package[:name] }
139
143
  end
144
+
145
+ def self.parse_project_assets_json(file_contents)
146
+ manifest = JSON.parse file_contents
147
+
148
+ frameworks = {}
149
+ manifest.fetch("targets",[]).each do |framework, deps|
150
+ frameworks[framework] = deps
151
+ .select { |name, details| details["type"] == "package" }
152
+ .map do |name, details|
153
+ name_split = name.split("/")
154
+ {
155
+ name: name_split[0],
156
+ requirement: name_split[1],
157
+ type: "runtime"
158
+ }
159
+ end
160
+ end
161
+
162
+ if frameworks.size > 0
163
+ # we should really return multiple manifests, but bibliothecary doesn't
164
+ # do that yet so at least pick deterministically.
165
+
166
+ # Note, frameworks can be empty, so remove empty ones and then return the last sorted item if any
167
+ frameworks = frameworks.delete_if { |k, v| v.empty? }
168
+ return frameworks[frameworks.keys.sort.last] unless frameworks.empty?
169
+ end
170
+ []
171
+ end
140
172
  end
141
173
  end
142
174
  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|
@@ -26,20 +26,16 @@ module Bibliothecary
26
26
 
27
27
  analyses
28
28
  end
29
+ alias analyze analyse
29
30
 
30
31
  # deprecated; use load_file_info_list.
31
32
  def load_file_list(path)
32
33
  load_file_info_list(path).map { |info| info.full_path }
33
34
  end
34
35
 
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
36
+ def applicable_package_managers(info)
37
+ managers = package_managers.select { |pm| pm.match_info?(info) }
38
+ managers.length > 0 ? managers : [nil]
43
39
  end
44
40
 
45
41
  def package_managers
@@ -48,29 +44,41 @@ module Bibliothecary
48
44
 
49
45
  def load_file_info_list_from_paths(paths)
50
46
  file_list = []
47
+
51
48
  paths.each do |path|
52
49
  info = FileInfo.new(nil, path)
53
50
 
54
51
  next if ignored_files.include?(info.relative_path)
55
52
 
56
- init_package_manager(info)
57
- file_list.push(info)
53
+ applicable_package_managers(info).each do |package_manager|
54
+ file = info.dup
55
+ file.package_manager = package_manager
56
+
57
+ file_list.push(file)
58
+ end
58
59
  end
60
+
59
61
  file_list
60
62
  end
61
63
 
62
64
  def load_file_info_list(path)
63
65
  file_list = []
66
+
64
67
  Find.find(path) do |subpath|
65
68
  info = FileInfo.new(path, subpath)
69
+
66
70
  Find.prune if FileTest.directory?(subpath) && ignored_dirs.include?(info.relative_path)
67
71
  next unless FileTest.file?(subpath)
68
72
  next if ignored_files.include?(info.relative_path)
69
73
 
70
- init_package_manager(info)
74
+ applicable_package_managers(info).each do |package_manager|
75
+ file = info.dup
76
+ file.package_manager = package_manager
71
77
 
72
- file_list.push(info)
78
+ file_list.push(file)
79
+ end
73
80
  end
81
+
74
82
  file_list
75
83
  end
76
84
 
@@ -87,6 +95,7 @@ module Bibliothecary
87
95
  pm.analyse_contents(file_path, contents)
88
96
  end.flatten.uniq.compact
89
97
  end
98
+ alias analyze_file analyse_file
90
99
 
91
100
  # this skips manifests sometimes because it doesn't look at file
92
101
  # contents and can't establish from only regexes that the thing
@@ -1,3 +1,3 @@
1
1
  module Bibliothecary
2
- VERSION = "6.10.6"
2
+ VERSION = "6.12.2"
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.6
4
+ version: 6.12.2
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-04-06 00:00:00.000000000 Z
11
+ date: 2021-05-24 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"