gitlab-license_finder 6.14.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.force-build +0 -0
- data/.gitignore +13 -0
- data/.rspec +1 -0
- data/.rubocop.yml +70 -0
- data/CHANGELOG.md +981 -0
- data/CONTRIBUTING.md +121 -0
- data/Dockerfile +249 -0
- data/Gemfile +2 -0
- data/LICENSE +22 -0
- data/README.md +555 -0
- data/Rakefile +77 -0
- data/TODO.md +12 -0
- data/VERSION +1 -0
- data/appveyor.yml +21 -0
- data/bin/license_finder +6 -0
- data/bin/license_finder_pip.py +43 -0
- data/ci/pipelines/pull-request.yml.erb +141 -0
- data/ci/pipelines/release.yml.erb +200 -0
- data/ci/scripts/containerize-tests.sh +14 -0
- data/ci/scripts/pushscript.sh +32 -0
- data/ci/scripts/run-rubocop.sh +15 -0
- data/ci/scripts/run-tests.sh +24 -0
- data/ci/scripts/test.ps1 +81 -0
- data/ci/scripts/updateChangelog.sh +84 -0
- data/ci/tasks/build-and-push-gem.yml +10 -0
- data/ci/tasks/build-windows.yml +6 -0
- data/ci/tasks/build.yml +16 -0
- data/ci/tasks/rubocop.yml +15 -0
- data/ci/tasks/run-tests.yml +10 -0
- data/ci/tasks/update-changelog.yml +18 -0
- data/dlf +12 -0
- data/examples/Gemfile +4 -0
- data/examples/custom_erb_template.rb +24 -0
- data/examples/extract_license_data.rb +63 -0
- data/examples/sample_template.erb +7 -0
- data/lib/license_finder/cli/approvals.rb +28 -0
- data/lib/license_finder/cli/base.rb +107 -0
- data/lib/license_finder/cli/dependencies.rb +44 -0
- data/lib/license_finder/cli/ignored_dependencies.rb +32 -0
- data/lib/license_finder/cli/ignored_groups.rb +32 -0
- data/lib/license_finder/cli/inherited_decisions.rb +50 -0
- data/lib/license_finder/cli/licenses.rb +26 -0
- data/lib/license_finder/cli/main.rb +221 -0
- data/lib/license_finder/cli/makes_decisions.rb +38 -0
- data/lib/license_finder/cli/patched_thor.rb +33 -0
- data/lib/license_finder/cli/permitted_licenses.rb +32 -0
- data/lib/license_finder/cli/project_name.rb +32 -0
- data/lib/license_finder/cli/restricted_licenses.rb +32 -0
- data/lib/license_finder/cli.rb +20 -0
- data/lib/license_finder/configuration.rb +186 -0
- data/lib/license_finder/core.rb +118 -0
- data/lib/license_finder/decision_applier.rb +70 -0
- data/lib/license_finder/decisions.rb +312 -0
- data/lib/license_finder/decisions_factory.rb +13 -0
- data/lib/license_finder/diff.rb +51 -0
- data/lib/license_finder/license/any_matcher.rb +15 -0
- data/lib/license_finder/license/definitions.rb +366 -0
- data/lib/license_finder/license/header_matcher.rb +17 -0
- data/lib/license_finder/license/matcher.rb +24 -0
- data/lib/license_finder/license/none_matcher.rb +11 -0
- data/lib/license_finder/license/template.rb +19 -0
- data/lib/license_finder/license/templates/0BSD.txt +10 -0
- data/lib/license_finder/license/templates/Apache1_1.txt +16 -0
- data/lib/license_finder/license/templates/Apache2.txt +172 -0
- data/lib/license_finder/license/templates/BSD.txt +24 -0
- data/lib/license_finder/license/templates/CC01.txt +30 -0
- data/lib/license_finder/license/templates/CDDL1.txt +131 -0
- data/lib/license_finder/license/templates/EPL1.txt +86 -0
- data/lib/license_finder/license/templates/GPLv2.txt +339 -0
- data/lib/license_finder/license/templates/GPLv3.txt +674 -0
- data/lib/license_finder/license/templates/ISC.txt +2 -0
- data/lib/license_finder/license/templates/LGPL.txt +165 -0
- data/lib/license_finder/license/templates/LGPL2_1.txt +169 -0
- data/lib/license_finder/license/templates/MIT.txt +9 -0
- data/lib/license_finder/license/templates/MPL1_1.txt +469 -0
- data/lib/license_finder/license/templates/MPL2.txt +373 -0
- data/lib/license_finder/license/templates/NewBSD.txt +21 -0
- data/lib/license_finder/license/templates/OFL.txt +91 -0
- data/lib/license_finder/license/templates/Python.txt +47 -0
- data/lib/license_finder/license/templates/Ruby.txt +52 -0
- data/lib/license_finder/license/templates/SimplifiedBSD.txt +19 -0
- data/lib/license_finder/license/templates/WTFPL.txt +14 -0
- data/lib/license_finder/license/templates/Zlib.txt +17 -0
- data/lib/license_finder/license/text.rb +45 -0
- data/lib/license_finder/license.rb +117 -0
- data/lib/license_finder/license_aggregator.rb +59 -0
- data/lib/license_finder/logger.rb +69 -0
- data/lib/license_finder/package.rb +202 -0
- data/lib/license_finder/package_delta.rb +61 -0
- data/lib/license_finder/package_manager.rb +181 -0
- data/lib/license_finder/package_managers/bower.rb +37 -0
- data/lib/license_finder/package_managers/bundler.rb +110 -0
- data/lib/license_finder/package_managers/cargo.rb +38 -0
- data/lib/license_finder/package_managers/carthage.rb +68 -0
- data/lib/license_finder/package_managers/cocoa_pods.rb +61 -0
- data/lib/license_finder/package_managers/composer.rb +63 -0
- data/lib/license_finder/package_managers/conan.rb +28 -0
- data/lib/license_finder/package_managers/conda.rb +131 -0
- data/lib/license_finder/package_managers/dep.rb +43 -0
- data/lib/license_finder/package_managers/dotnet.rb +83 -0
- data/lib/license_finder/package_managers/erlangmk.rb +50 -0
- data/lib/license_finder/package_managers/glide.rb +36 -0
- data/lib/license_finder/package_managers/go_15vendorexperiment.rb +87 -0
- data/lib/license_finder/package_managers/go_dep.rb +80 -0
- data/lib/license_finder/package_managers/go_modules.rb +93 -0
- data/lib/license_finder/package_managers/go_workspace.rb +116 -0
- data/lib/license_finder/package_managers/govendor.rb +73 -0
- data/lib/license_finder/package_managers/gradle.rb +99 -0
- data/lib/license_finder/package_managers/gvt.rb +69 -0
- data/lib/license_finder/package_managers/maven.rb +65 -0
- data/lib/license_finder/package_managers/mix.rb +131 -0
- data/lib/license_finder/package_managers/npm.rb +57 -0
- data/lib/license_finder/package_managers/nuget.rb +154 -0
- data/lib/license_finder/package_managers/pip.rb +70 -0
- data/lib/license_finder/package_managers/pipenv.rb +63 -0
- data/lib/license_finder/package_managers/rebar.rb +65 -0
- data/lib/license_finder/package_managers/sbt.rb +50 -0
- data/lib/license_finder/package_managers/spm.rb +93 -0
- data/lib/license_finder/package_managers/trash.rb +43 -0
- data/lib/license_finder/package_managers/yarn.rb +107 -0
- data/lib/license_finder/package_utils/activation.rb +40 -0
- data/lib/license_finder/package_utils/conan_info_parser.rb +77 -0
- data/lib/license_finder/package_utils/gradle_dependency_finder.rb +15 -0
- data/lib/license_finder/package_utils/license_files.rb +41 -0
- data/lib/license_finder/package_utils/licensing.rb +39 -0
- data/lib/license_finder/package_utils/maven_dependency_finder.rb +15 -0
- data/lib/license_finder/package_utils/notice_files.rb +40 -0
- data/lib/license_finder/package_utils/possible_license_file.rb +27 -0
- data/lib/license_finder/package_utils/pypi.rb +41 -0
- data/lib/license_finder/package_utils/sbt_dependency_finder.rb +15 -0
- data/lib/license_finder/packages/bower_package.rb +42 -0
- data/lib/license_finder/packages/bundler_package.rb +33 -0
- data/lib/license_finder/packages/cargo_package.rb +28 -0
- data/lib/license_finder/packages/carthage_package.rb +18 -0
- data/lib/license_finder/packages/cocoa_pods_package.rb +22 -0
- data/lib/license_finder/packages/composer_package.rb +13 -0
- data/lib/license_finder/packages/conan_package.rb +23 -0
- data/lib/license_finder/packages/conda_package.rb +74 -0
- data/lib/license_finder/packages/erlangmk_package.rb +114 -0
- data/lib/license_finder/packages/go_package.rb +32 -0
- data/lib/license_finder/packages/gradle_package.rb +30 -0
- data/lib/license_finder/packages/manual_package.rb +27 -0
- data/lib/license_finder/packages/maven_package.rb +27 -0
- data/lib/license_finder/packages/merged_package.rb +44 -0
- data/lib/license_finder/packages/mix_package.rb +13 -0
- data/lib/license_finder/packages/npm_package.rb +171 -0
- data/lib/license_finder/packages/nuget_package.rb +13 -0
- data/lib/license_finder/packages/pip_package.rb +50 -0
- data/lib/license_finder/packages/rebar_package.rb +13 -0
- data/lib/license_finder/packages/sbt_package.rb +22 -0
- data/lib/license_finder/packages/spm_package.rb +18 -0
- data/lib/license_finder/packages/yarn_package.rb +13 -0
- data/lib/license_finder/platform.rb +15 -0
- data/lib/license_finder/project_finder.rb +62 -0
- data/lib/license_finder/report.rb +33 -0
- data/lib/license_finder/reports/csv_report.rb +99 -0
- data/lib/license_finder/reports/diff_report.rb +29 -0
- data/lib/license_finder/reports/erb_report.rb +58 -0
- data/lib/license_finder/reports/html_report.rb +13 -0
- data/lib/license_finder/reports/json_report.rb +30 -0
- data/lib/license_finder/reports/junit_report.rb +19 -0
- data/lib/license_finder/reports/markdown_report.rb +9 -0
- data/lib/license_finder/reports/merged_report.rb +16 -0
- data/lib/license_finder/reports/templates/bootstrap.css +9 -0
- data/lib/license_finder/reports/templates/html_report.erb +113 -0
- data/lib/license_finder/reports/templates/junit_report.erb +41 -0
- data/lib/license_finder/reports/templates/markdown_report.erb +49 -0
- data/lib/license_finder/reports/templates/xml_report.erb +19 -0
- data/lib/license_finder/reports/text_report.rb +12 -0
- data/lib/license_finder/reports/xml_report.rb +19 -0
- data/lib/license_finder/scanner.rb +83 -0
- data/lib/license_finder/shared_helpers/cmd.rb +13 -0
- data/lib/license_finder/shared_helpers/common_path.rb +29 -0
- data/lib/license_finder/version.rb +6 -0
- data/lib/license_finder.rb +14 -0
- data/license_finder.gemspec +72 -0
- data/release/instructions.md +8 -0
- data/swift-all-keys.asc +240 -0
- metadata +544 -0
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'license_finder/package'
|
4
|
+
|
5
|
+
module LicenseFinder
|
6
|
+
class GoPackage < Package
|
7
|
+
def package_manager
|
8
|
+
'Go'
|
9
|
+
end
|
10
|
+
|
11
|
+
def package_url
|
12
|
+
"https://pkg.go.dev/#{CGI.escape(name)}@#{CGI.escape(version)}"
|
13
|
+
end
|
14
|
+
|
15
|
+
class << self
|
16
|
+
def from_dependency(hash, prefix, full_version)
|
17
|
+
name = hash['ImportPath']
|
18
|
+
install_path = hash['InstallPath']
|
19
|
+
install_path ||= install_path(prefix.join(name))
|
20
|
+
version = full_version ? hash['Rev'].gsub('+incompatible', '') : hash['Rev'][0..6]
|
21
|
+
homepage = hash['Homepage']
|
22
|
+
new(name, version, install_path: install_path, package_manager: 'Go', homepage: homepage)
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def install_path(path)
|
28
|
+
Pathname(path).cleanpath.to_s
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module LicenseFinder
|
4
|
+
class GradlePackage < Package
|
5
|
+
def initialize(spec, options = {})
|
6
|
+
name = spec['name']
|
7
|
+
if name.scan(':').size >= 1
|
8
|
+
group, name, version = name.split(':')
|
9
|
+
else
|
10
|
+
version = 'unknown'
|
11
|
+
end
|
12
|
+
|
13
|
+
name = options[:include_groups] ? "#{group}:#{name}" : name
|
14
|
+
|
15
|
+
licenses = Array(spec['license'])
|
16
|
+
.map { |l| l['name'] }
|
17
|
+
.reject { |reject_name| reject_name == 'No license found' }
|
18
|
+
|
19
|
+
super(name, version, options.merge(spec_licenses: licenses))
|
20
|
+
end
|
21
|
+
|
22
|
+
def package_manager
|
23
|
+
'Gradle'
|
24
|
+
end
|
25
|
+
|
26
|
+
def package_url
|
27
|
+
"https://plugins.gradle.org/plugin/#{CGI.escape(name)}/#{CGI.escape(version)}"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module LicenseFinder
|
4
|
+
class ManualPackage < Package
|
5
|
+
def ==(other)
|
6
|
+
eql? other
|
7
|
+
end
|
8
|
+
|
9
|
+
def eql?(other)
|
10
|
+
name == other.name
|
11
|
+
end
|
12
|
+
|
13
|
+
def hash
|
14
|
+
name.hash
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def licenses_from_spec
|
20
|
+
Set.new
|
21
|
+
end
|
22
|
+
|
23
|
+
def licenses_from_files
|
24
|
+
Set.new
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module LicenseFinder
|
4
|
+
class MavenPackage < Package
|
5
|
+
def initialize(spec, options = {})
|
6
|
+
name = spec['artifactId']
|
7
|
+
name = "#{spec['groupId']}:#{name}" if options[:include_groups]
|
8
|
+
|
9
|
+
super(
|
10
|
+
name,
|
11
|
+
spec['version'],
|
12
|
+
options.merge(
|
13
|
+
spec_licenses: Array(spec['licenses']).map { |l| l['name'] },
|
14
|
+
groups: Array(spec['groupId'])
|
15
|
+
)
|
16
|
+
)
|
17
|
+
end
|
18
|
+
|
19
|
+
def package_manager
|
20
|
+
'Maven'
|
21
|
+
end
|
22
|
+
|
23
|
+
def package_url
|
24
|
+
"https://search.maven.org/artifact/#{CGI.escape(groups.first)}/#{CGI.escape(name.split(':').last)}/#{CGI.escape(version)}/jar"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module LicenseFinder
|
4
|
+
class MergedPackage < Package
|
5
|
+
extend Forwardable
|
6
|
+
attr_reader :dependency
|
7
|
+
|
8
|
+
def initialize(package, aggregate_paths)
|
9
|
+
@dependency = package
|
10
|
+
@aggregate_paths = aggregate_paths.map { |p| Pathname(p) }
|
11
|
+
super(package.name, package.version)
|
12
|
+
end
|
13
|
+
|
14
|
+
def_delegators :@dependency, :name, :version, :authors, :summary, :description, :homepage, :package_url, :children, :parents,
|
15
|
+
:groups, :permitted, :restricted, :manual_approval, :install_path, :licenses, :approved_manually?,
|
16
|
+
:approved_manually!, :approved?, :permitted!, :permitted?, :restricted!, :restricted?, :hash,
|
17
|
+
:activations, :missing, :license_names_from_spec, :decided_licenses, :licensing, :decide_on_license,
|
18
|
+
:license_files, :package_manager, :missing?, :log_activation, :notice_files
|
19
|
+
|
20
|
+
def aggregate_paths
|
21
|
+
@aggregate_paths.map { |p| p.expand_path.to_s }
|
22
|
+
end
|
23
|
+
|
24
|
+
def <=>(other)
|
25
|
+
dependency <=> other.dependency
|
26
|
+
end
|
27
|
+
|
28
|
+
def eql?(other)
|
29
|
+
if other.instance_of? MergedPackage
|
30
|
+
other.dependency.eql?(dependency)
|
31
|
+
else
|
32
|
+
dependency.eql?(other)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def ==(other)
|
37
|
+
dependency.eql?(other.dependency) && aggregate_paths.eql?(other.aggregate_paths)
|
38
|
+
end
|
39
|
+
|
40
|
+
def method_missing(_method_name)
|
41
|
+
nil
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,171 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module LicenseFinder
|
4
|
+
class NpmPackage < Package
|
5
|
+
attr_accessor :identifier, :dependencies, :groups, :json
|
6
|
+
|
7
|
+
class << self
|
8
|
+
def packages_from_json(npm_json, package_path)
|
9
|
+
@packages = flattened_dependencies(npm_json)
|
10
|
+
package_json = PackageJson.new(package_path)
|
11
|
+
populate_groups(package_json)
|
12
|
+
@packages.reject! do |_identifier, package|
|
13
|
+
package.name.empty? &&
|
14
|
+
package.version.empty? &&
|
15
|
+
package.licenses.length == 1 &&
|
16
|
+
package.licenses.first.name == 'unknown'
|
17
|
+
end
|
18
|
+
@packages.values
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def flattened_dependencies(npm_json, existing_packages = {})
|
24
|
+
identifier = Identifier.from_hash npm_json
|
25
|
+
if existing_packages[identifier].nil?
|
26
|
+
existing_packages[identifier] = NpmPackage.new(npm_json) if identifier
|
27
|
+
npm_json.fetch('dependencies', {}).values.map do |d|
|
28
|
+
flattened_dependencies(d, existing_packages)
|
29
|
+
end
|
30
|
+
else
|
31
|
+
duplicate_package = NpmPackage.new(npm_json)
|
32
|
+
unless existing_packages[identifier].dependencies.include?(duplicate_package.dependencies)
|
33
|
+
existing_packages[identifier].dependencies |= duplicate_package.dependencies
|
34
|
+
npm_json.fetch('dependencies', {}).values.map do |d|
|
35
|
+
flattened_dependencies(d, existing_packages)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
existing_packages
|
40
|
+
end
|
41
|
+
|
42
|
+
def populate_groups(package_json)
|
43
|
+
package_json.groups.each do |group|
|
44
|
+
group.package_names.each do |package_name|
|
45
|
+
@packages.each_key do |identifier|
|
46
|
+
next unless identifier.name == package_name
|
47
|
+
|
48
|
+
dependency = @packages[identifier]
|
49
|
+
dependency.groups |= [group.name]
|
50
|
+
populate_child_groups(dependency, @packages)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def populate_child_groups(dependency, packages, populated_ids = [])
|
57
|
+
dependency.dependencies.each do |id|
|
58
|
+
next if populated_ids.include? id
|
59
|
+
|
60
|
+
populated_ids.push id
|
61
|
+
packages[id].groups |= dependency.groups
|
62
|
+
populate_child_groups(packages[id], packages, populated_ids)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def initialize(npm_json)
|
68
|
+
@json = npm_json
|
69
|
+
@identifier = Identifier.from_hash(npm_json)
|
70
|
+
@dependencies = deps_from_json
|
71
|
+
super(@identifier.name,
|
72
|
+
@identifier.version,
|
73
|
+
description: npm_json['description'],
|
74
|
+
homepage: npm_json['homepage'],
|
75
|
+
spec_licenses: Package.license_names_from_standard_spec(npm_json),
|
76
|
+
install_path: npm_json['path'],
|
77
|
+
children: @dependencies.map(&:name))
|
78
|
+
end
|
79
|
+
|
80
|
+
def ==(other)
|
81
|
+
other.is_a?(NpmPackage) && @identifier == other.identifier
|
82
|
+
end
|
83
|
+
|
84
|
+
def to_s
|
85
|
+
@identifier.to_s
|
86
|
+
end
|
87
|
+
|
88
|
+
def package_manager
|
89
|
+
'Npm'
|
90
|
+
end
|
91
|
+
|
92
|
+
def package_url
|
93
|
+
"https://www.npmjs.com/package/#{CGI.escape(name)}/v/#{CGI.escape(version)}"
|
94
|
+
end
|
95
|
+
|
96
|
+
private
|
97
|
+
|
98
|
+
def deps_from_json
|
99
|
+
@json.fetch('dependencies', {}).values.map { |dep| Identifier.from_hash(dep) }.compact
|
100
|
+
end
|
101
|
+
|
102
|
+
class Identifier
|
103
|
+
attr_accessor :name, :version
|
104
|
+
|
105
|
+
def initialize(name, version)
|
106
|
+
@name = name
|
107
|
+
@version = version
|
108
|
+
end
|
109
|
+
|
110
|
+
def self.from_hash(hash)
|
111
|
+
name = hash['name']
|
112
|
+
version = hash['version']
|
113
|
+
return nil if name.nil? || version.nil?
|
114
|
+
|
115
|
+
Identifier.new(name, version)
|
116
|
+
end
|
117
|
+
|
118
|
+
def ==(other)
|
119
|
+
other.is_a?(Identifier) && @name == other.name && @version == other.version
|
120
|
+
end
|
121
|
+
|
122
|
+
def eql?(other)
|
123
|
+
self == other
|
124
|
+
end
|
125
|
+
|
126
|
+
def hash
|
127
|
+
[@name, @version].hash
|
128
|
+
end
|
129
|
+
|
130
|
+
def <=>(other)
|
131
|
+
sort_name = @name <=> other.name
|
132
|
+
sort_name.zero? ? @version <=> other.version : sort_name
|
133
|
+
end
|
134
|
+
|
135
|
+
def to_s
|
136
|
+
"#{@name} - #{@version}"
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
class Group
|
141
|
+
attr_accessor :name, :package_names
|
142
|
+
|
143
|
+
def initialize(name, hash)
|
144
|
+
@name = name
|
145
|
+
@package_names = hash.keys
|
146
|
+
end
|
147
|
+
|
148
|
+
def include?(identifier)
|
149
|
+
@package_names.include? identifier.name
|
150
|
+
end
|
151
|
+
|
152
|
+
def to_s
|
153
|
+
@name
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
class PackageJson
|
158
|
+
attr_reader :groups
|
159
|
+
DEPENDENCY_GROUPS = %w[dependencies devDependencies].freeze
|
160
|
+
|
161
|
+
def initialize(path)
|
162
|
+
json = JSON.parse(File.read(path), max_nesting: false)
|
163
|
+
@groups = DEPENDENCY_GROUPS.map { |name| Group.new(name, json.fetch(name, {})) }
|
164
|
+
end
|
165
|
+
|
166
|
+
def groups_for(identifier)
|
167
|
+
@groups.select { |g| g.include? identifier }.map(&:name)
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'set'
|
4
|
+
|
5
|
+
module LicenseFinder
|
6
|
+
class PipPackage < Package
|
7
|
+
LICENSE_FORMAT = /^License.*::\s*(.*)$/.freeze
|
8
|
+
INVALID_LICENSES = ['', 'UNKNOWN'].to_set
|
9
|
+
|
10
|
+
def self.license_names_from_spec(spec)
|
11
|
+
license_names = spec['license'].to_s.strip.split(' or ')
|
12
|
+
has_unrecognized_license = false
|
13
|
+
|
14
|
+
license_names.each do |license_name|
|
15
|
+
license = License.find_by_name(license_name.strip)
|
16
|
+
|
17
|
+
has_unrecognized_license ||= license.unrecognized_matcher?
|
18
|
+
end
|
19
|
+
|
20
|
+
return license_names if !license_names.empty? && !has_unrecognized_license
|
21
|
+
|
22
|
+
spec
|
23
|
+
.fetch('classifiers', [])
|
24
|
+
.select { |c| c =~ LICENSE_FORMAT }
|
25
|
+
.map { |c| c.gsub(LICENSE_FORMAT, '\1') }
|
26
|
+
end
|
27
|
+
|
28
|
+
def initialize(name, version, spec, options = {})
|
29
|
+
super(
|
30
|
+
name,
|
31
|
+
version,
|
32
|
+
options.merge(
|
33
|
+
authors: spec['author'],
|
34
|
+
summary: spec['summary'],
|
35
|
+
description: spec['description'],
|
36
|
+
homepage: spec['home_page'],
|
37
|
+
spec_licenses: self.class.license_names_from_spec(spec)
|
38
|
+
)
|
39
|
+
)
|
40
|
+
end
|
41
|
+
|
42
|
+
def package_manager
|
43
|
+
'Pip'
|
44
|
+
end
|
45
|
+
|
46
|
+
def package_url
|
47
|
+
"https://pypi.org/project/#{CGI.escape(name)}/#{CGI.escape(version)}/"
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module LicenseFinder
|
4
|
+
class SbtPackage < Package
|
5
|
+
def initialize(spec, options = {})
|
6
|
+
name = spec['artifactId']
|
7
|
+
name = "#{spec['groupId']}:#{name}" if options[:include_groups]
|
8
|
+
|
9
|
+
super(
|
10
|
+
name,
|
11
|
+
spec['version'],
|
12
|
+
options.merge(
|
13
|
+
spec_licenses: Array(spec['licenses']).map { |l| l['name'] }
|
14
|
+
)
|
15
|
+
)
|
16
|
+
end
|
17
|
+
|
18
|
+
def package_manager
|
19
|
+
'Sbt'
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module LicenseFinder
|
4
|
+
class SpmPackage < Package
|
5
|
+
def initialize(name, version, license_text, options = {})
|
6
|
+
super(name, version, options)
|
7
|
+
@license = License.find_by_text(license_text.to_s)
|
8
|
+
end
|
9
|
+
|
10
|
+
def licenses_from_spec
|
11
|
+
[@license].compact
|
12
|
+
end
|
13
|
+
|
14
|
+
def package_manager
|
15
|
+
'Spm'
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module LicenseFinder
|
4
|
+
module Platform
|
5
|
+
def self.darwin?
|
6
|
+
RUBY_PLATFORM =~ /darwin/
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.windows?
|
10
|
+
# SO: What is the correct way to detect if ruby is running on Windows?,
|
11
|
+
# cf. https://stackoverflow.com/a/21468976/2592915
|
12
|
+
Gem.win_platform? || RUBY_PLATFORM =~ /mswin|cygwin|mingw/
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module LicenseFinder
|
4
|
+
class ProjectFinder
|
5
|
+
def initialize(main_project_path, strict_matching = false)
|
6
|
+
@package_managers = LicenseFinder::Scanner::PACKAGE_MANAGERS
|
7
|
+
@strict_matching = strict_matching
|
8
|
+
@main_project_path = main_project_path
|
9
|
+
end
|
10
|
+
|
11
|
+
def find_projects
|
12
|
+
project_paths = []
|
13
|
+
all_paths = find_all_paths
|
14
|
+
until all_paths.empty?
|
15
|
+
project_paths << collect_project_path(all_paths)
|
16
|
+
all_paths.shift
|
17
|
+
end
|
18
|
+
project_paths.compact
|
19
|
+
end
|
20
|
+
|
21
|
+
def collect_project_path(all_paths)
|
22
|
+
potential_project_path = all_paths.first
|
23
|
+
is_active_project = active_project?(potential_project_path)
|
24
|
+
return unless is_active_project
|
25
|
+
|
26
|
+
potential_project_path.to_s
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def find_all_paths
|
32
|
+
Dir.glob("#{@main_project_path}/**/").map { |path| full_path(path) }
|
33
|
+
end
|
34
|
+
|
35
|
+
def remove_nested(pathname, paths)
|
36
|
+
return if project_root?(pathname)
|
37
|
+
|
38
|
+
paths.reject! { |path| nested_path?(path, pathname) }
|
39
|
+
end
|
40
|
+
|
41
|
+
def project_root?(pathname)
|
42
|
+
full_path(@main_project_path).to_s == pathname.to_s
|
43
|
+
end
|
44
|
+
|
45
|
+
def active_project?(project_path)
|
46
|
+
active_project = @package_managers.map do |pm_class|
|
47
|
+
pm = pm_class.new(project_path: project_path, strict_matching: @strict_matching)
|
48
|
+
pm.active?
|
49
|
+
end
|
50
|
+
|
51
|
+
active_project.include?(true)
|
52
|
+
end
|
53
|
+
|
54
|
+
def full_path(rel_path)
|
55
|
+
Pathname.new(rel_path).expand_path
|
56
|
+
end
|
57
|
+
|
58
|
+
def nested_path?(path, pathname)
|
59
|
+
path.to_s.start_with?(pathname.to_s) && path.to_s != pathname.to_s
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module LicenseFinder
|
4
|
+
class Report
|
5
|
+
def self.of(dependencies, options)
|
6
|
+
new(dependencies, options).to_s
|
7
|
+
end
|
8
|
+
|
9
|
+
def initialize(dependencies, options)
|
10
|
+
@dependencies = dependencies
|
11
|
+
@project_name = options[:project_name]
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
attr_reader :dependencies, :project_name
|
17
|
+
|
18
|
+
def sorted_dependencies
|
19
|
+
dependencies.sort
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
require 'license_finder/reports/erb_report'
|
25
|
+
require 'license_finder/reports/csv_report'
|
26
|
+
require 'license_finder/reports/text_report'
|
27
|
+
require 'license_finder/reports/diff_report'
|
28
|
+
require 'license_finder/reports/merged_report'
|
29
|
+
require 'license_finder/reports/html_report'
|
30
|
+
require 'license_finder/reports/markdown_report'
|
31
|
+
require 'license_finder/reports/xml_report'
|
32
|
+
require 'license_finder/reports/json_report'
|
33
|
+
require 'license_finder/reports/junit_report'
|
@@ -0,0 +1,99 @@
|
|
1
|
+
require 'csv'
|
2
|
+
|
3
|
+
module LicenseFinder
|
4
|
+
class CsvReport < Report
|
5
|
+
COMMA_SEP = ','.freeze
|
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
|
8
|
+
MISSING_DEPENDENCY_TEXT = 'This package is not installed. Please install to determine licenses.'.freeze
|
9
|
+
|
10
|
+
def initialize(dependencies, options)
|
11
|
+
super
|
12
|
+
options[:columns] ||= %w[name version licenses]
|
13
|
+
@columns = Array(options[:columns]) & self.class::AVAILABLE_COLUMNS
|
14
|
+
@write_headers = options[:write_headers] || false
|
15
|
+
end
|
16
|
+
|
17
|
+
def to_s
|
18
|
+
CSV.generate(col_sep: self.class::COMMA_SEP, headers: @columns, write_headers: @write_headers) do |csv|
|
19
|
+
sorted_dependencies.each do |s|
|
20
|
+
csv << format_dependency(s)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def format_dependency(dep)
|
28
|
+
@columns.map do |column|
|
29
|
+
send("format_#{column}", dep)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def format_texts(dep)
|
34
|
+
dep.license_files.map { |file| file.text.split(/[\n\r]+/).join(self.class::NEWLINE_SEP) }
|
35
|
+
.join(self.class::NEWLINE_SEP).force_encoding("ISO-8859-1").encode("UTF-8")
|
36
|
+
end
|
37
|
+
|
38
|
+
def format_notice(dep)
|
39
|
+
dep.notice_files.map { |file| file.text.split(/[\n\r]+/).join(self.class::NEWLINE_SEP) }
|
40
|
+
.join(self.class::NEWLINE_SEP).force_encoding("ISO-8859-1").encode("UTF-8")
|
41
|
+
end
|
42
|
+
|
43
|
+
def format_name(dep)
|
44
|
+
dep.name
|
45
|
+
end
|
46
|
+
|
47
|
+
def format_version(dep)
|
48
|
+
dep.version
|
49
|
+
end
|
50
|
+
|
51
|
+
def format_authors(dep)
|
52
|
+
dep.authors.to_s.strip
|
53
|
+
end
|
54
|
+
|
55
|
+
def format_homepage(dep)
|
56
|
+
dep.homepage
|
57
|
+
end
|
58
|
+
|
59
|
+
def format_licenses(dep)
|
60
|
+
if dep.missing?
|
61
|
+
MISSING_DEPENDENCY_TEXT
|
62
|
+
else
|
63
|
+
dep.licenses.map(&:name).join(self.class::COMMA_SEP)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def format_license_links(dep)
|
68
|
+
dep.licenses.map(&:url).join(self.class::COMMA_SEP)
|
69
|
+
end
|
70
|
+
|
71
|
+
def format_approved(dep)
|
72
|
+
dep.approved? ? 'Approved' : 'Not approved'
|
73
|
+
end
|
74
|
+
|
75
|
+
def format_summary(dep)
|
76
|
+
dep.summary.to_s.strip
|
77
|
+
end
|
78
|
+
|
79
|
+
def format_description(dep)
|
80
|
+
dep.description.to_s.strip
|
81
|
+
end
|
82
|
+
|
83
|
+
def format_install_path(dep)
|
84
|
+
dep.install_path
|
85
|
+
end
|
86
|
+
|
87
|
+
def format_package_manager(dep)
|
88
|
+
dep.package_manager
|
89
|
+
end
|
90
|
+
|
91
|
+
def format_groups(dep)
|
92
|
+
if dep.groups.nil?
|
93
|
+
''
|
94
|
+
else
|
95
|
+
dep.groups.join(self.class::COMMA_SEP)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|