gitlab-license_finder 6.14.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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,77 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module LicenseFinder
|
|
4
|
+
class ConanInfoParser
|
|
5
|
+
def parse(info)
|
|
6
|
+
@lines = info.lines.map(&:chomp)
|
|
7
|
+
@state = :project_level # state of the state machine
|
|
8
|
+
@projects = [] # list of projects
|
|
9
|
+
@current_project = nil # current project being populated in the SM
|
|
10
|
+
@current_vals = [] # current val list being populate in the SM
|
|
11
|
+
@current_key = nil # current key to be associated with the current val
|
|
12
|
+
while (line = @lines.shift)
|
|
13
|
+
next if line == ''
|
|
14
|
+
|
|
15
|
+
case @state
|
|
16
|
+
when :project_level
|
|
17
|
+
@current_project = {}
|
|
18
|
+
@current_project['name'] = line.strip
|
|
19
|
+
@state = :key_val
|
|
20
|
+
when :key_val
|
|
21
|
+
parse_key_val(line)
|
|
22
|
+
when :val_list
|
|
23
|
+
parse_val_list(line)
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
wrap_up
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
private
|
|
30
|
+
|
|
31
|
+
def parse_key_val(line)
|
|
32
|
+
key, val = key_val(line)
|
|
33
|
+
if val
|
|
34
|
+
@current_project[key] = val
|
|
35
|
+
elsif line.start_with?(' ')
|
|
36
|
+
@current_key = key
|
|
37
|
+
@current_vals = []
|
|
38
|
+
@state = :val_list
|
|
39
|
+
else
|
|
40
|
+
change_to_new_project_state line
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def parse_val_list(line)
|
|
45
|
+
if val_list_level(line)
|
|
46
|
+
@current_vals << line.strip
|
|
47
|
+
else
|
|
48
|
+
@current_project[@current_key] = @current_vals
|
|
49
|
+
if line.start_with?(' ')
|
|
50
|
+
@state = :key_val
|
|
51
|
+
@lines.unshift(line)
|
|
52
|
+
else
|
|
53
|
+
change_to_new_project_state line
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def wrap_up
|
|
59
|
+
@current_project[@current_key] = @current_vals if @current_vals.count && @current_key
|
|
60
|
+
@projects << @current_project
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def val_list_level(line)
|
|
64
|
+
line.start_with?(' ')
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def change_to_new_project_state(line)
|
|
68
|
+
@state = :project_level
|
|
69
|
+
@projects << @current_project
|
|
70
|
+
@lines.unshift(line)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def key_val(info)
|
|
74
|
+
info.split(':', 2).map(&:strip!)
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module LicenseFinder
|
|
4
|
+
class GradleDependencyFinder
|
|
5
|
+
def initialize(project_path)
|
|
6
|
+
@project_path = project_path
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def dependencies
|
|
10
|
+
Pathname
|
|
11
|
+
.glob(@project_path.join('**', 'dependency-license.xml'))
|
|
12
|
+
.map(&:read)
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'license_finder/package_utils/possible_license_file'
|
|
4
|
+
|
|
5
|
+
module LicenseFinder
|
|
6
|
+
class LicenseFiles
|
|
7
|
+
CANDIDATE_FILE_NAMES = %w[License Licence COPYING README].freeze
|
|
8
|
+
CANDIDATE_PATH_WILDCARD = "*{#{CANDIDATE_FILE_NAMES.join(',')}}*"
|
|
9
|
+
|
|
10
|
+
def self.find(install_path, options = {})
|
|
11
|
+
new(install_path).find(options)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def initialize(install_path)
|
|
15
|
+
@install_path = install_path ? Pathname(install_path) : nil
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def find(options = {})
|
|
19
|
+
paths_of_candidate_files
|
|
20
|
+
.map { |path| PossibleLicenseFile.new(path, options) }
|
|
21
|
+
.reject { |file| file.license.nil? }
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
private
|
|
25
|
+
|
|
26
|
+
attr_reader :install_path
|
|
27
|
+
|
|
28
|
+
def paths_of_candidate_files
|
|
29
|
+
candidate_files_and_dirs
|
|
30
|
+
.flat_map { |path| path.directory? ? path.children : path }
|
|
31
|
+
.reject(&:directory?)
|
|
32
|
+
.uniq
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def candidate_files_and_dirs
|
|
36
|
+
return [] if install_path.nil?
|
|
37
|
+
|
|
38
|
+
Pathname.glob(install_path.join('**', CANDIDATE_PATH_WILDCARD), File::FNM_CASEFOLD)
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'license_finder/package_utils/activation'
|
|
4
|
+
|
|
5
|
+
module LicenseFinder
|
|
6
|
+
Licensing = Struct.new(:package, :decided_licenses, :licenses_from_spec, :license_files) do
|
|
7
|
+
# Implements the algorithm for choosing the right set of licenses from
|
|
8
|
+
# among the various sources of licenses we know about. In order of
|
|
9
|
+
# priority, licenses come from decisions, package specs, or package files.
|
|
10
|
+
def activations
|
|
11
|
+
if activations_from_decisions.any? then activations_from_decisions
|
|
12
|
+
elsif activations_from_spec.any? then activations_from_spec
|
|
13
|
+
elsif activations_from_files.any? then activations_from_files
|
|
14
|
+
else [default_activation]
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def activations_from_decisions
|
|
19
|
+
@activations_from_decisions ||= decided_licenses
|
|
20
|
+
.map { |license| Activation::FromDecision.new(package, license) }
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def activations_from_spec
|
|
24
|
+
@activations_from_spec ||= licenses_from_spec
|
|
25
|
+
.map { |license| Activation::FromSpec.new(package, license) }
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def activations_from_files
|
|
29
|
+
@activations_from_files ||= license_files
|
|
30
|
+
.group_by(&:license)
|
|
31
|
+
.map { |license, files| Activation::FromFiles.new(package, license, files) }
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def default_activation
|
|
35
|
+
default_license = License.find_by_name nil
|
|
36
|
+
Activation::None.new(package, default_license)
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module LicenseFinder
|
|
4
|
+
class MavenDependencyFinder
|
|
5
|
+
def initialize(project_path)
|
|
6
|
+
@project_path = project_path
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def dependencies
|
|
10
|
+
Pathname
|
|
11
|
+
.glob(@project_path.join('**', 'target', 'generated-resources', 'licenses.xml'))
|
|
12
|
+
.map(&:read)
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'license_finder/package_utils/possible_license_file'
|
|
4
|
+
|
|
5
|
+
module LicenseFinder
|
|
6
|
+
class NoticeFiles
|
|
7
|
+
CANDIDATE_FILE_NAMES = %w[NOTICE Notice].freeze
|
|
8
|
+
CANDIDATE_PATH_WILDCARD = "*{#{CANDIDATE_FILE_NAMES.join(',')}}*"
|
|
9
|
+
|
|
10
|
+
def self.find(install_path, options = {})
|
|
11
|
+
new(install_path).find(options)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def initialize(install_path)
|
|
15
|
+
@install_path = install_path ? Pathname(install_path) : nil
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def find(options = {})
|
|
19
|
+
paths_of_candidate_files
|
|
20
|
+
.map { |path| PossibleLicenseFile.new(path, options) } # Not really possible license files, but that class has all we need.
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
private
|
|
24
|
+
|
|
25
|
+
attr_reader :install_path
|
|
26
|
+
|
|
27
|
+
def paths_of_candidate_files
|
|
28
|
+
candidate_files_and_dirs
|
|
29
|
+
.flat_map { |path| path.directory? ? path.children : path }
|
|
30
|
+
.reject(&:directory?)
|
|
31
|
+
.uniq
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def candidate_files_and_dirs
|
|
35
|
+
return [] if install_path.nil?
|
|
36
|
+
|
|
37
|
+
Pathname.glob(install_path.join('**', CANDIDATE_PATH_WILDCARD))
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module LicenseFinder
|
|
4
|
+
class PossibleLicenseFile
|
|
5
|
+
def initialize(path, options = {})
|
|
6
|
+
@path = Pathname(path)
|
|
7
|
+
@logger = options[:logger]
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def path
|
|
11
|
+
@path.to_s
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def license
|
|
15
|
+
License.find_by_text(text)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def text
|
|
19
|
+
if @path.exist?
|
|
20
|
+
@text ||= (@path.respond_to?(:binread) ? @path.binread : @path.read)
|
|
21
|
+
else
|
|
22
|
+
@logger.info('ERROR', "#{@path} does not exists", color: :red)
|
|
23
|
+
''
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'net/http'
|
|
4
|
+
require 'openssl'
|
|
5
|
+
|
|
6
|
+
module LicenseFinder
|
|
7
|
+
class PyPI
|
|
8
|
+
CONNECTION_ERRORS = [
|
|
9
|
+
EOFError,
|
|
10
|
+
Errno::ECONNREFUSED,
|
|
11
|
+
Errno::ECONNRESET,
|
|
12
|
+
Errno::ECONNRESET,
|
|
13
|
+
Errno::EHOSTUNREACH,
|
|
14
|
+
Errno::EINVAL,
|
|
15
|
+
Net::OpenTimeout,
|
|
16
|
+
Net::ProtocolError,
|
|
17
|
+
Net::ReadTimeout,
|
|
18
|
+
OpenSSL::OpenSSLError,
|
|
19
|
+
OpenSSL::SSL::SSLError,
|
|
20
|
+
SocketError,
|
|
21
|
+
Timeout::Error
|
|
22
|
+
].freeze
|
|
23
|
+
|
|
24
|
+
class << self
|
|
25
|
+
def definition(name, version)
|
|
26
|
+
response = request("https://pypi.org/pypi/#{name}/#{version}/json")
|
|
27
|
+
response.is_a?(Net::HTTPSuccess) ? JSON.parse(response.body).fetch('info', {}) : {}
|
|
28
|
+
rescue *CONNECTION_ERRORS
|
|
29
|
+
{}
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def request(location, limit = 10)
|
|
33
|
+
uri = URI(location)
|
|
34
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
|
35
|
+
http.use_ssl = true
|
|
36
|
+
response = http.get(uri.request_uri).response
|
|
37
|
+
response.is_a?(Net::HTTPRedirection) && limit.positive? ? request(response['location'], limit - 1) : response
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module LicenseFinder
|
|
4
|
+
class SbtDependencyFinder
|
|
5
|
+
def initialize(project_path)
|
|
6
|
+
@project_path = project_path
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def dependencies
|
|
10
|
+
Pathname
|
|
11
|
+
.glob(@project_path.join('**', 'target', 'license-reports', '*.csv'))
|
|
12
|
+
.map(&:read)
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'open-uri'
|
|
4
|
+
|
|
5
|
+
module LicenseFinder
|
|
6
|
+
class BowerPackage < Package
|
|
7
|
+
def initialize(bower_module, options = {})
|
|
8
|
+
spec = bower_module.fetch('pkgMeta', {})
|
|
9
|
+
|
|
10
|
+
if spec.empty?
|
|
11
|
+
endpoint = bower_module.fetch('endpoint', {})
|
|
12
|
+
name = endpoint['name']
|
|
13
|
+
version = endpoint['target']
|
|
14
|
+
else
|
|
15
|
+
name = spec['name']
|
|
16
|
+
version = spec['version']
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
super(
|
|
20
|
+
name,
|
|
21
|
+
version,
|
|
22
|
+
options.merge(
|
|
23
|
+
summary: spec['description'],
|
|
24
|
+
description: spec['readme'],
|
|
25
|
+
homepage: spec['homepage'],
|
|
26
|
+
spec_licenses: Package.license_names_from_standard_spec(spec),
|
|
27
|
+
install_path: bower_module['canonicalDir'],
|
|
28
|
+
missing: bower_module['missing']
|
|
29
|
+
)
|
|
30
|
+
)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def package_manager
|
|
34
|
+
'Bower'
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def package_url
|
|
38
|
+
meta = JSON.parse(open("https://registry.bower.io/packages/#{CGI.escape(name)}").read)
|
|
39
|
+
meta['url']
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module LicenseFinder
|
|
4
|
+
class BundlerPackage < Package
|
|
5
|
+
def initialize(spec, bundler_def, options = {})
|
|
6
|
+
children = spec.dependencies.map(&:name)
|
|
7
|
+
groups = Array(bundler_def && bundler_def.groups).map(&:to_s)
|
|
8
|
+
|
|
9
|
+
super(
|
|
10
|
+
spec.name,
|
|
11
|
+
spec.version.to_s,
|
|
12
|
+
options.merge(
|
|
13
|
+
authors: Array(spec.authors).join(', '),
|
|
14
|
+
summary: spec.summary,
|
|
15
|
+
description: spec.description,
|
|
16
|
+
homepage: spec.homepage,
|
|
17
|
+
children: children,
|
|
18
|
+
groups: groups,
|
|
19
|
+
spec_licenses: spec.licenses,
|
|
20
|
+
install_path: spec.full_gem_path
|
|
21
|
+
)
|
|
22
|
+
)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def package_manager
|
|
26
|
+
'Bundler'
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def package_url
|
|
30
|
+
"https://rubygems.org/gems/#{CGI.escape(name)}/versions/#{CGI.escape(version)}"
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module LicenseFinder
|
|
4
|
+
class CargoPackage < Package
|
|
5
|
+
def initialize(crate, options = {})
|
|
6
|
+
crate = crate.reject { |_, v| v.nil? || v == '' }
|
|
7
|
+
children = crate.fetch('dependencies', []).map { |p| p['name'] }
|
|
8
|
+
licenses = crate.fetch('license', '').split('/')
|
|
9
|
+
super(
|
|
10
|
+
crate['name'],
|
|
11
|
+
crate['version'],
|
|
12
|
+
options.merge(
|
|
13
|
+
summary: crate.fetch('description', '').strip,
|
|
14
|
+
spec_licenses: licenses.compact,
|
|
15
|
+
children: children
|
|
16
|
+
)
|
|
17
|
+
)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def package_manager
|
|
21
|
+
'Cargo'
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def package_url
|
|
25
|
+
"https://crates.io/crates/#{CGI.escape(name)}/#{CGI.escape(version)}"
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module LicenseFinder
|
|
4
|
+
class CarthagePackage < 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
|
+
'Carthage'
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module LicenseFinder
|
|
4
|
+
class CocoaPodsPackage < 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
|
+
'CocoaPods'
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def package_url
|
|
19
|
+
"https://cocoapods.org/pods/#{CGI.escape(name)}"
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module LicenseFinder
|
|
4
|
+
class ConanPackage < Package
|
|
5
|
+
def initialize(name, version, license_text, url, options = {})
|
|
6
|
+
super(name, version, options)
|
|
7
|
+
@license = License.find_by_text(license_text.to_s)
|
|
8
|
+
@homepage = url
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def licenses_from_spec
|
|
12
|
+
[@license].compact
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def package_manager
|
|
16
|
+
'Conan'
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def package_url
|
|
20
|
+
"https://conan.io/center/#{CGI.escape(name)}/#{CGI.escape(version)}"
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module LicenseFinder
|
|
4
|
+
class CondaPackage < Package
|
|
5
|
+
attr_accessor :identifier, :json
|
|
6
|
+
|
|
7
|
+
def initialize(conda_json)
|
|
8
|
+
@json = conda_json
|
|
9
|
+
@identifier = Identifier.from_hash(conda_json)
|
|
10
|
+
super(@identifier.name,
|
|
11
|
+
@identifier.version,
|
|
12
|
+
spec_licenses: Package.license_names_from_standard_spec(conda_json),
|
|
13
|
+
children: children)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def ==(other)
|
|
17
|
+
other.is_a?(CondaPackage) && @identifier == other.identifier
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def to_s
|
|
21
|
+
@identifier.to_s
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def package_manager
|
|
25
|
+
'Conda'
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def package_url
|
|
29
|
+
@json['url']
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def children
|
|
33
|
+
@json.fetch('depends', []).map { |constraint| constraint.split.first }
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
class Identifier
|
|
37
|
+
attr_accessor :name, :version
|
|
38
|
+
|
|
39
|
+
def initialize(name, version)
|
|
40
|
+
@name = name
|
|
41
|
+
@version = version
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def self.from_hash(hash)
|
|
45
|
+
name = hash['name']
|
|
46
|
+
version = hash['version']
|
|
47
|
+
return nil if name.nil? || version.nil?
|
|
48
|
+
|
|
49
|
+
Identifier.new(name, version)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def ==(other)
|
|
53
|
+
other.is_a?(Identifier) && @name == other.name && @version == other.version
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def eql?(other)
|
|
57
|
+
self == other
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def hash
|
|
61
|
+
[@name, @version].hash
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def <=>(other)
|
|
65
|
+
sort_name = @name <=> other.name
|
|
66
|
+
sort_name.zero? ? @version <=> other.version : sort_name
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def to_s
|
|
70
|
+
"#{@name} - #{@version}"
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'rubygems'
|
|
4
|
+
|
|
5
|
+
class InvalidErlangmkPackageError < ArgumentError
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
module LicenseFinder
|
|
9
|
+
class ErlangmkPackage < Package
|
|
10
|
+
attr_reader :dep_parent,
|
|
11
|
+
:dep_name,
|
|
12
|
+
:dep_fetch_method,
|
|
13
|
+
:dep_repo_unformatted,
|
|
14
|
+
:dep_version_unformatted,
|
|
15
|
+
:dep_absolute_path
|
|
16
|
+
|
|
17
|
+
def initialize(dep_string_from_query_deps)
|
|
18
|
+
@dep_parent,
|
|
19
|
+
@dep_name,
|
|
20
|
+
@dep_fetch_method,
|
|
21
|
+
@dep_repo_unformatted,
|
|
22
|
+
@dep_version_unformatted,
|
|
23
|
+
@dep_absolute_path = dep_string_from_query_deps.split
|
|
24
|
+
|
|
25
|
+
raise_invalid(dep_string_from_query_deps) unless all_parts_valid?
|
|
26
|
+
|
|
27
|
+
super(
|
|
28
|
+
dep_name,
|
|
29
|
+
dep_version,
|
|
30
|
+
homepage: dep_repo,
|
|
31
|
+
install_path: dep_absolute_path
|
|
32
|
+
)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def package_manager
|
|
36
|
+
'Erlangmk'
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def dep_version
|
|
40
|
+
@dep_version ||= begin
|
|
41
|
+
dep_version_unformatted.sub(version_prefix_re, '')
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def dep_repo
|
|
46
|
+
@dep_repo ||= dep_repo_unformatted
|
|
47
|
+
.chomp('.git')
|
|
48
|
+
.sub('git@github.com:', 'https://github.com/')
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def raise_invalid(dep_string)
|
|
52
|
+
invalid_dep_message = "'#{dep_string}' does not look like a valid Erlank.mk dependency"
|
|
53
|
+
valid_dep_example = "A valid dependency example: 'lager: goldrush git https://github.com/DeadZen/goldrush.git 0.1.9 /absolute/path/to/dep'"
|
|
54
|
+
raise(InvalidErlangmkPackageError, "#{invalid_dep_message}. #{valid_dep_example}")
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def all_parts_valid?
|
|
58
|
+
dep_part_valid?(dep_parent) &&
|
|
59
|
+
dep_part_valid?(dep_name) &&
|
|
60
|
+
set?(dep_fetch_method) &&
|
|
61
|
+
dep_repo_valid? &&
|
|
62
|
+
dep_version_valid? &&
|
|
63
|
+
set?(dep_absolute_path)
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
private
|
|
67
|
+
|
|
68
|
+
def dep_part_valid?(dep_part)
|
|
69
|
+
set?(dep_part) &&
|
|
70
|
+
word?(dep_part)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def set?(dep_part)
|
|
74
|
+
!dep_part.nil? &&
|
|
75
|
+
!dep_part.empty?
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def word?(dep_part)
|
|
79
|
+
dep = dep_part.chomp(':')
|
|
80
|
+
dep =~ word_re
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def dep_repo_valid?
|
|
84
|
+
set?(dep_repo_unformatted) &&
|
|
85
|
+
URI.parse(dep_repo)
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def dep_version_valid?
|
|
89
|
+
return false unless set?(dep_version_unformatted)
|
|
90
|
+
|
|
91
|
+
if dep_version =~ version_re
|
|
92
|
+
Gem::Version.correct?(dep_version)
|
|
93
|
+
else
|
|
94
|
+
dep_version =~ word_dot_re
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def version_re
|
|
99
|
+
@version_re ||= Regexp.new('\d+\.\d+\.\d+')
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def version_prefix_re
|
|
103
|
+
@version_prefix_re ||= Regexp.new('^v')
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def word_re
|
|
107
|
+
@word_re ||= Regexp.new('^\w+$')
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def word_dot_re
|
|
111
|
+
@word_dot_re ||= Regexp.new('^[.\w]+$')
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
end
|