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,118 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'forwardable'
|
4
|
+
|
5
|
+
require 'license_finder/logger'
|
6
|
+
require 'license_finder/license'
|
7
|
+
|
8
|
+
require 'license_finder/configuration'
|
9
|
+
require 'license_finder/package_manager'
|
10
|
+
require 'license_finder/decisions'
|
11
|
+
require 'license_finder/decisions_factory'
|
12
|
+
require 'license_finder/decision_applier'
|
13
|
+
require 'license_finder/scanner'
|
14
|
+
|
15
|
+
module LicenseFinder
|
16
|
+
# Coordinates setup
|
17
|
+
class Core
|
18
|
+
attr_reader :config
|
19
|
+
|
20
|
+
def self.default_logger
|
21
|
+
Logger.new
|
22
|
+
end
|
23
|
+
|
24
|
+
# Default +options+:
|
25
|
+
# {
|
26
|
+
# project_path: Pathname.pwd
|
27
|
+
# logger: nil, # can be :quiet or :debug
|
28
|
+
# decisions_file: "doc/dependency_decisions.yml",
|
29
|
+
# gradle_command: "gradle",
|
30
|
+
# rebar_command: "rebar",
|
31
|
+
# rebar_deps_dir: "deps",
|
32
|
+
# }
|
33
|
+
def initialize(configuration)
|
34
|
+
@logger = Logger.new(configuration.logger_mode)
|
35
|
+
@config = configuration
|
36
|
+
@scanner = Scanner.new(options)
|
37
|
+
end
|
38
|
+
|
39
|
+
def modifying
|
40
|
+
yield
|
41
|
+
decisions.save!(config.decisions_file_path)
|
42
|
+
end
|
43
|
+
|
44
|
+
extend Forwardable
|
45
|
+
def_delegators :decision_applier, :acknowledged, :unapproved, :restricted, :any_packages?
|
46
|
+
|
47
|
+
def project_name
|
48
|
+
decisions.project_name || config.project_path.basename.to_s
|
49
|
+
end
|
50
|
+
|
51
|
+
def project_path
|
52
|
+
config.project_path
|
53
|
+
end
|
54
|
+
|
55
|
+
def decisions
|
56
|
+
@decisions ||= DecisionsFactory.decisions(config.decisions_file_path)
|
57
|
+
end
|
58
|
+
|
59
|
+
def prepare_projects
|
60
|
+
clear_logs
|
61
|
+
package_managers = @scanner.active_package_managers
|
62
|
+
package_managers.each do |manager|
|
63
|
+
logger.debug manager.class, 'Running prepare on project'
|
64
|
+
manager.prepare
|
65
|
+
logger.debug manager.class, 'Finished prepare on project', color: :green
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
private
|
70
|
+
|
71
|
+
attr_reader :logger
|
72
|
+
|
73
|
+
# The core of the system. The saved decisions are applied to the current
|
74
|
+
# packages.
|
75
|
+
def decision_applier
|
76
|
+
# lazy, do not move to `initialize`
|
77
|
+
# Needs to be lazy loaded to prvent multiple decision appliers being created each time
|
78
|
+
@decision_applier ||= DecisionApplier.new(decisions: decisions, packages: current_packages)
|
79
|
+
end
|
80
|
+
|
81
|
+
def current_packages
|
82
|
+
# lazy, do not move to `initialize`
|
83
|
+
@scanner.active_packages
|
84
|
+
end
|
85
|
+
|
86
|
+
def clear_logs
|
87
|
+
FileUtils.rmtree config.log_directory, secure: true if File.directory? config.log_directory
|
88
|
+
end
|
89
|
+
|
90
|
+
def options # rubocop:disable Metrics/AbcSize
|
91
|
+
{
|
92
|
+
logger: logger,
|
93
|
+
project_path: config.project_path,
|
94
|
+
log_directory: File.join(config.log_directory, project_name),
|
95
|
+
ignored_groups: decisions.ignored_groups,
|
96
|
+
enabled_package_manager_ids: config.enabled_package_manager_ids,
|
97
|
+
go_full_version: config.go_full_version,
|
98
|
+
gradle_command: config.gradle_command,
|
99
|
+
gradle_include_groups: config.gradle_include_groups,
|
100
|
+
maven_include_groups: config.maven_include_groups,
|
101
|
+
maven_options: config.maven_options,
|
102
|
+
npm_options: config.npm_options,
|
103
|
+
pip_requirements_path: config.pip_requirements_path,
|
104
|
+
python_version: config.python_version,
|
105
|
+
rebar_command: config.rebar_command,
|
106
|
+
rebar_deps_dir: config.rebar_deps_dir,
|
107
|
+
elixir_command: config.elixir_command,
|
108
|
+
mix_command: config.mix_command,
|
109
|
+
mix_deps_dir: config.mix_deps_dir,
|
110
|
+
prepare: config.prepare,
|
111
|
+
prepare_no_fail: config.prepare_no_fail,
|
112
|
+
sbt_include_groups: config.sbt_include_groups,
|
113
|
+
conda_bash_setup_script: config.conda_bash_setup_script,
|
114
|
+
composer_check_require_only: config.composer_check_require_only
|
115
|
+
}
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module LicenseFinder
|
4
|
+
class DecisionApplier
|
5
|
+
def initialize(options)
|
6
|
+
@decisions = options.fetch(:decisions)
|
7
|
+
@all_packages = options.fetch(:packages).to_set + @decisions.packages.to_set
|
8
|
+
@acknowledged = apply_decisions
|
9
|
+
end
|
10
|
+
|
11
|
+
attr_reader :acknowledged
|
12
|
+
|
13
|
+
def unapproved
|
14
|
+
acknowledged.reject(&:approved?)
|
15
|
+
end
|
16
|
+
|
17
|
+
def restricted
|
18
|
+
acknowledged.select(&:restricted?)
|
19
|
+
end
|
20
|
+
|
21
|
+
def any_packages?
|
22
|
+
all_packages.any?
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
attr_reader :decisions, :all_packages
|
28
|
+
|
29
|
+
def apply_decisions
|
30
|
+
all_packages
|
31
|
+
.reject { |package| ignored?(package) }
|
32
|
+
.map do |package|
|
33
|
+
with_homepage(
|
34
|
+
with_approval(
|
35
|
+
with_decided_licenses(package)
|
36
|
+
)
|
37
|
+
)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def ignored?(package)
|
42
|
+
decisions.ignored?(package.name) ||
|
43
|
+
(package.groups.any? && package.groups.all? { |group| decisions.ignored_group?(group) })
|
44
|
+
end
|
45
|
+
|
46
|
+
def with_decided_licenses(package)
|
47
|
+
decisions.licenses_of(package.name).each do |license|
|
48
|
+
package.decide_on_license license
|
49
|
+
end
|
50
|
+
package
|
51
|
+
end
|
52
|
+
|
53
|
+
def with_homepage(package)
|
54
|
+
homepage = decisions.homepage_of(package.name)
|
55
|
+
package.homepage = homepage if homepage
|
56
|
+
package
|
57
|
+
end
|
58
|
+
|
59
|
+
def with_approval(package)
|
60
|
+
if package.licenses.all? { |license| decisions.restricted?(license) }
|
61
|
+
package.restricted!
|
62
|
+
elsif decisions.approved?(package.name, package.version)
|
63
|
+
package.approved_manually!(decisions.approval_of(package.name, package.version))
|
64
|
+
elsif package.licenses.any? { |license| decisions.permitted?(license) }
|
65
|
+
package.permitted!
|
66
|
+
end
|
67
|
+
package
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,312 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'open-uri'
|
4
|
+
require 'license_finder/license'
|
5
|
+
|
6
|
+
module LicenseFinder
|
7
|
+
class Decisions
|
8
|
+
######
|
9
|
+
# READ
|
10
|
+
######
|
11
|
+
|
12
|
+
attr_reader :packages, :permitted, :restricted, :ignored, :ignored_groups, :project_name, :inherited_decisions
|
13
|
+
|
14
|
+
def licenses_of(name)
|
15
|
+
@licenses[name]
|
16
|
+
end
|
17
|
+
|
18
|
+
def homepage_of(name)
|
19
|
+
@homepages[name]
|
20
|
+
end
|
21
|
+
|
22
|
+
def approval_of(name, version = nil)
|
23
|
+
if !@approvals.key?(name)
|
24
|
+
nil
|
25
|
+
elsif !version.nil?
|
26
|
+
@approvals[name] if @approvals[name][:safe_versions].empty? || @approvals[name][:safe_versions].include?(version)
|
27
|
+
elsif @approvals[name][:safe_versions].empty?
|
28
|
+
@approvals[name]
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def approved?(name, version = nil)
|
33
|
+
if !@approvals.key?(name)
|
34
|
+
nil
|
35
|
+
elsif !version.nil?
|
36
|
+
@approvals.key?(name) && @approvals[name][:safe_versions].empty? || @approvals[name][:safe_versions].include?(version)
|
37
|
+
else
|
38
|
+
@approvals.key?(name)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def permitted?(lic)
|
43
|
+
if @permitted.include?(lic)
|
44
|
+
true
|
45
|
+
elsif lic.is_a?(OrLicense)
|
46
|
+
lic.sub_licenses.any? { |sub_lic| @permitted.include?(sub_lic) }
|
47
|
+
elsif lic.is_a?(AndLicense)
|
48
|
+
lic.sub_licenses.all? { |sub_lic| @permitted.include?(sub_lic) }
|
49
|
+
else
|
50
|
+
false
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def restricted?(lic)
|
55
|
+
@restricted.include?(lic)
|
56
|
+
end
|
57
|
+
|
58
|
+
def ignored?(name)
|
59
|
+
@ignored.include?(name)
|
60
|
+
end
|
61
|
+
|
62
|
+
def ignored_group?(name)
|
63
|
+
@ignored_groups.include?(name)
|
64
|
+
end
|
65
|
+
|
66
|
+
#######
|
67
|
+
# WRITE
|
68
|
+
#######
|
69
|
+
|
70
|
+
TXN = Struct.new(:who, :why, :safe_when, :safe_versions) do
|
71
|
+
def self.from_hash(txn, versions)
|
72
|
+
new(txn[:who], txn[:why], txn[:when], versions || [])
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def initialize
|
77
|
+
@decisions = []
|
78
|
+
@packages = Set.new
|
79
|
+
@licenses = Hash.new { |h, k| h[k] = Set.new }
|
80
|
+
@homepages = {}
|
81
|
+
@approvals = {}
|
82
|
+
@permitted = Set.new
|
83
|
+
@restricted = Set.new
|
84
|
+
@ignored = Set.new
|
85
|
+
@ignored_groups = Set.new
|
86
|
+
@inherited_decisions = Set.new
|
87
|
+
end
|
88
|
+
|
89
|
+
def add_package(name, version, txn = {})
|
90
|
+
add_decision [:add_package, name, version, txn]
|
91
|
+
@packages << ManualPackage.new(name, version)
|
92
|
+
self
|
93
|
+
end
|
94
|
+
|
95
|
+
def remove_package(name, txn = {})
|
96
|
+
add_decision [:remove_package, name, txn]
|
97
|
+
@packages.delete(ManualPackage.new(name))
|
98
|
+
self
|
99
|
+
end
|
100
|
+
|
101
|
+
def license(name, lic, txn = {})
|
102
|
+
add_decision [:license, name, lic, txn]
|
103
|
+
@licenses[name] << License.find_by_name(lic)
|
104
|
+
self
|
105
|
+
end
|
106
|
+
|
107
|
+
def unlicense(name, lic, txn = {})
|
108
|
+
add_decision [:unlicense, name, lic, txn]
|
109
|
+
@licenses[name].delete(License.find_by_name(lic))
|
110
|
+
self
|
111
|
+
end
|
112
|
+
|
113
|
+
def homepage(name, homepage, txn = {})
|
114
|
+
add_decision [:homepage, name, homepage, txn]
|
115
|
+
@homepages[name] = homepage
|
116
|
+
self
|
117
|
+
end
|
118
|
+
|
119
|
+
def approve(name, txn = {})
|
120
|
+
add_decision [:approve, name, txn]
|
121
|
+
|
122
|
+
versions = []
|
123
|
+
versions = @approvals[name][:safe_versions] if @approvals.key?(name)
|
124
|
+
@approvals[name] = TXN.from_hash(txn, versions)
|
125
|
+
@approvals[name][:safe_versions].concat(txn[:versions]) unless txn[:versions].nil?
|
126
|
+
self
|
127
|
+
end
|
128
|
+
|
129
|
+
def unapprove(name, txn = {})
|
130
|
+
add_decision [:unapprove, name, txn]
|
131
|
+
@approvals.delete(name)
|
132
|
+
self
|
133
|
+
end
|
134
|
+
|
135
|
+
def permit(lic, txn = {})
|
136
|
+
add_decision [:permit, lic, txn]
|
137
|
+
@permitted << License.find_by_name(lic)
|
138
|
+
self
|
139
|
+
end
|
140
|
+
|
141
|
+
def unpermit(lic, txn = {})
|
142
|
+
add_decision [:unpermit, lic, txn]
|
143
|
+
@permitted.delete(License.find_by_name(lic))
|
144
|
+
self
|
145
|
+
end
|
146
|
+
|
147
|
+
def restrict(lic, txn = {})
|
148
|
+
add_decision [:restrict, lic, txn]
|
149
|
+
@restricted << License.find_by_name(lic)
|
150
|
+
self
|
151
|
+
end
|
152
|
+
|
153
|
+
def unrestrict(lic, txn = {})
|
154
|
+
add_decision [:unrestrict, lic, txn]
|
155
|
+
@restricted.delete(License.find_by_name(lic))
|
156
|
+
self
|
157
|
+
end
|
158
|
+
|
159
|
+
def ignore(name, txn = {})
|
160
|
+
add_decision [:ignore, name, txn]
|
161
|
+
@ignored << name
|
162
|
+
self
|
163
|
+
end
|
164
|
+
|
165
|
+
def heed(name, txn = {})
|
166
|
+
add_decision [:heed, name, txn]
|
167
|
+
@ignored.delete(name)
|
168
|
+
self
|
169
|
+
end
|
170
|
+
|
171
|
+
def ignore_group(name, txn = {})
|
172
|
+
add_decision [:ignore_group, name, txn]
|
173
|
+
@ignored_groups << name
|
174
|
+
self
|
175
|
+
end
|
176
|
+
|
177
|
+
def heed_group(name, txn = {})
|
178
|
+
add_decision [:heed_group, name, txn]
|
179
|
+
@ignored_groups.delete(name)
|
180
|
+
self
|
181
|
+
end
|
182
|
+
|
183
|
+
def name_project(name, txn = {})
|
184
|
+
add_decision [:name_project, name, txn]
|
185
|
+
@project_name = name
|
186
|
+
self
|
187
|
+
end
|
188
|
+
|
189
|
+
def unname_project(txn = {})
|
190
|
+
add_decision [:unname_project, txn]
|
191
|
+
@project_name = nil
|
192
|
+
self
|
193
|
+
end
|
194
|
+
|
195
|
+
def inherit_from(filepath_info)
|
196
|
+
decisions =
|
197
|
+
if filepath_info.is_a?(Hash)
|
198
|
+
resolve_inheritance(filepath_info)
|
199
|
+
elsif filepath_info =~ %r{^https?://}
|
200
|
+
open_uri(filepath_info).read
|
201
|
+
else
|
202
|
+
Pathname(filepath_info).read
|
203
|
+
end
|
204
|
+
|
205
|
+
add_decision [:inherit_from, filepath_info]
|
206
|
+
@inherited_decisions << filepath_info
|
207
|
+
restore_inheritance(decisions)
|
208
|
+
end
|
209
|
+
|
210
|
+
def resolve_inheritance(filepath_info)
|
211
|
+
if (gem_name = filepath_info['gem'])
|
212
|
+
Pathname(gem_config_path(gem_name, filepath_info['path'])).read
|
213
|
+
else
|
214
|
+
open_uri(filepath_info['url'], filepath_info['authorization']).read
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
def gem_config_path(gem_name, relative_config_path)
|
219
|
+
spec = Gem::Specification.find_by_name(gem_name)
|
220
|
+
File.join(spec.gem_dir, relative_config_path)
|
221
|
+
rescue Gem::LoadError => e
|
222
|
+
raise Gem::LoadError,
|
223
|
+
"Unable to find gem #{gem_name}; is the gem installed? #{e}"
|
224
|
+
end
|
225
|
+
|
226
|
+
def remove_inheritance(filepath)
|
227
|
+
@decisions -= [[:inherit_from, filepath]]
|
228
|
+
@inherited_decisions.delete(filepath)
|
229
|
+
self
|
230
|
+
end
|
231
|
+
|
232
|
+
def add_decision(decision)
|
233
|
+
@decisions << decision unless @inherited
|
234
|
+
end
|
235
|
+
|
236
|
+
def restore_inheritance(decisions)
|
237
|
+
@inherited = true
|
238
|
+
self.class.restore(decisions, self)
|
239
|
+
@inherited = false
|
240
|
+
self
|
241
|
+
end
|
242
|
+
|
243
|
+
def open_uri(uri, auth = nil)
|
244
|
+
header = {}
|
245
|
+
auth_header = resolve_authorization(auth)
|
246
|
+
header['Authorization'] = auth_header if auth_header
|
247
|
+
|
248
|
+
# ruby < 2.5.0 URI.open is private
|
249
|
+
if Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.5.0')
|
250
|
+
# rubocop:disable Security/Open
|
251
|
+
open(uri, header)
|
252
|
+
# rubocop:enable Security/Open
|
253
|
+
else
|
254
|
+
URI.open(uri, header)
|
255
|
+
end
|
256
|
+
end
|
257
|
+
|
258
|
+
def resolve_authorization(auth)
|
259
|
+
return unless auth
|
260
|
+
|
261
|
+
token_env = auth.match(/\$(\S.*)/)
|
262
|
+
return auth unless token_env
|
263
|
+
|
264
|
+
token = ENV[token_env[1]]
|
265
|
+
auth.sub(token_env[0], token)
|
266
|
+
end
|
267
|
+
|
268
|
+
#########
|
269
|
+
# PERSIST
|
270
|
+
#########
|
271
|
+
|
272
|
+
def self.fetch_saved(file)
|
273
|
+
restore(read!(file))
|
274
|
+
end
|
275
|
+
|
276
|
+
def save!(file)
|
277
|
+
write!(persist, file)
|
278
|
+
end
|
279
|
+
|
280
|
+
def self.restore(persisted, result = new)
|
281
|
+
return result unless persisted
|
282
|
+
|
283
|
+
actions = YAML.load(persisted)
|
284
|
+
|
285
|
+
list_of_actions = (actions || []).map(&:first)
|
286
|
+
|
287
|
+
if (list_of_actions & %i[whitelist blacklist]).any?
|
288
|
+
raise 'The decisions file seems to have whitelist/blacklist keys which are deprecated. Please replace them with permit/restrict respectively and try again! More info - https://github.com/pivotal/LicenseFinder/commit/a40b22fda11b3a0efbb3c0a021381534bc998dd9'
|
289
|
+
end
|
290
|
+
|
291
|
+
(actions || []).each do |action, *args|
|
292
|
+
result.send(action, *args)
|
293
|
+
end
|
294
|
+
result
|
295
|
+
end
|
296
|
+
|
297
|
+
def persist
|
298
|
+
YAML.dump(@decisions)
|
299
|
+
end
|
300
|
+
|
301
|
+
def self.read!(file)
|
302
|
+
file.read if file.exist?
|
303
|
+
end
|
304
|
+
|
305
|
+
def write!(value, file)
|
306
|
+
file.dirname.mkpath
|
307
|
+
file.open('w+') do |f|
|
308
|
+
f.print value
|
309
|
+
end
|
310
|
+
end
|
311
|
+
end
|
312
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module LicenseFinder
|
4
|
+
class DecisionsFactory
|
5
|
+
@decisions = {}
|
6
|
+
class << self
|
7
|
+
def decisions(decisions_file_path)
|
8
|
+
@decisions[decisions_file_path] = Decisions.fetch_saved(decisions_file_path) if @decisions[decisions_file_path].nil?
|
9
|
+
@decisions[decisions_file_path]
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module LicenseFinder
|
4
|
+
class Diff
|
5
|
+
class << self
|
6
|
+
def compare(file1, file2)
|
7
|
+
p1 = Set.new(build_packages(file1))
|
8
|
+
p2 = Set.new(build_packages(file2))
|
9
|
+
|
10
|
+
added = p2.difference(p1).to_a
|
11
|
+
removed = p1.difference(p2).to_a
|
12
|
+
unchanged = p1.intersection(p2).to_a
|
13
|
+
|
14
|
+
[].tap do |packages|
|
15
|
+
unchanged.each do |package|
|
16
|
+
package_previous = find_package(p1, package)
|
17
|
+
package_current = find_package(p2, package)
|
18
|
+
|
19
|
+
if package_current.licenses == package_previous.licenses
|
20
|
+
packages << PackageDelta.unchanged(package_current, package_previous)
|
21
|
+
else
|
22
|
+
packages << PackageDelta.removed(package_previous)
|
23
|
+
packages << PackageDelta.added(package_current)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
added.each { |package| packages << PackageDelta.added(package) }
|
28
|
+
removed.each { |package| packages << PackageDelta.removed(package) }
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def build_packages(content)
|
35
|
+
CSV.parse(content).map do |row|
|
36
|
+
row.map!(&:strip)
|
37
|
+
package = Package.new(row[0], row[1], spec_licenses: [row[2]])
|
38
|
+
if row.count == 4
|
39
|
+
MergedPackage.new(package, row[3].split(','))
|
40
|
+
else
|
41
|
+
package
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def find_package(set, package)
|
47
|
+
set.find { |p| p.eql? package }
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|