license_finder 7.0.0 → 7.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/dependabot.yml +7 -0
- data/.pre-commit-hooks.yaml +10 -0
- data/CHANGELOG.md +41 -9
- data/CONTRIBUTING.md +1 -0
- data/Dockerfile +69 -52
- data/README.md +72 -29
- data/VERSION +1 -1
- data/dlf +6 -1
- data/lib/license_finder/cli/base.rb +2 -0
- data/lib/license_finder/cli/licenses.rb +8 -3
- data/lib/license_finder/cli/main.rb +3 -1
- data/lib/license_finder/configuration.rb +8 -0
- data/lib/license_finder/core.rb +2 -0
- data/lib/license_finder/decision_applier.rb +1 -1
- data/lib/license_finder/decisions.rb +24 -6
- data/lib/license_finder/license/definitions.rb +2 -0
- data/lib/license_finder/license/templates/Apache2.txt +0 -2
- data/lib/license_finder/manual_licenses.rb +79 -0
- data/lib/license_finder/package.rb +1 -0
- data/lib/license_finder/package_manager.rb +1 -0
- data/lib/license_finder/package_managers/dotnet.rb +5 -2
- data/lib/license_finder/package_managers/maven.rb +2 -6
- data/lib/license_finder/package_managers/nuget.rb +5 -0
- data/lib/license_finder/package_managers/pnpm.rb +120 -0
- data/lib/license_finder/package_managers/yarn.rb +91 -31
- data/lib/license_finder/package_utils/pypi.rb +3 -1
- data/lib/license_finder/packages/npm_package.rb +21 -0
- data/lib/license_finder/packages/pnpm_package.rb +13 -0
- data/lib/license_finder/reports/csv_report.rb +10 -1
- data/lib/license_finder/scanner.rb +1 -1
- data/license_finder.gemspec +4 -4
- metadata +19 -15
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
require 'open-uri'
|
4
4
|
require 'license_finder/license'
|
5
|
+
require 'license_finder/manual_licenses'
|
5
6
|
|
6
7
|
module LicenseFinder
|
7
8
|
class Decisions
|
@@ -11,8 +12,8 @@ module LicenseFinder
|
|
11
12
|
|
12
13
|
attr_reader :packages, :permitted, :restricted, :ignored, :ignored_groups, :project_name, :inherited_decisions
|
13
14
|
|
14
|
-
def licenses_of(name)
|
15
|
-
@
|
15
|
+
def licenses_of(name, version = nil)
|
16
|
+
@manual_licenses.licenses_of(name, version)
|
16
17
|
end
|
17
18
|
|
18
19
|
def homepage_of(name)
|
@@ -76,7 +77,7 @@ module LicenseFinder
|
|
76
77
|
def initialize
|
77
78
|
@decisions = []
|
78
79
|
@packages = Set.new
|
79
|
-
@
|
80
|
+
@manual_licenses = ManualLicenses.new
|
80
81
|
@homepages = {}
|
81
82
|
@approvals = {}
|
82
83
|
@permitted = Set.new
|
@@ -100,13 +101,29 @@ module LicenseFinder
|
|
100
101
|
|
101
102
|
def license(name, lic, txn = {})
|
102
103
|
add_decision [:license, name, lic, txn]
|
103
|
-
|
104
|
+
|
105
|
+
versions = txn[:versions]
|
106
|
+
|
107
|
+
if versions.nil? || versions.empty?
|
108
|
+
@manual_licenses.assign_to_all_versions(name, lic)
|
109
|
+
else
|
110
|
+
@manual_licenses.assign_to_specific_versions(name, lic, versions)
|
111
|
+
end
|
112
|
+
|
104
113
|
self
|
105
114
|
end
|
106
115
|
|
107
116
|
def unlicense(name, lic, txn = {})
|
108
117
|
add_decision [:unlicense, name, lic, txn]
|
109
|
-
|
118
|
+
|
119
|
+
versions = txn[:versions]
|
120
|
+
|
121
|
+
if versions.nil? || versions.empty?
|
122
|
+
@manual_licenses.unassign_from_all_versions(name, lic)
|
123
|
+
else
|
124
|
+
@manual_licenses.unassign_from_specific_versions(name, lic, versions)
|
125
|
+
end
|
126
|
+
|
110
127
|
self
|
111
128
|
end
|
112
129
|
|
@@ -235,9 +252,10 @@ module LicenseFinder
|
|
235
252
|
end
|
236
253
|
|
237
254
|
def restore_inheritance(decisions)
|
255
|
+
previous_value = @inherited
|
238
256
|
@inherited = true
|
239
257
|
self.class.restore(decisions, self)
|
240
|
-
@inherited =
|
258
|
+
@inherited = previous_value
|
241
259
|
self
|
242
260
|
end
|
243
261
|
|
@@ -0,0 +1,79 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module LicenseFinder
|
4
|
+
class ManualLicenses
|
5
|
+
def initialize
|
6
|
+
@all_versions = {}
|
7
|
+
@specific_versions = {}
|
8
|
+
end
|
9
|
+
|
10
|
+
def licenses_of(name, version = nil)
|
11
|
+
return @all_versions[name] if @all_versions[name]
|
12
|
+
|
13
|
+
if version && @specific_versions[name] && @specific_versions[name][version]
|
14
|
+
@specific_versions[name][version]
|
15
|
+
else
|
16
|
+
Set.new
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def assign_to_all_versions(name, lic)
|
21
|
+
# Ex: licenses add foo_gem MIT => Adds MIT at "all" versions for this gem
|
22
|
+
|
23
|
+
@all_versions[name] ||= Set.new
|
24
|
+
@all_versions[name] << to_license(lic)
|
25
|
+
|
26
|
+
@specific_versions.delete(name)
|
27
|
+
end
|
28
|
+
|
29
|
+
def assign_to_specific_versions(name, lic, versions)
|
30
|
+
# Ex: licenses add foo_gem MIT --version=1.0 => Adds MIT at only 1.0 for this gem
|
31
|
+
|
32
|
+
@specific_versions[name] ||= {}
|
33
|
+
versions.each do |version|
|
34
|
+
@specific_versions[name][version] ||= Set.new
|
35
|
+
@specific_versions[name][version] << to_license(lic)
|
36
|
+
end
|
37
|
+
|
38
|
+
@all_versions.delete(name)
|
39
|
+
end
|
40
|
+
|
41
|
+
def unassign_from_all_versions(name, lic = nil)
|
42
|
+
if lic
|
43
|
+
# Ex: licenses remove foo_gem MIT => Removes MIT at all versions for this gem
|
44
|
+
@all_versions[name]&.delete(to_license(lic))
|
45
|
+
|
46
|
+
@specific_versions[name]&.each do |_version, licenses|
|
47
|
+
licenses.delete(to_license(lic))
|
48
|
+
end
|
49
|
+
else
|
50
|
+
# Ex: licenses remove foo_gem => Removes all licenses for all versions of the gem
|
51
|
+
@all_versions.delete(name)
|
52
|
+
@specific_versions.delete(name)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def unassign_from_specific_versions(name, lic, versions)
|
57
|
+
return unless @specific_versions[name]
|
58
|
+
|
59
|
+
versions.each do |version|
|
60
|
+
if @specific_versions[name][version]
|
61
|
+
if lic
|
62
|
+
# Ex: licenses remove foo_gem MIT --version=1.0 => Removes MIT at only 1.0 for this gem
|
63
|
+
@specific_versions[name][version].delete(to_license(lic))
|
64
|
+
@specific_versions[name].delete(version) if @specific_versions[name][version].empty?
|
65
|
+
else
|
66
|
+
# Ex: licenses remove foo_gem --version=1.0 => Removes all licenses at only 1.0 for the gem
|
67
|
+
@specific_versions[name].delete(version)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
private
|
74
|
+
|
75
|
+
def to_license(lic)
|
76
|
+
License.find_by_name(lic)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -187,6 +187,7 @@ require 'license_finder/packages/merged_package'
|
|
187
187
|
require 'license_finder/packages/nuget_package'
|
188
188
|
require 'license_finder/packages/conan_package'
|
189
189
|
require 'license_finder/packages/yarn_package'
|
190
|
+
require 'license_finder/packages/pnpm_package'
|
190
191
|
require 'license_finder/packages/sbt_package'
|
191
192
|
require 'license_finder/packages/cargo_package'
|
192
193
|
require 'license_finder/packages/composer_package'
|
@@ -158,6 +158,7 @@ require 'license_finder/package_managers/go_modules'
|
|
158
158
|
require 'license_finder/package_managers/trash'
|
159
159
|
require 'license_finder/package_managers/bundler'
|
160
160
|
require 'license_finder/package_managers/npm'
|
161
|
+
require 'license_finder/package_managers/pnpm'
|
161
162
|
require 'license_finder/package_managers/yarn'
|
162
163
|
require 'license_finder/package_managers/pip'
|
163
164
|
require 'license_finder/package_managers/pipenv'
|
@@ -42,9 +42,13 @@ module LicenseFinder
|
|
42
42
|
end
|
43
43
|
|
44
44
|
def read_license_urls
|
45
|
-
possible_spec_paths.flat_map do |path|
|
45
|
+
raw_licenses = possible_spec_paths.flat_map do |path|
|
46
46
|
Nuget.nuspec_license_urls(File.read(path)) if File.exist? path
|
47
47
|
end.compact
|
48
|
+
|
49
|
+
raw_licenses&.map! do |license|
|
50
|
+
license.gsub('https://licenses.nuget.org/', '')
|
51
|
+
end
|
48
52
|
end
|
49
53
|
|
50
54
|
def ==(other)
|
@@ -61,7 +65,6 @@ module LicenseFinder
|
|
61
65
|
package_metadatas = asset_files
|
62
66
|
.flat_map { |path| AssetFile.new(path).dependencies }
|
63
67
|
.uniq { |d| [d.name, d.version] }
|
64
|
-
|
65
68
|
package_metadatas.map do |d|
|
66
69
|
path = Dir.glob("#{Dir.home}/.nuget/packages/#{d.name.downcase}/#{d.version}").first
|
67
70
|
NugetPackage.new(d.name, d.version, spec_licenses: d.read_license_urls, install_path: path)
|
@@ -34,14 +34,10 @@ module LicenseFinder
|
|
34
34
|
end
|
35
35
|
|
36
36
|
def package_management_command
|
37
|
-
wrapper =
|
38
|
-
'mvnw.cmd'
|
39
|
-
else
|
40
|
-
'./mvnw'
|
41
|
-
end
|
37
|
+
wrapper = File.join(project_path, Platform.windows? ? 'mvnw.cmd' : 'mvnw')
|
42
38
|
maven = 'mvn'
|
43
39
|
|
44
|
-
File.exist?(
|
40
|
+
File.exist?(wrapper) ? wrapper : maven
|
45
41
|
end
|
46
42
|
|
47
43
|
def possible_package_paths
|
@@ -51,6 +51,10 @@ module LicenseFinder
|
|
51
51
|
def current_packages
|
52
52
|
dependencies.each_with_object({}) do |dep, memo|
|
53
53
|
licenses = license_urls(dep)
|
54
|
+
licenses&.map! do |license|
|
55
|
+
license.gsub('https://licenses.nuget.org/', '')
|
56
|
+
end
|
57
|
+
|
54
58
|
path = Dir.glob("#{Dir.home}/.nuget/packages/#{dep.name.downcase}/#{dep.version}").first
|
55
59
|
|
56
60
|
memo[dep.name] ||= NugetPackage.new(dep.name, dep.version, spec_licenses: licenses, install_path: path)
|
@@ -60,6 +64,7 @@ module LicenseFinder
|
|
60
64
|
|
61
65
|
def license_urls(dep)
|
62
66
|
files = Dir["**/#{dep.name}.#{dep.version}.nupkg"]
|
67
|
+
|
63
68
|
return nil if files.empty?
|
64
69
|
|
65
70
|
file = files.first
|
@@ -0,0 +1,120 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'json'
|
4
|
+
require 'tempfile'
|
5
|
+
|
6
|
+
module LicenseFinder
|
7
|
+
class PNPM < PackageManager
|
8
|
+
def initialize(options = {})
|
9
|
+
super
|
10
|
+
@pnpm_options = options[:pnpm_options]
|
11
|
+
end
|
12
|
+
|
13
|
+
SHELL_COMMAND = 'pnpm licenses list --json --long'
|
14
|
+
|
15
|
+
def possible_package_paths
|
16
|
+
[project_path.join('pnpm-lock.yaml')]
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.takes_priority_over
|
20
|
+
NPM
|
21
|
+
end
|
22
|
+
|
23
|
+
def current_packages
|
24
|
+
# check if the minimum version of PNPM is met
|
25
|
+
raise 'The minimum PNPM version is not met, requires 7.17.0 or later' unless supported_pnpm?
|
26
|
+
|
27
|
+
# check if the project directory has workspace file
|
28
|
+
cmd = PNPM::SHELL_COMMAND.to_s
|
29
|
+
cmd += ' --no-color'
|
30
|
+
cmd += ' --recursive' unless project_has_workspaces == false
|
31
|
+
cmd += " --dir #{project_path}" unless project_path.nil?
|
32
|
+
cmd += " #{@pnpm_options}" unless @pnpm_options.nil?
|
33
|
+
|
34
|
+
stdout, stderr, status = Cmd.run(cmd)
|
35
|
+
raise "Command '#{cmd}' failed to execute: #{stderr}" unless status.success?
|
36
|
+
|
37
|
+
json_objects = JSON.parse(stdout)
|
38
|
+
get_pnpm_packages(json_objects)
|
39
|
+
end
|
40
|
+
|
41
|
+
def get_pnpm_packages(json_objects)
|
42
|
+
packages = []
|
43
|
+
incompatible_packages = []
|
44
|
+
|
45
|
+
json_objects.map do |_, value|
|
46
|
+
value.each do |pkg|
|
47
|
+
name = pkg['name']
|
48
|
+
version = pkg['version']
|
49
|
+
license = pkg['license']
|
50
|
+
homepage = pkg['vendorUrl']
|
51
|
+
author = pkg['vendorName']
|
52
|
+
module_path = pkg['path']
|
53
|
+
|
54
|
+
package = PNPMPackage.new(
|
55
|
+
name,
|
56
|
+
version,
|
57
|
+
spec_licenses: [license],
|
58
|
+
homepage: homepage,
|
59
|
+
authors: author,
|
60
|
+
install_path: module_path
|
61
|
+
)
|
62
|
+
packages << package
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
packages + incompatible_packages.uniq
|
67
|
+
end
|
68
|
+
|
69
|
+
def package_management_command
|
70
|
+
'pnpm'
|
71
|
+
end
|
72
|
+
|
73
|
+
def prepare_command
|
74
|
+
'pnpm install --no-lockfile --ignore-scripts'
|
75
|
+
end
|
76
|
+
|
77
|
+
def prepare
|
78
|
+
prep_cmd = "#{prepare_command}#{production_flag}"
|
79
|
+
_stdout, stderr, status = Dir.chdir(project_path) { Cmd.run(prep_cmd) }
|
80
|
+
|
81
|
+
return if status.success?
|
82
|
+
|
83
|
+
log_errors stderr
|
84
|
+
raise "Prepare command '#{prep_cmd}' failed" unless @prepare_no_fail
|
85
|
+
end
|
86
|
+
|
87
|
+
private
|
88
|
+
|
89
|
+
def project_has_workspaces
|
90
|
+
Dir.chdir(project_path) do
|
91
|
+
return File.file?('pnpm-workspace.yaml')
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
# PNPM introduced the licenses command in 7.17.0
|
96
|
+
def supported_pnpm?
|
97
|
+
Dir.chdir(project_path) do
|
98
|
+
version_string, stderr_str, status = Cmd.run('pnpm --version')
|
99
|
+
raise "Command 'pnpm -v' failed to execute: #{stderr_str}" unless status.success?
|
100
|
+
|
101
|
+
version = version_string.split('.').map(&:to_i)
|
102
|
+
major = version[0]
|
103
|
+
minor = version[1]
|
104
|
+
patch = version[1]
|
105
|
+
|
106
|
+
return true if major > 7
|
107
|
+
return true if major == 7 && minor > 17
|
108
|
+
return true if major == 7 && minor == 17 && patch >= 0
|
109
|
+
|
110
|
+
return false
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
def production_flag
|
115
|
+
return '' if @ignored_groups.nil?
|
116
|
+
|
117
|
+
@ignored_groups.include?('devDependencies') ? ' --prod' : ''
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
@@ -2,40 +2,37 @@
|
|
2
2
|
|
3
3
|
module LicenseFinder
|
4
4
|
class Yarn < PackageManager
|
5
|
-
|
5
|
+
def initialize(options = {})
|
6
|
+
super
|
7
|
+
@yarn_options = options[:yarn_options]
|
8
|
+
end
|
9
|
+
|
10
|
+
SHELL_COMMAND = 'yarn licenses list --recursive --json'
|
6
11
|
|
7
12
|
def possible_package_paths
|
8
13
|
[project_path.join('yarn.lock')]
|
9
14
|
end
|
10
15
|
|
11
16
|
def current_packages
|
12
|
-
|
13
|
-
|
14
|
-
|
17
|
+
# the licenses plugin supports the classic production flag
|
18
|
+
cmd = "#{Yarn::SHELL_COMMAND}#{classic_yarn_production_flag}"
|
19
|
+
if yarn_version == 1
|
20
|
+
cmd += ' --no-progress'
|
21
|
+
cmd += " --cwd #{project_path}" unless project_path.nil?
|
22
|
+
cmd += " #{@yarn_options}" unless @yarn_options.nil?
|
23
|
+
end
|
15
24
|
|
16
25
|
stdout, stderr, status = Cmd.run(cmd)
|
17
26
|
raise "Command '#{cmd}' failed to execute: #{stderr}" unless status.success?
|
18
27
|
|
19
|
-
packages = []
|
20
|
-
incompatible_packages = []
|
21
|
-
|
22
28
|
json_strings = stdout.encode('ASCII', invalid: :replace, undef: :replace, replace: '?').split("\n")
|
23
29
|
json_objects = json_strings.map { |json_object| JSON.parse(json_object) }
|
24
30
|
|
25
|
-
if
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
json_objects.each do |json_object|
|
31
|
-
match = /(?<name>[\w,\-]+)@(?<version>(\d+\.?)+)/ =~ json_object['data'].to_s
|
32
|
-
if match
|
33
|
-
package = YarnPackage.new(name, version, spec_licenses: ['unknown'])
|
34
|
-
incompatible_packages.push(package)
|
35
|
-
end
|
31
|
+
if yarn_version == 1
|
32
|
+
get_yarn1_packages(json_objects)
|
33
|
+
else
|
34
|
+
get_yarn_packages(json_objects)
|
36
35
|
end
|
37
|
-
|
38
|
-
packages + incompatible_packages.uniq
|
39
36
|
end
|
40
37
|
|
41
38
|
def prepare
|
@@ -56,33 +53,96 @@ module LicenseFinder
|
|
56
53
|
end
|
57
54
|
|
58
55
|
def prepare_command
|
59
|
-
if
|
60
|
-
|
56
|
+
if yarn_version == 1
|
57
|
+
classic_yarn_prepare_command
|
61
58
|
else
|
62
|
-
|
59
|
+
yarn_prepare_command
|
63
60
|
end
|
64
61
|
end
|
65
62
|
|
66
63
|
private
|
67
64
|
|
68
|
-
def
|
69
|
-
"#{
|
65
|
+
def yarn_prepare_command
|
66
|
+
"#{yarn_plugin_production_command}yarn install && yarn plugin import https://raw.githubusercontent.com/mhassan1/yarn-plugin-licenses/#{yarn_licenses_plugin_version}/bundles/@yarnpkg/plugin-licenses.js"
|
70
67
|
end
|
71
68
|
|
72
|
-
def
|
73
|
-
"yarn install --ignore-engines --ignore-scripts#{
|
69
|
+
def classic_yarn_prepare_command
|
70
|
+
"yarn install --ignore-engines --ignore-scripts#{classic_yarn_production_flag}"
|
74
71
|
end
|
75
72
|
|
76
|
-
def
|
73
|
+
def yarn_licenses_plugin_version
|
74
|
+
if yarn_version == 2
|
75
|
+
'v0.6.0'
|
76
|
+
else
|
77
|
+
'v0.7.2'
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def yarn_version
|
77
82
|
Dir.chdir(project_path) do
|
78
83
|
version_string, stderr_str, status = Cmd.run('yarn -v')
|
79
84
|
raise "Command 'yarn -v' failed to execute: #{stderr_str}" unless status.success?
|
80
85
|
|
81
86
|
version = version_string.split('.').map(&:to_i)
|
82
|
-
return version[0]
|
87
|
+
return version[0]
|
83
88
|
end
|
84
89
|
end
|
85
90
|
|
91
|
+
def get_yarn_packages(json_objects)
|
92
|
+
packages = []
|
93
|
+
incompatible_packages = []
|
94
|
+
json_objects.each do |json_object|
|
95
|
+
license = json_object['value']
|
96
|
+
body = json_object['children']
|
97
|
+
|
98
|
+
body.each do |package_name, vendor_info|
|
99
|
+
valid_match = %r{(?<name>[@,\w,\-,/,.]+)@(?<manager>\D*):\D*(?<version>(\d+\.?)+)} =~ package_name.to_s
|
100
|
+
valid_match = %r{(?<name>[@,\w,\-,/,.]+)@virtual:.+#(\D*):\D*(?<version>(\d+\.?)+)} =~ package_name.to_s if manager.eql?('virtual')
|
101
|
+
|
102
|
+
if valid_match
|
103
|
+
homepage = vendor_info['children']['vendorUrl']
|
104
|
+
author = vendor_info['children']['vendorName']
|
105
|
+
package = YarnPackage.new(
|
106
|
+
name,
|
107
|
+
version,
|
108
|
+
spec_licenses: [license],
|
109
|
+
homepage: homepage,
|
110
|
+
authors: author,
|
111
|
+
install_path: project_path.join(modules_folder, name)
|
112
|
+
)
|
113
|
+
packages << package
|
114
|
+
end
|
115
|
+
incompatible_match = /(?<name>[\w,\-]+)@[a-z]*:(?<version>(\.))/ =~ package_name.to_s
|
116
|
+
|
117
|
+
if incompatible_match
|
118
|
+
package = YarnPackage.new(name, version, spec_licenses: ['unknown'])
|
119
|
+
incompatible_packages.push(package)
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
packages + incompatible_packages.uniq
|
125
|
+
end
|
126
|
+
|
127
|
+
def get_yarn1_packages(json_objects)
|
128
|
+
packages = []
|
129
|
+
incompatible_packages = []
|
130
|
+
if json_objects.last['type'] == 'table'
|
131
|
+
license_json = json_objects.pop['data']
|
132
|
+
packages = packages_from_json(license_json)
|
133
|
+
end
|
134
|
+
|
135
|
+
json_objects.each do |json_object|
|
136
|
+
match = /(?<name>[\w,\-]+)@(?<version>(\d+\.?)+)/ =~ json_object['data'].to_s
|
137
|
+
if match
|
138
|
+
package = YarnPackage.new(name, version, spec_licenses: ['unknown'])
|
139
|
+
incompatible_packages.push(package)
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
packages + incompatible_packages.uniq
|
144
|
+
end
|
145
|
+
|
86
146
|
def packages_from_json(json_data)
|
87
147
|
body = json_data['body']
|
88
148
|
head = json_data['head']
|
@@ -120,13 +180,13 @@ module LicenseFinder
|
|
120
180
|
all_packages - [yarn_internal_package]
|
121
181
|
end
|
122
182
|
|
123
|
-
def
|
183
|
+
def classic_yarn_production_flag
|
124
184
|
return '' if @ignored_groups.nil?
|
125
185
|
|
126
186
|
@ignored_groups.include?('devDependencies') ? ' --production' : ''
|
127
187
|
end
|
128
188
|
|
129
|
-
def
|
189
|
+
def yarn_plugin_production_command
|
130
190
|
return '' if @ignored_groups.nil?
|
131
191
|
|
132
192
|
@ignored_groups.include?('devDependencies') ? 'yarn plugin import workspace-tools && yarn workspaces focus --all --production && ' : ''
|
@@ -25,7 +25,9 @@ module LicenseFinder
|
|
25
25
|
def definition(name, version)
|
26
26
|
response = request("https://pypi.org/pypi/#{name}/#{version}/json")
|
27
27
|
response.is_a?(Net::HTTPSuccess) ? JSON.parse(response.body).fetch('info', {}) : {}
|
28
|
-
rescue *CONNECTION_ERRORS
|
28
|
+
rescue *CONNECTION_ERRORS => e
|
29
|
+
raise e, "Unable to read package from pypi.org #{name} #{version}: #{e}" unless @prepare_no_fail
|
30
|
+
|
29
31
|
{}
|
30
32
|
end
|
31
33
|
|
@@ -72,11 +72,32 @@ module LicenseFinder
|
|
72
72
|
@identifier.version,
|
73
73
|
description: npm_json['description'],
|
74
74
|
homepage: npm_json['homepage'],
|
75
|
+
authors: author_names,
|
75
76
|
spec_licenses: Package.license_names_from_standard_spec(npm_json),
|
76
77
|
install_path: npm_json['path'],
|
77
78
|
children: @dependencies.map(&:name))
|
78
79
|
end
|
79
80
|
|
81
|
+
def author_names
|
82
|
+
names = []
|
83
|
+
names.push(author_name(@json['author'])) unless @json['author'].nil?
|
84
|
+
names += @json['contributors'].map { |c| author_name(c) } if @json['contributors'].is_a?(Array)
|
85
|
+
names.join(', ')
|
86
|
+
end
|
87
|
+
|
88
|
+
def author_name(author)
|
89
|
+
if author.instance_of?(String)
|
90
|
+
author_name_from_combined(author)
|
91
|
+
else
|
92
|
+
author['name']
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def author_name_from_combined(author)
|
97
|
+
matches = author.match /^(.*?)\s*(<.*?>)?\s*(\(.*?\))?\s*$/
|
98
|
+
matches[1]
|
99
|
+
end
|
100
|
+
|
80
101
|
def ==(other)
|
81
102
|
other.is_a?(NpmPackage) && @identifier == other.identifier
|
82
103
|
end
|
@@ -4,7 +4,7 @@ module LicenseFinder
|
|
4
4
|
class CsvReport < Report
|
5
5
|
COMMA_SEP = ','.freeze
|
6
6
|
NEWLINE_SEP = '\@NL'.freeze
|
7
|
-
AVAILABLE_COLUMNS = %w[name version authors licenses license_links approved summary description homepage install_path package_manager groups texts notice].freeze
|
7
|
+
AVAILABLE_COLUMNS = %w[name version authors licenses license_links approved summary description homepage install_path package_manager groups texts notice approved_by approved_reason].freeze
|
8
8
|
MISSING_DEPENDENCY_TEXT = 'This package is not installed. Please install to determine licenses.'.freeze
|
9
9
|
|
10
10
|
def initialize(dependencies, options)
|
@@ -95,5 +95,14 @@ module LicenseFinder
|
|
95
95
|
dep.groups.join(self.class::COMMA_SEP)
|
96
96
|
end
|
97
97
|
end
|
98
|
+
|
99
|
+
def format_approved_by(dep)
|
100
|
+
dep.approved_manually? ? dep.manual_approval.who : ''
|
101
|
+
end
|
102
|
+
|
103
|
+
def format_approved_reason(dep)
|
104
|
+
dep.approved_manually? ? dep.manual_approval.why : ''
|
105
|
+
end
|
106
|
+
|
98
107
|
end
|
99
108
|
end
|
@@ -3,7 +3,7 @@
|
|
3
3
|
module LicenseFinder
|
4
4
|
class Scanner
|
5
5
|
PACKAGE_MANAGERS = [
|
6
|
-
GoModules, GoDep, GoWorkspace, Go15VendorExperiment, Glide, Gvt, Govendor, Trash, Dep, Bundler, NPM, Pip,
|
6
|
+
GoModules, GoDep, GoWorkspace, Go15VendorExperiment, Glide, Gvt, Govendor, Trash, Dep, Bundler, NPM, PNPM, Pip,
|
7
7
|
Yarn, Bower, Maven, Gradle, CocoaPods, Rebar, Erlangmk, Nuget, Carthage, Mix, Conan, Sbt, Cargo, Dotnet, Composer, Pipenv,
|
8
8
|
Conda, Spm, Pub
|
9
9
|
].freeze
|
data/license_finder.gemspec
CHANGED
@@ -50,11 +50,11 @@ Gem::Specification.new do |s|
|
|
50
50
|
s.add_dependency 'with_env', '1.1.0'
|
51
51
|
s.add_dependency 'xml-simple', '~> 1.1.9'
|
52
52
|
|
53
|
-
s.add_development_dependency 'addressable', '2.8.
|
53
|
+
s.add_development_dependency 'addressable', '2.8.1'
|
54
54
|
s.add_development_dependency 'capybara', '~> 3.32.2'
|
55
55
|
s.add_development_dependency 'cocoapods', '>= 1.0.0' if RUBY_PLATFORM.match?(/darwin/)
|
56
56
|
s.add_development_dependency 'e2mmap', '~> 0.1.0'
|
57
|
-
s.add_development_dependency 'fakefs', '~> 1.
|
57
|
+
s.add_development_dependency 'fakefs', '~> 1.8.0'
|
58
58
|
s.add_development_dependency 'matrix', '~> 0.1.0'
|
59
59
|
s.add_development_dependency 'mime-types', '3.4.1'
|
60
60
|
s.add_development_dependency 'pry', '~> 0.14.1'
|
@@ -66,8 +66,8 @@ Gem::Specification.new do |s|
|
|
66
66
|
s.add_development_dependency 'webmock', '~> 3.14'
|
67
67
|
|
68
68
|
s.add_development_dependency 'nokogiri', '~>1.10'
|
69
|
-
s.add_development_dependency 'rack', '~>
|
70
|
-
s.add_development_dependency 'rack-test', '
|
69
|
+
s.add_development_dependency 'rack', '~> 3.0.0'
|
70
|
+
s.add_development_dependency 'rack-test', '> 0.7', '~> 2.0.2'
|
71
71
|
|
72
72
|
s.files = `git ls-files`.split("\n").reject { |f| f.start_with?('spec', 'features') }
|
73
73
|
s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
|