license_finder 6.15.0 → 7.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. checksums.yaml +4 -4
  2. data/.github/dependabot.yml +9 -0
  3. data/.rubocop.yml +12 -2
  4. data/CHANGELOG.md +18 -1
  5. data/Dockerfile +21 -2
  6. data/README.md +6 -6
  7. data/Rakefile +2 -2
  8. data/VERSION +1 -1
  9. data/ci/pipelines/release.yml.erb +1 -1
  10. data/ci/scripts/pushscript.sh +2 -3
  11. data/ci/scripts/run-tests.sh +4 -3
  12. data/ci/tasks/rubocop.yml +1 -1
  13. data/lib/license_finder/cli/approvals.rb +2 -2
  14. data/lib/license_finder/cli/base.rb +9 -5
  15. data/lib/license_finder/cli/dependencies.rb +4 -4
  16. data/lib/license_finder/cli/ignored_dependencies.rb +3 -3
  17. data/lib/license_finder/cli/ignored_groups.rb +3 -3
  18. data/lib/license_finder/cli/inherited_decisions.rb +5 -5
  19. data/lib/license_finder/cli/licenses.rb +2 -2
  20. data/lib/license_finder/cli/main.rb +17 -11
  21. data/lib/license_finder/cli/permitted_licenses.rb +3 -3
  22. data/lib/license_finder/cli/project_name.rb +4 -4
  23. data/lib/license_finder/cli/restricted_licenses.rb +3 -3
  24. data/lib/license_finder/configuration.rb +6 -3
  25. data/lib/license_finder/core.rb +2 -1
  26. data/lib/license_finder/decisions.rb +9 -5
  27. data/lib/license_finder/license/definitions.rb +22 -0
  28. data/lib/license_finder/license/text.rb +3 -3
  29. data/lib/license_finder/license.rb +8 -2
  30. data/lib/license_finder/logger.rb +1 -1
  31. data/lib/license_finder/package.rb +3 -11
  32. data/lib/license_finder/package_delta.rb +1 -1
  33. data/lib/license_finder/package_manager.rb +1 -0
  34. data/lib/license_finder/package_managers/cocoa_pods.rb +14 -9
  35. data/lib/license_finder/package_managers/conda.rb +1 -1
  36. data/lib/license_finder/package_managers/glide.rb +7 -1
  37. data/lib/license_finder/package_managers/go_15vendorexperiment.rb +2 -2
  38. data/lib/license_finder/package_managers/go_dep.rb +1 -1
  39. data/lib/license_finder/package_managers/go_workspace.rb +1 -1
  40. data/lib/license_finder/package_managers/nuget.rb +1 -1
  41. data/lib/license_finder/package_managers/pub.rb +86 -0
  42. data/lib/license_finder/package_managers/sbt.rb +1 -5
  43. data/lib/license_finder/package_managers/yarn.rb +2 -2
  44. data/lib/license_finder/package_utils/license_files.rb +2 -2
  45. data/lib/license_finder/packages/bower_package.rb +5 -2
  46. data/lib/license_finder/packages/erlangmk_package.rb +2 -4
  47. data/lib/license_finder/packages/npm_package.rb +1 -0
  48. data/lib/license_finder/packages/pubspec_package.rb +18 -0
  49. data/lib/license_finder/printer.rb +39 -0
  50. data/lib/license_finder/report.rb +2 -1
  51. data/lib/license_finder/reports/csv_report.rb +1 -1
  52. data/lib/license_finder/reports/erb_report.rb +7 -3
  53. data/lib/license_finder/reports/json_report.rb +2 -1
  54. data/lib/license_finder/reports/junit_report.rb +5 -1
  55. data/lib/license_finder/reports/xml_report.rb +5 -1
  56. data/lib/license_finder/scanner.rb +1 -1
  57. data/license_finder.gemspec +15 -13
  58. metadata +58 -26
@@ -31,6 +31,7 @@ module LicenseFinder
31
31
  # rebar_deps_dir: "deps",
32
32
  # }
33
33
  def initialize(configuration)
34
+ @printer = Printer.new
34
35
  @logger = Logger.new(configuration.logger_mode)
35
36
  @config = configuration
36
37
  @scanner = Scanner.new(options)
@@ -68,7 +69,7 @@ module LicenseFinder
68
69
 
69
70
  private
70
71
 
71
- attr_reader :logger
72
+ attr_reader :logger, :printer
72
73
 
73
74
  # The core of the system. The saved decisions are applied to the current
74
75
  # packages.
@@ -194,9 +194,10 @@ module LicenseFinder
194
194
 
195
195
  def inherit_from(filepath_info)
196
196
  decisions =
197
- if filepath_info.is_a?(Hash)
197
+ case filepath_info
198
+ when Hash
198
199
  resolve_inheritance(filepath_info)
199
- elsif filepath_info =~ %r{^https?://}
200
+ when %r{^https?://}
200
201
  open_uri(filepath_info).read
201
202
  else
202
203
  Pathname(filepath_info).read
@@ -247,9 +248,7 @@ module LicenseFinder
247
248
 
248
249
  # ruby < 2.5.0 URI.open is private
249
250
  if Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.5.0')
250
- # rubocop:disable Security/Open
251
251
  open(uri, header)
252
- # rubocop:enable Security/Open
253
252
  else
254
253
  URI.open(uri, header)
255
254
  end
@@ -280,7 +279,12 @@ module LicenseFinder
280
279
  def self.restore(persisted, result = new)
281
280
  return result unless persisted
282
281
 
283
- actions = YAML.load(persisted)
282
+ # From https://makandracards.com/makandra/465149-ruby-the-yaml-safe_load-method-hides-some-pitfalls
283
+ actions = if Gem::Version.new(Psych::VERSION) >= Gem::Version.new('3.1.0.pre1')
284
+ YAML.safe_load(persisted, permitted_classes: [Symbol, Time], aliases: true)
285
+ else
286
+ YAML.safe_load(persisted, [Symbol, Time], [], true)
287
+ end
284
288
 
285
289
  list_of_actions = (actions || []).map(&:first)
286
290
 
@@ -46,6 +46,7 @@ module LicenseFinder
46
46
  License.new(
47
47
  short_name: 'Apache1_1',
48
48
  pretty_name: 'Apache 1.1',
49
+ spdx_id: 'Apache-1.1',
49
50
  other_names: [
50
51
  'Apache-1.1',
51
52
  'The Apache Software License, Version 1.1'
@@ -58,6 +59,7 @@ module LicenseFinder
58
59
  License.new(
59
60
  short_name: 'Apache2',
60
61
  pretty_name: 'Apache 2.0',
62
+ spdx_id: 'Apache-2.0',
61
63
  other_names: [
62
64
  'Apache-2.0',
63
65
  'Apache Software License',
@@ -79,6 +81,7 @@ module LicenseFinder
79
81
  def bsd
80
82
  License.new(
81
83
  short_name: 'BSD',
84
+ spdx_id: 'BSD-4-Clause',
82
85
  other_names: ['BSD4', 'bsd-old', '4-clause BSD', 'BSD-4-Clause', 'BSD 4-Clause', 'BSD License'],
83
86
  url: 'http://en.wikipedia.org/wiki/BSD_licenses#4-clause_license_.28original_.22BSD_License.22.29'
84
87
  )
@@ -87,6 +90,7 @@ module LicenseFinder
87
90
  def cc01
88
91
  License.new(
89
92
  short_name: 'CC01',
93
+ spdx_id: 'CC0-1.0',
90
94
  pretty_name: 'CC0 1.0 Universal',
91
95
  other_names: ['CC0 1.0'],
92
96
  url: 'http://creativecommons.org/publicdomain/zero/1.0'
@@ -96,6 +100,7 @@ module LicenseFinder
96
100
  def cddl1
97
101
  License.new(
98
102
  short_name: 'CDDL1',
103
+ spdx_id: 'CDDL-1.0',
99
104
  pretty_name: 'Common Development and Distribution License 1.0',
100
105
  other_names: [
101
106
  'CDDL-1.0',
@@ -109,6 +114,7 @@ module LicenseFinder
109
114
  def eclipse1
110
115
  License.new(
111
116
  short_name: 'EPL1',
117
+ spdx_id: 'EPL-1.0',
112
118
  pretty_name: 'Eclipse Public License 1.0',
113
119
  other_names: [
114
120
  'EPL-1.0',
@@ -122,6 +128,7 @@ module LicenseFinder
122
128
  def gplv2
123
129
  License.new(
124
130
  short_name: 'GPLv2',
131
+ spdx_id: 'GPL-2.0-only',
125
132
  other_names: ['GPL V2', 'gpl-v2', 'GNU GENERAL PUBLIC LICENSE Version 2'],
126
133
  url: 'http://www.gnu.org/licenses/gpl-2.0.txt'
127
134
  )
@@ -130,6 +137,7 @@ module LicenseFinder
130
137
  def gplv3
131
138
  License.new(
132
139
  short_name: 'GPLv3',
140
+ spdx_id: 'GPL-3.0-only',
133
141
  other_names: ['GPL V3', 'gpl-v3', 'GNU GENERAL PUBLIC LICENSE Version 3'],
134
142
  url: 'http://www.gnu.org/licenses/gpl-3.0.txt'
135
143
  )
@@ -138,6 +146,7 @@ module LicenseFinder
138
146
  def isc
139
147
  License.new(
140
148
  short_name: 'ISC',
149
+ spdx_id: 'ISC',
141
150
  url: 'http://en.wikipedia.org/wiki/ISC_license'
142
151
  )
143
152
  end
@@ -145,6 +154,7 @@ module LicenseFinder
145
154
  def lgpl
146
155
  License.new(
147
156
  short_name: 'LGPL',
157
+ spdx_id: 'LGPL-3.0-only',
148
158
  other_names: ['LGPL-3', 'LGPLv3', 'LGPL-3.0'],
149
159
  url: 'http://www.gnu.org/licenses/lgpl.txt'
150
160
  )
@@ -153,6 +163,7 @@ module LicenseFinder
153
163
  def lgpl2_1
154
164
  License.new(
155
165
  short_name: 'LGPL2_1',
166
+ spdx_id: 'LGPL-2.1-only',
156
167
  pretty_name: 'GNU Lesser General Public License version 2.1',
157
168
  other_names: [
158
169
  'LGPL-2.1-only',
@@ -178,6 +189,7 @@ module LicenseFinder
178
189
 
179
190
  License.new(
180
191
  short_name: 'MIT',
192
+ spdx_id: 'MIT',
181
193
  other_names: ['Expat', 'MIT license', 'MIT License', 'The MIT License (MIT)'],
182
194
  url: 'http://opensource.org/licenses/mit-license',
183
195
  matcher: matcher
@@ -197,6 +209,7 @@ module LicenseFinder
197
209
 
198
210
  License.new(
199
211
  short_name: 'MPL1_1',
212
+ spdx_id: 'MPL-1.1',
200
213
  pretty_name: 'Mozilla Public License 1.1',
201
214
  other_names: [
202
215
  'MPL-1.1',
@@ -218,6 +231,7 @@ module LicenseFinder
218
231
 
219
232
  License.new(
220
233
  short_name: 'MPL2',
234
+ spdx_id: 'MPL-2.0',
221
235
  pretty_name: 'Mozilla Public License 2.0',
222
236
  other_names: [
223
237
  'MPL-2.0',
@@ -243,6 +257,7 @@ module LicenseFinder
243
257
 
244
258
  License.new(
245
259
  short_name: 'NewBSD',
260
+ spdx_id: 'BSD-3-Clause',
246
261
  pretty_name: 'New BSD',
247
262
  other_names: [
248
263
  'Modified BSD',
@@ -266,6 +281,7 @@ module LicenseFinder
266
281
  def ofl
267
282
  License.new(
268
283
  short_name: 'OFL',
284
+ spdx_id: 'OFL-1.1',
269
285
  pretty_name: 'SIL OPEN FONT LICENSE Version 1.1',
270
286
  other_names: [
271
287
  'OPEN FONT LICENSE Version 1.1'
@@ -277,6 +293,7 @@ module LicenseFinder
277
293
  def python
278
294
  License.new(
279
295
  short_name: 'Python',
296
+ spdx_id: 'PSF-2.0',
280
297
  pretty_name: 'Python Software Foundation License',
281
298
  other_names: [
282
299
  'PSF',
@@ -297,6 +314,7 @@ module LicenseFinder
297
314
 
298
315
  License.new(
299
316
  short_name: 'Ruby',
317
+ spdx_id: 'Ruby',
300
318
  pretty_name: 'ruby',
301
319
  url: url,
302
320
  matcher: matcher
@@ -306,6 +324,7 @@ module LicenseFinder
306
324
  def simplifiedbsd
307
325
  License.new(
308
326
  short_name: 'SimplifiedBSD',
327
+ spdx_id: 'BSD-2-Clause',
309
328
  pretty_name: 'Simplified BSD',
310
329
  other_names: [
311
330
  'FreeBSD',
@@ -321,6 +340,7 @@ module LicenseFinder
321
340
  def wtfpl
322
341
  License.new(
323
342
  short_name: 'WTFPL',
343
+ spdx_id: 'WTFPL',
324
344
  pretty_name: 'WTFPL',
325
345
  other_names: [
326
346
  'WTFPL V2',
@@ -337,6 +357,7 @@ module LicenseFinder
337
357
 
338
358
  License.new(
339
359
  short_name: '0BSD',
360
+ spdx_id: '0BSD',
340
361
  pretty_name: 'BSD Zero Clause License',
341
362
  other_names: [
342
363
  '0-Clause BSD',
@@ -354,6 +375,7 @@ module LicenseFinder
354
375
  def zlib
355
376
  License.new(
356
377
  short_name: 'Zlib',
378
+ spdx_id: 'Zlib',
357
379
  pretty_name: 'zlib/libpng license',
358
380
  other_names: [
359
381
  'zlib License'
@@ -11,11 +11,11 @@ module LicenseFinder
11
11
  SPECIAL_DOUBLE_QUOTES = /[“”„«»]/.freeze
12
12
  ALPHABET_ORDERED_LIST = /\\\([a-z]\\\)\\\s/.freeze
13
13
  ALPHABET_ORDERED_LIST_OPTIONAL = '(\([a-z]\)\s)?'
14
- LIST_BULLETS = /(\d{1,2}\\\.|\\\*|\\\-)\\\s/.freeze
14
+ LIST_BULLETS = /(\d{1,2}\\\.|\\\*|\\-)\\\s/.freeze
15
15
  LIST_BULLETS_OPTIONAL = '(\d{1,2}.|\*|\-)?\s*'
16
16
  NEWLINE_CHARACTER = /\n+/.freeze
17
- QUOTE_COMMENT_CHARACTER = /^\s*\>+/.freeze
18
- ESCAPED_QUOTES = /\\\"/.freeze
17
+ QUOTE_COMMENT_CHARACTER = /^\s*>+/.freeze
18
+ ESCAPED_QUOTES = /\\"/.freeze
19
19
 
20
20
  def self.normalize_punctuation(text)
21
21
  text.dup.force_encoding('UTF-8')
@@ -40,6 +40,7 @@ module LicenseFinder
40
40
  def initialize(settings)
41
41
  @short_name = settings.fetch(:short_name)
42
42
  @pretty_name = settings.fetch(:pretty_name, short_name)
43
+ @spdx_id = settings.fetch(:spdx_id, '')
43
44
  @other_names = settings.fetch(:other_names, [])
44
45
  @url = settings.fetch(:url)
45
46
  @matcher = settings.fetch(:matcher) { Matcher.from_template(Template.named(short_name)) }
@@ -51,6 +52,10 @@ module LicenseFinder
51
52
  pretty_name
52
53
  end
53
54
 
55
+ def standard_id
56
+ spdx_id
57
+ end
58
+
54
59
  def stripped_name(name)
55
60
  name.sub(/^The /i, '')
56
61
  end
@@ -77,13 +82,13 @@ module LicenseFinder
77
82
 
78
83
  private
79
84
 
80
- attr_reader :short_name, :pretty_name, :other_names
81
- attr_reader :matcher
85
+ attr_reader :short_name, :pretty_name, :other_names, :spdx_id, :matcher
82
86
 
83
87
  def names
84
88
  ([short_name, pretty_name] + other_names).uniq
85
89
  end
86
90
  end
91
+
87
92
  class AndLicense < License
88
93
  def self.operator
89
94
  ' AND '
@@ -93,6 +98,7 @@ module LicenseFinder
93
98
  @short_name = name
94
99
  @pretty_name = name
95
100
  @url = nil
101
+ @spdx_id = nil
96
102
  @matcher = NoneMatcher.new
97
103
  # removes heading and trailing parentesis and splits
98
104
  name = name[1..-2] if name.start_with?('(')
@@ -11,7 +11,7 @@ module LicenseFinder
11
11
  attr_reader :mode
12
12
 
13
13
  def initialize(mode = nil)
14
- @system_logger = ::Logger.new(STDOUT)
14
+ @system_logger = ::Logger.new($stdout)
15
15
  @system_logger.formatter = proc do |_, _, _, msg|
16
16
  "#{msg}\n"
17
17
  end
@@ -18,7 +18,7 @@ module LicenseFinder
18
18
  # the constructor options
19
19
  # - otherwise, override #licenses_from_spec or #license_files
20
20
  class Package
21
- attr_reader :logger
21
+ attr_reader :logger, :name, :version, :authors, :summary, :description, :children, :parents, :groups, :manual_approval, :license_names_from_spec, :install_path
22
22
 
23
23
  def self.license_names_from_standard_spec(spec)
24
24
  licenses = spec['licenses'] || [spec['license']].compact
@@ -64,10 +64,6 @@ module LicenseFinder
64
64
 
65
65
  attr_accessor :homepage, :package_url
66
66
 
67
- attr_reader :name, :version, :authors,
68
- :summary, :description,
69
- :children, :parents, :groups
70
-
71
67
  ## APPROVAL
72
68
 
73
69
  def approved_manually!(approval)
@@ -101,8 +97,6 @@ module LicenseFinder
101
97
  @restricted
102
98
  end
103
99
 
104
- attr_reader :manual_approval
105
-
106
100
  ## EQUALITY
107
101
 
108
102
  def <=>(other)
@@ -120,10 +114,7 @@ module LicenseFinder
120
114
  [name, version].hash
121
115
  end
122
116
 
123
- ## LICENSING
124
-
125
- attr_reader :license_names_from_spec # stubbed in tests, otherwise private
126
- attr_reader :install_path # checked in tests, otherwise private
117
+ ## LICENSING # stubbed in tests, otherwise private # checked in tests, otherwise private
127
118
 
128
119
  def licenses
129
120
  @licenses ||= activations.map(&:license).sort_by(&:name).to_set
@@ -200,3 +191,4 @@ require 'license_finder/packages/sbt_package'
200
191
  require 'license_finder/packages/cargo_package'
201
192
  require 'license_finder/packages/composer_package'
202
193
  require 'license_finder/packages/conda_package'
194
+ require 'license_finder/packages/pubspec_package'
@@ -29,7 +29,7 @@ module LicenseFinder
29
29
  end
30
30
 
31
31
  def merged_package?
32
- pick_package.class == MergedPackage
32
+ pick_package.instance_of?(MergedPackage)
33
33
  end
34
34
 
35
35
  def method_missing(_method_name)
@@ -177,5 +177,6 @@ require 'license_finder/package_managers/sbt'
177
177
  require 'license_finder/package_managers/cargo'
178
178
  require 'license_finder/package_managers/composer'
179
179
  require 'license_finder/package_managers/conda'
180
+ require 'license_finder/package_managers/pub'
180
181
 
181
182
  require 'license_finder/package'
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'json'
4
+ require 'open3'
4
5
 
5
6
  module LicenseFinder
6
7
  class CocoaPods < PackageManager
@@ -42,20 +43,24 @@ module LicenseFinder
42
43
  end
43
44
 
44
45
  def acknowledgements_path
45
- search_paths = ['Pods/Pods-acknowledgements.plist',
46
- 'Pods/Target Support Files/Pods/Pods-acknowledgements.plist',
47
- 'Pods/Target Support Files/Pods-*/Pods-*-acknowledgements.plist']
48
-
49
- result = Dir[*search_paths.map { |path| File.join(project_path, path) }].first
50
- raise "Found a Podfile but no Pods directory in #{project_path}. Try running pod install before running license_finder." if result.nil?
46
+ if !ENV['ACKNOWLEDGEMENTS_PATH'].nil?
47
+ result = Dir[*ENV['ACKNOWLEDGEMENTS_PATH']].first
48
+ else
49
+ search_paths = ['Pods/Pods-acknowledgements.plist',
50
+ 'Pods/Target Support Files/Pods/Pods-acknowledgements.plist',
51
+ 'Pods/Target Support Files/Pods-*/Pods-*-acknowledgements.plist']
51
52
 
53
+ result = Dir[*search_paths.map { |path| File.join(project_path, path) }].first
54
+ raise "Found a Podfile but no Pods directory in #{project_path}. Try running pod install before running license_finder." if result.nil?
55
+ end
52
56
  result
53
57
  end
54
58
 
55
59
  def read_plist(pathname)
56
- transformed_pathname = pathname.gsub!(%r{[^0-9A-Za-z. \-'/]}, '')
57
- transformed_pathname = pathname if transformed_pathname.nil?
58
- JSON.parse(`plutil -convert json -o - '#{transformed_pathname}'`)
60
+ out, err, status = Open3.capture3('plutil', '-convert', 'json', '-o', '-', pathname)
61
+ raise "#{out}\n\n#{err}" unless status.success?
62
+
63
+ JSON.parse(out)
59
64
  end
60
65
  end
61
66
  end
@@ -90,7 +90,7 @@ module LicenseFinder
90
90
  if status.success?
91
91
  conda_list = []
92
92
  stdout.each_line do |line|
93
- next if line =~ /^\s*#/
93
+ next if /^\s*#/.match?(line)
94
94
 
95
95
  name, version, build, channel = line.split
96
96
  conda_list << {
@@ -9,7 +9,13 @@ module LicenseFinder
9
9
  def current_packages
10
10
  detected_path = detected_package_path
11
11
 
12
- YAML.load_file(detected_path).fetch('imports').map do |package_hash|
12
+ imports = if Gem::Version.new(Psych::VERSION) >= Gem::Version.new('3.1.0.pre1')
13
+ YAML.safe_load(File.read(detected_path), permitted_classes: [Symbol, Time], aliases: true).fetch('imports')
14
+ else
15
+ YAML.safe_load(File.read(detected_path), [Symbol, Time], [], true).fetch('imports')
16
+ end
17
+
18
+ imports.map do |package_hash|
13
19
  import_path = package_hash.fetch('name')
14
20
  license_path = project_path.join('vendor', import_path)
15
21
 
@@ -37,7 +37,7 @@ module LicenseFinder
37
37
  GoPackage.from_dependency({
38
38
  'ImportPath' => dep,
39
39
  'InstallPath' => detected_package_path.join(dep),
40
- 'Rev' => 'vendored-' + project_sha(detected_package_path.join(dep)),
40
+ 'Rev' => "vendored-#{project_sha(detected_package_path.join(dep))}",
41
41
  'Homepage' => repo_name(dep)
42
42
  }, nil, true)
43
43
  end
@@ -70,7 +70,7 @@ module LicenseFinder
70
70
  deps = val.split("\n")
71
71
  Cmd.run('go list std').first.split("\n").each do |std|
72
72
  deps.delete_if do |dep|
73
- dep =~ %r{(\/|^)#{std}(\/|$)}
73
+ dep =~ %r{(/|^)#{std}(/|$)}
74
74
  end
75
75
  end
76
76
  deps.map do |d|
@@ -38,7 +38,7 @@ module LicenseFinder
38
38
  project_path.join(GODEP_VENDOR_PATH)
39
39
  else
40
40
  download_dependencies
41
- Pathname(ENV['GOPATH'] ? ENV['GOPATH'] + '/src' : ENV['HOME'] + '/go/src')
41
+ Pathname(ENV['GOPATH'] ? "#{ENV['GOPATH']}/src" : "#{ENV['HOME']}/go/src")
42
42
  end
43
43
  end
44
44
 
@@ -94,7 +94,7 @@ module LicenseFinder
94
94
  deps = val.split("\n")
95
95
  Cmd.run('go list std').first.split("\n").each do |std|
96
96
  deps.delete_if do |dep|
97
- dep =~ %r{(\/|^)#{std}(\/|$)}
97
+ dep =~ %r{(/|^)#{std}(/|$)}
98
98
  end
99
99
  end
100
100
  deps
@@ -64,7 +64,7 @@ module LicenseFinder
64
64
 
65
65
  file = files.first
66
66
  Zip::File.open file do |zipfile|
67
- content = zipfile.read(dep.name + '.nuspec')
67
+ content = zipfile.read("#{dep.name}.nuspec")
68
68
  Nuget.nuspec_license_urls(content)
69
69
  end
70
70
  end
@@ -0,0 +1,86 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+ require 'yaml'
5
+
6
+ module LicenseFinder
7
+ class Pub < PackageManager
8
+ class PubError < RuntimeError; end
9
+
10
+ def current_packages
11
+ unless File.exist?('pubspec.lock')
12
+ raise PubError, "No checked-out Pub packages found.
13
+ Please install your dependencies first."
14
+ end
15
+
16
+ if ENV['PUB_CACHE'].nil? || ENV['PUB_CACHE'].eql?('')
17
+ raise PubError, 'While PUB_CACHE environment variable is empty, retrieving package licenses is impossible. Please set the PUB_CACHE env variable (default: ~/.pub)'
18
+ end
19
+
20
+ stdout, _stderr, _status = Cmd.run('flutter pub deps --json')
21
+ yaml_deps = JSON.parse(stdout)
22
+ yaml_deps['packages'].map do |dependency|
23
+ package_name = dependency['name']
24
+ subpath = "#{dependency['name']}-#{dependency['version']}"
25
+ package_version = dependency['version']
26
+
27
+ project_repo = dependency['source'] == 'git' ? Pathname("#{ENV['PUB_CACHE']}/git/#{dependency['name']}-*/") : Pathname("#{ENV['PUB_CACHE']}/hosted/pub.dartlang.org/#{subpath}")
28
+
29
+ homepage = read_repository_home(project_repo)
30
+ homepage = "https://pub.dev/packages/#{package_name}" if homepage.nil? || homepage.empty?
31
+ PubPackage.new(
32
+ package_name,
33
+ package_version,
34
+ license_text(project_repo),
35
+ logger: logger,
36
+ install_path: project_repo,
37
+ homepage: homepage
38
+ )
39
+ end
40
+ end
41
+
42
+ def possible_package_paths
43
+ [project_path.join('pubspec.lock')]
44
+ end
45
+
46
+ def package_management_command
47
+ 'flutter'
48
+ end
49
+
50
+ def prepare_command
51
+ 'flutter pub get'
52
+ end
53
+
54
+ def prepare
55
+ prep_cmd = "#{prepare_command} #{production_flag}"
56
+ _stdout, stderr, status = Dir.chdir(project_path) { Cmd.run(prep_cmd) }
57
+
58
+ return if status.success?
59
+
60
+ log_errors stderr
61
+ raise "Prepare command '#{prep_cmd}' failed" unless @prepare_no_fail
62
+ end
63
+
64
+ private
65
+
66
+ def license_text(subpath)
67
+ license_path = license_pattern(subpath).find { |f| File.exist?(f) }
68
+ license_path.nil? ? nil : IO.read(license_path)
69
+ end
70
+
71
+ def license_pattern(subpath)
72
+ Dir.glob(subpath.join('LICENSE*'), File::FNM_CASEFOLD)
73
+ end
74
+
75
+ def production_flag
76
+ return '' if @ignored_groups.nil?
77
+
78
+ @ignored_groups.include?('devDependencies') ? '' : 'no-'
79
+ end
80
+
81
+ def read_repository_home(project_repo)
82
+ package_yaml = project_repo.join('pubspec.yaml')
83
+ YAML.load(IO.read(package_yaml))['repository'] if Dir.exist?(project_repo) && File.exist?(package_yaml)
84
+ end
85
+ end
86
+ end
@@ -17,11 +17,7 @@ module LicenseFinder
17
17
 
18
18
  dependencies = SbtDependencyFinder.new(project_path).dependencies
19
19
  packages = dependencies.flat_map do |text|
20
- options = {
21
- headers: true
22
- }
23
-
24
- contents = CSV.parse(text, options)
20
+ contents = CSV.parse(text, headers: true)
25
21
  contents.map do |row|
26
22
  group_id, name, version = row['Dependency'].split('#').map(&:strip)
27
23
  spec = {
@@ -13,8 +13,8 @@ module LicenseFinder
13
13
  suffix = " --cwd #{project_path}" unless project_path.nil?
14
14
  cmd += suffix unless suffix.nil?
15
15
 
16
- stdout, _stderr, status = Cmd.run(cmd)
17
- return [] unless status.success?
16
+ stdout, stderr, status = Cmd.run(cmd)
17
+ raise "Command '#{cmd}' failed to execute: #{stderr}" unless status.success?
18
18
 
19
19
  packages = []
20
20
  incompatible_packages = []
@@ -4,7 +4,7 @@ require 'license_finder/package_utils/possible_license_file'
4
4
 
5
5
  module LicenseFinder
6
6
  class LicenseFiles
7
- CANDIDATE_FILE_NAMES = %w[License Licence COPYING README].freeze
7
+ CANDIDATE_FILE_NAMES = %w[LICENSE License license LICENCE Licence licence COPYING copying README readme].freeze
8
8
  CANDIDATE_PATH_WILDCARD = "*{#{CANDIDATE_FILE_NAMES.join(',')}}*"
9
9
 
10
10
  def self.find(install_path, options = {})
@@ -35,7 +35,7 @@ module LicenseFinder
35
35
  def candidate_files_and_dirs
36
36
  return [] if install_path.nil?
37
37
 
38
- Pathname.glob(install_path.join('**', CANDIDATE_PATH_WILDCARD), File::FNM_CASEFOLD)
38
+ Pathname.glob(install_path.join('**', CANDIDATE_PATH_WILDCARD))
39
39
  end
40
40
  end
41
41
  end
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'open-uri'
4
-
5
4
  module LicenseFinder
6
5
  class BowerPackage < Package
7
6
  def initialize(bower_module, options = {})
@@ -35,7 +34,11 @@ module LicenseFinder
35
34
  end
36
35
 
37
36
  def package_url
38
- meta = JSON.parse(open("https://registry.bower.io/packages/#{CGI.escape(name)}").read)
37
+ meta = if Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.5.0')
38
+ JSON.parse(open("https://registry.bower.io/packages/#{CGI.escape(name)}").read)
39
+ else
40
+ JSON.parse(URI.open("https://registry.bower.io/packages/#{CGI.escape(name)}").read)
41
+ end
39
42
  meta['url']
40
43
  end
41
44
  end
@@ -37,9 +37,7 @@ module LicenseFinder
37
37
  end
38
38
 
39
39
  def dep_version
40
- @dep_version ||= begin
41
- dep_version_unformatted.sub(version_prefix_re, '')
42
- end
40
+ @dep_version ||= dep_version_unformatted.sub(version_prefix_re, '')
43
41
  end
44
42
 
45
43
  def dep_repo
@@ -88,7 +86,7 @@ module LicenseFinder
88
86
  def dep_version_valid?
89
87
  return false unless set?(dep_version_unformatted)
90
88
 
91
- if dep_version =~ version_re
89
+ if dep_version&.match?(version_re)
92
90
  Gem::Version.correct?(dep_version)
93
91
  else
94
92
  dep_version =~ word_dot_re
@@ -156,6 +156,7 @@ module LicenseFinder
156
156
 
157
157
  class PackageJson
158
158
  attr_reader :groups
159
+
159
160
  DEPENDENCY_GROUPS = %w[dependencies devDependencies].freeze
160
161
 
161
162
  def initialize(path)