license_finder-rubyzip3 7.2.1.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.
Files changed (196) hide show
  1. checksums.yaml +7 -0
  2. data/.force-build +0 -0
  3. data/.github/dependabot.yml +16 -0
  4. data/.gitignore +13 -0
  5. data/.pre-commit-hooks.yaml +10 -0
  6. data/.rspec +1 -0
  7. data/.rubocop.yml +84 -0
  8. data/CHANGELOG.md +1066 -0
  9. data/CONTRIBUTING.md +122 -0
  10. data/Dockerfile +275 -0
  11. data/Gemfile +2 -0
  12. data/LICENSE +22 -0
  13. data/README.md +597 -0
  14. data/Rakefile +77 -0
  15. data/TODO.md +12 -0
  16. data/VERSION +1 -0
  17. data/appveyor.yml +21 -0
  18. data/bin/license_finder +6 -0
  19. data/bin/license_finder_pip.py +43 -0
  20. data/ci/pipelines/pull-request.yml.erb +138 -0
  21. data/ci/pipelines/release.yml.erb +176 -0
  22. data/ci/scripts/containerize-tests.sh +14 -0
  23. data/ci/scripts/pushscript.sh +31 -0
  24. data/ci/scripts/run-rubocop.sh +15 -0
  25. data/ci/scripts/run-tests.sh +41 -0
  26. data/ci/scripts/test.ps1 +81 -0
  27. data/ci/scripts/updateChangelog.sh +84 -0
  28. data/ci/tasks/build-and-push-gem.yml +10 -0
  29. data/ci/tasks/build-windows.yml +6 -0
  30. data/ci/tasks/build.yml +16 -0
  31. data/ci/tasks/rubocop.yml +15 -0
  32. data/ci/tasks/run-tests.yml +10 -0
  33. data/ci/tasks/update-changelog.yml +18 -0
  34. data/dlf +21 -0
  35. data/examples/Gemfile +4 -0
  36. data/examples/custom_erb_template.rb +24 -0
  37. data/examples/extract_license_data.rb +63 -0
  38. data/examples/sample_template.erb +7 -0
  39. data/lib/license_finder/cli/approvals.rb +28 -0
  40. data/lib/license_finder/cli/base.rb +113 -0
  41. data/lib/license_finder/cli/dependencies.rb +44 -0
  42. data/lib/license_finder/cli/ignored_dependencies.rb +32 -0
  43. data/lib/license_finder/cli/ignored_groups.rb +32 -0
  44. data/lib/license_finder/cli/inherited_decisions.rb +50 -0
  45. data/lib/license_finder/cli/licenses.rb +31 -0
  46. data/lib/license_finder/cli/main.rb +229 -0
  47. data/lib/license_finder/cli/makes_decisions.rb +38 -0
  48. data/lib/license_finder/cli/patched_thor.rb +33 -0
  49. data/lib/license_finder/cli/permitted_licenses.rb +32 -0
  50. data/lib/license_finder/cli/project_name.rb +32 -0
  51. data/lib/license_finder/cli/restricted_licenses.rb +32 -0
  52. data/lib/license_finder/cli.rb +20 -0
  53. data/lib/license_finder/configuration.rb +197 -0
  54. data/lib/license_finder/core.rb +121 -0
  55. data/lib/license_finder/decision_applier.rb +70 -0
  56. data/lib/license_finder/decisions.rb +334 -0
  57. data/lib/license_finder/decisions_factory.rb +13 -0
  58. data/lib/license_finder/diff.rb +51 -0
  59. data/lib/license_finder/license/any_matcher.rb +15 -0
  60. data/lib/license_finder/license/definitions.rb +498 -0
  61. data/lib/license_finder/license/header_matcher.rb +17 -0
  62. data/lib/license_finder/license/matcher.rb +24 -0
  63. data/lib/license_finder/license/none_matcher.rb +11 -0
  64. data/lib/license_finder/license/template.rb +19 -0
  65. data/lib/license_finder/license/templates/0BSD.txt +10 -0
  66. data/lib/license_finder/license/templates/AGPL3.txt +661 -0
  67. data/lib/license_finder/license/templates/Apache1_1.txt +16 -0
  68. data/lib/license_finder/license/templates/Apache2.txt +170 -0
  69. data/lib/license_finder/license/templates/Artistic.txt +128 -0
  70. data/lib/license_finder/license/templates/BSD.txt +24 -0
  71. data/lib/license_finder/license/templates/CC01.txt +30 -0
  72. data/lib/license_finder/license/templates/CC01_alt.txt +31 -0
  73. data/lib/license_finder/license/templates/CDDL1.txt +131 -0
  74. data/lib/license_finder/license/templates/CDDL1_1.txt +123 -0
  75. data/lib/license_finder/license/templates/CPL1.txt +217 -0
  76. data/lib/license_finder/license/templates/EPL1.txt +86 -0
  77. data/lib/license_finder/license/templates/EPL2.txt +80 -0
  78. data/lib/license_finder/license/templates/GPLv2.txt +339 -0
  79. data/lib/license_finder/license/templates/GPLv3.txt +674 -0
  80. data/lib/license_finder/license/templates/ISC.txt +2 -0
  81. data/lib/license_finder/license/templates/LGPL.txt +165 -0
  82. data/lib/license_finder/license/templates/LGPL2_1.txt +169 -0
  83. data/lib/license_finder/license/templates/MIT.txt +9 -0
  84. data/lib/license_finder/license/templates/MPL1_1.txt +469 -0
  85. data/lib/license_finder/license/templates/MPL2.txt +373 -0
  86. data/lib/license_finder/license/templates/NewBSD.txt +21 -0
  87. data/lib/license_finder/license/templates/OFL.txt +91 -0
  88. data/lib/license_finder/license/templates/Python.txt +47 -0
  89. data/lib/license_finder/license/templates/Ruby.txt +52 -0
  90. data/lib/license_finder/license/templates/SimplifiedBSD.txt +19 -0
  91. data/lib/license_finder/license/templates/Unlicense.txt +24 -0
  92. data/lib/license_finder/license/templates/WTFPL.txt +14 -0
  93. data/lib/license_finder/license/templates/Zlib.txt +17 -0
  94. data/lib/license_finder/license/text.rb +49 -0
  95. data/lib/license_finder/license.rb +123 -0
  96. data/lib/license_finder/license_aggregator.rb +59 -0
  97. data/lib/license_finder/logger.rb +69 -0
  98. data/lib/license_finder/manual_licenses.rb +79 -0
  99. data/lib/license_finder/package.rb +195 -0
  100. data/lib/license_finder/package_delta.rb +61 -0
  101. data/lib/license_finder/package_manager.rb +183 -0
  102. data/lib/license_finder/package_managers/bower.rb +37 -0
  103. data/lib/license_finder/package_managers/bundler.rb +110 -0
  104. data/lib/license_finder/package_managers/cargo.rb +38 -0
  105. data/lib/license_finder/package_managers/carthage.rb +68 -0
  106. data/lib/license_finder/package_managers/cocoa_pods.rb +66 -0
  107. data/lib/license_finder/package_managers/composer.rb +63 -0
  108. data/lib/license_finder/package_managers/conan.rb +70 -0
  109. data/lib/license_finder/package_managers/conda.rb +131 -0
  110. data/lib/license_finder/package_managers/dep.rb +45 -0
  111. data/lib/license_finder/package_managers/dotnet.rb +86 -0
  112. data/lib/license_finder/package_managers/erlangmk.rb +50 -0
  113. data/lib/license_finder/package_managers/glide.rb +42 -0
  114. data/lib/license_finder/package_managers/go_15vendorexperiment.rb +87 -0
  115. data/lib/license_finder/package_managers/go_dep.rb +80 -0
  116. data/lib/license_finder/package_managers/go_modules.rb +93 -0
  117. data/lib/license_finder/package_managers/go_workspace.rb +117 -0
  118. data/lib/license_finder/package_managers/govendor.rb +73 -0
  119. data/lib/license_finder/package_managers/gradle.rb +99 -0
  120. data/lib/license_finder/package_managers/gvt.rb +69 -0
  121. data/lib/license_finder/package_managers/maven.rb +69 -0
  122. data/lib/license_finder/package_managers/mix.rb +131 -0
  123. data/lib/license_finder/package_managers/npm.rb +70 -0
  124. data/lib/license_finder/package_managers/nuget.rb +159 -0
  125. data/lib/license_finder/package_managers/pip.rb +70 -0
  126. data/lib/license_finder/package_managers/pipenv.rb +63 -0
  127. data/lib/license_finder/package_managers/pnpm.rb +126 -0
  128. data/lib/license_finder/package_managers/pub.rb +86 -0
  129. data/lib/license_finder/package_managers/rebar.rb +65 -0
  130. data/lib/license_finder/package_managers/sbt.rb +46 -0
  131. data/lib/license_finder/package_managers/spm.rb +93 -0
  132. data/lib/license_finder/package_managers/trash.rb +43 -0
  133. data/lib/license_finder/package_managers/yarn.rb +195 -0
  134. data/lib/license_finder/package_utils/activation.rb +40 -0
  135. data/lib/license_finder/package_utils/conan_info_parser.rb +77 -0
  136. data/lib/license_finder/package_utils/conan_info_parser_v2.rb +82 -0
  137. data/lib/license_finder/package_utils/gradle_dependency_finder.rb +15 -0
  138. data/lib/license_finder/package_utils/license_files.rb +51 -0
  139. data/lib/license_finder/package_utils/licensing.rb +40 -0
  140. data/lib/license_finder/package_utils/maven_dependency_finder.rb +57 -0
  141. data/lib/license_finder/package_utils/notice_files.rb +51 -0
  142. data/lib/license_finder/package_utils/possible_license_file.rb +33 -0
  143. data/lib/license_finder/package_utils/pypi.rb +43 -0
  144. data/lib/license_finder/package_utils/sbt_dependency_finder.rb +15 -0
  145. data/lib/license_finder/packages/bower_package.rb +45 -0
  146. data/lib/license_finder/packages/bundler_package.rb +33 -0
  147. data/lib/license_finder/packages/cargo_package.rb +28 -0
  148. data/lib/license_finder/packages/carthage_package.rb +18 -0
  149. data/lib/license_finder/packages/cocoa_pods_package.rb +22 -0
  150. data/lib/license_finder/packages/composer_package.rb +13 -0
  151. data/lib/license_finder/packages/conan_package.rb +23 -0
  152. data/lib/license_finder/packages/conda_package.rb +74 -0
  153. data/lib/license_finder/packages/erlangmk_package.rb +112 -0
  154. data/lib/license_finder/packages/go_package.rb +30 -0
  155. data/lib/license_finder/packages/gradle_package.rb +30 -0
  156. data/lib/license_finder/packages/manual_package.rb +27 -0
  157. data/lib/license_finder/packages/maven_package.rb +39 -0
  158. data/lib/license_finder/packages/merged_package.rb +44 -0
  159. data/lib/license_finder/packages/mix_package.rb +13 -0
  160. data/lib/license_finder/packages/npm_package.rb +219 -0
  161. data/lib/license_finder/packages/nuget_package.rb +13 -0
  162. data/lib/license_finder/packages/pip_package.rb +50 -0
  163. data/lib/license_finder/packages/pnpm_package.rb +13 -0
  164. data/lib/license_finder/packages/pubspec_package.rb +18 -0
  165. data/lib/license_finder/packages/rebar_package.rb +13 -0
  166. data/lib/license_finder/packages/sbt_package.rb +22 -0
  167. data/lib/license_finder/packages/spm_package.rb +18 -0
  168. data/lib/license_finder/packages/yarn_package.rb +13 -0
  169. data/lib/license_finder/platform.rb +15 -0
  170. data/lib/license_finder/printer.rb +39 -0
  171. data/lib/license_finder/project_finder.rb +62 -0
  172. data/lib/license_finder/report.rb +34 -0
  173. data/lib/license_finder/reports/csv_report.rb +108 -0
  174. data/lib/license_finder/reports/diff_report.rb +29 -0
  175. data/lib/license_finder/reports/erb_report.rb +62 -0
  176. data/lib/license_finder/reports/html_report.rb +13 -0
  177. data/lib/license_finder/reports/json_report.rb +31 -0
  178. data/lib/license_finder/reports/junit_report.rb +23 -0
  179. data/lib/license_finder/reports/markdown_report.rb +9 -0
  180. data/lib/license_finder/reports/merged_report.rb +16 -0
  181. data/lib/license_finder/reports/templates/bootstrap.css +9 -0
  182. data/lib/license_finder/reports/templates/html_report.erb +113 -0
  183. data/lib/license_finder/reports/templates/junit_report.erb +41 -0
  184. data/lib/license_finder/reports/templates/markdown_report.erb +49 -0
  185. data/lib/license_finder/reports/templates/xml_report.erb +19 -0
  186. data/lib/license_finder/reports/text_report.rb +12 -0
  187. data/lib/license_finder/reports/xml_report.rb +23 -0
  188. data/lib/license_finder/scanner.rb +83 -0
  189. data/lib/license_finder/shared_helpers/cmd.rb +13 -0
  190. data/lib/license_finder/shared_helpers/common_path.rb +29 -0
  191. data/lib/license_finder/version.rb +6 -0
  192. data/lib/license_finder.rb +14 -0
  193. data/license_finder.gemspec +79 -0
  194. data/release/instructions.md +8 -0
  195. data/swift-all-keys.asc +240 -0
  196. metadata +604 -0
@@ -0,0 +1,121 @@
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
+ @printer = Printer.new
35
+ @logger = Logger.new(configuration.logger_mode)
36
+ @config = configuration
37
+ @scanner = Scanner.new(options)
38
+ end
39
+
40
+ def modifying
41
+ yield
42
+ decisions.save!(config.decisions_file_path)
43
+ end
44
+
45
+ extend Forwardable
46
+ def_delegators :decision_applier, :acknowledged, :unapproved, :restricted, :any_packages?
47
+
48
+ def project_name
49
+ decisions.project_name || config.project_path.basename.to_s
50
+ end
51
+
52
+ def project_path
53
+ config.project_path
54
+ end
55
+
56
+ def decisions
57
+ @decisions ||= DecisionsFactory.decisions(config.decisions_file_path)
58
+ end
59
+
60
+ def prepare_projects
61
+ clear_logs
62
+ package_managers = @scanner.active_package_managers
63
+ package_managers.each do |manager|
64
+ logger.debug manager.class, "Running prepare on project '#{config.project_path}'"
65
+ manager.prepare
66
+ logger.debug manager.class, "Finished prepare on project '#{config.project_path}'", color: :green
67
+ end
68
+ end
69
+
70
+ private
71
+
72
+ attr_reader :logger, :printer
73
+
74
+ # The core of the system. The saved decisions are applied to the current
75
+ # packages.
76
+ def decision_applier
77
+ # lazy, do not move to `initialize`
78
+ # Needs to be lazy loaded to prvent multiple decision appliers being created each time
79
+ @decision_applier ||= DecisionApplier.new(decisions: decisions, packages: current_packages)
80
+ end
81
+
82
+ def current_packages
83
+ # lazy, do not move to `initialize`
84
+ @scanner.active_packages
85
+ end
86
+
87
+ def clear_logs
88
+ FileUtils.rmtree config.log_directory, secure: true if File.directory? config.log_directory
89
+ end
90
+
91
+ def options # rubocop:disable Metrics/AbcSize
92
+ {
93
+ logger: logger,
94
+ project_path: config.project_path,
95
+ log_directory: File.join(config.log_directory, project_name),
96
+ ignored_groups: decisions.ignored_groups,
97
+ enabled_package_manager_ids: config.enabled_package_manager_ids,
98
+ go_full_version: config.go_full_version,
99
+ gradle_command: config.gradle_command,
100
+ gradle_include_groups: config.gradle_include_groups,
101
+ maven_include_groups: config.maven_include_groups,
102
+ maven_options: config.maven_options,
103
+ npm_options: config.npm_options,
104
+ yarn_options: config.yarn_options,
105
+ pnpm_options: config.pnpm_options,
106
+ pip_requirements_path: config.pip_requirements_path,
107
+ python_version: config.python_version,
108
+ rebar_command: config.rebar_command,
109
+ rebar_deps_dir: config.rebar_deps_dir,
110
+ elixir_command: config.elixir_command,
111
+ mix_command: config.mix_command,
112
+ mix_deps_dir: config.mix_deps_dir,
113
+ prepare: config.prepare,
114
+ prepare_no_fail: config.prepare_no_fail,
115
+ sbt_include_groups: config.sbt_include_groups,
116
+ conda_bash_setup_script: config.conda_bash_setup_script,
117
+ composer_check_require_only: config.composer_check_require_only
118
+ }
119
+ end
120
+ end
121
+ 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, package.version).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,334 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'open-uri'
4
+ require 'license_finder/license'
5
+ require 'license_finder/manual_licenses'
6
+
7
+ module LicenseFinder
8
+ class Decisions
9
+ ######
10
+ # READ
11
+ ######
12
+
13
+ attr_reader :packages, :permitted, :restricted, :ignored, :ignored_groups, :project_name, :inherited_decisions
14
+
15
+ def licenses_of(name, version = nil)
16
+ @manual_licenses.licenses_of(name, version)
17
+ end
18
+
19
+ def homepage_of(name)
20
+ @homepages[name]
21
+ end
22
+
23
+ def approval_of(name, version = nil)
24
+ if !@approvals.key?(name)
25
+ nil
26
+ elsif !version.nil?
27
+ @approvals[name] if @approvals[name][:safe_versions].empty? || @approvals[name][:safe_versions].include?(version)
28
+ elsif @approvals[name][:safe_versions].empty?
29
+ @approvals[name]
30
+ end
31
+ end
32
+
33
+ def approved?(name, version = nil)
34
+ if !@approvals.key?(name)
35
+ nil
36
+ elsif !version.nil?
37
+ @approvals.key?(name) && @approvals[name][:safe_versions].empty? || @approvals[name][:safe_versions].include?(version)
38
+ else
39
+ @approvals.key?(name)
40
+ end
41
+ end
42
+
43
+ def permitted?(lic)
44
+ if @permitted.include?(lic)
45
+ true
46
+ elsif lic.is_a?(OrLicense)
47
+ lic.sub_licenses.any? { |sub_lic| @permitted.include?(sub_lic) }
48
+ elsif lic.is_a?(AndLicense)
49
+ lic.sub_licenses.all? { |sub_lic| @permitted.include?(sub_lic) }
50
+ else
51
+ false
52
+ end
53
+ end
54
+
55
+ def restricted?(lic)
56
+ @restricted.include?(lic)
57
+ end
58
+
59
+ def ignored?(name)
60
+ @ignored.include?(name)
61
+ end
62
+
63
+ def ignored_group?(name)
64
+ @ignored_groups.include?(name)
65
+ end
66
+
67
+ #######
68
+ # WRITE
69
+ #######
70
+
71
+ TXN = Struct.new(:who, :why, :safe_when, :safe_versions) do
72
+ def self.from_hash(txn, versions)
73
+ new(txn[:who], txn[:why], txn[:when], versions || [])
74
+ end
75
+ end
76
+
77
+ def initialize
78
+ @decisions = []
79
+ @packages = Set.new
80
+ @manual_licenses = ManualLicenses.new
81
+ @homepages = {}
82
+ @approvals = {}
83
+ @permitted = Set.new
84
+ @restricted = Set.new
85
+ @ignored = Set.new
86
+ @ignored_groups = Set.new
87
+ @inherited_decisions = Set.new
88
+ end
89
+
90
+ def add_package(name, version, txn = {})
91
+ add_decision [:add_package, name, version, txn]
92
+ @packages << ManualPackage.new(name, version)
93
+ self
94
+ end
95
+
96
+ def remove_package(name, txn = {})
97
+ add_decision [:remove_package, name, txn]
98
+ @packages.delete(ManualPackage.new(name))
99
+ self
100
+ end
101
+
102
+ def license(name, lic, txn = {})
103
+ add_decision [:license, name, lic, txn]
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
+
113
+ self
114
+ end
115
+
116
+ def unlicense(name, lic, txn = {})
117
+ add_decision [:unlicense, name, lic, txn]
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
+
127
+ self
128
+ end
129
+
130
+ def homepage(name, homepage, txn = {})
131
+ add_decision [:homepage, name, homepage, txn]
132
+ @homepages[name] = homepage
133
+ self
134
+ end
135
+
136
+ def approve(name, txn = {})
137
+ add_decision [:approve, name, txn]
138
+
139
+ versions = []
140
+ versions = @approvals[name][:safe_versions] if @approvals.key?(name)
141
+ @approvals[name] = TXN.from_hash(txn, versions)
142
+ @approvals[name][:safe_versions].concat(txn[:versions]) unless txn[:versions].nil?
143
+ self
144
+ end
145
+
146
+ def unapprove(name, txn = {})
147
+ add_decision [:unapprove, name, txn]
148
+ @approvals.delete(name)
149
+ self
150
+ end
151
+
152
+ def permit(lic, txn = {})
153
+ add_decision [:permit, lic, txn]
154
+ @permitted << License.find_by_name(lic)
155
+ self
156
+ end
157
+
158
+ def unpermit(lic, txn = {})
159
+ add_decision [:unpermit, lic, txn]
160
+ @permitted.delete(License.find_by_name(lic))
161
+ self
162
+ end
163
+
164
+ def restrict(lic, txn = {})
165
+ add_decision [:restrict, lic, txn]
166
+ @restricted << License.find_by_name(lic)
167
+ self
168
+ end
169
+
170
+ def unrestrict(lic, txn = {})
171
+ add_decision [:unrestrict, lic, txn]
172
+ @restricted.delete(License.find_by_name(lic))
173
+ self
174
+ end
175
+
176
+ def ignore(name, txn = {})
177
+ add_decision [:ignore, name, txn]
178
+ @ignored << name
179
+ self
180
+ end
181
+
182
+ def heed(name, txn = {})
183
+ add_decision [:heed, name, txn]
184
+ @ignored.delete(name)
185
+ self
186
+ end
187
+
188
+ def ignore_group(name, txn = {})
189
+ add_decision [:ignore_group, name, txn]
190
+ @ignored_groups << name
191
+ self
192
+ end
193
+
194
+ def heed_group(name, txn = {})
195
+ add_decision [:heed_group, name, txn]
196
+ @ignored_groups.delete(name)
197
+ self
198
+ end
199
+
200
+ def name_project(name, txn = {})
201
+ add_decision [:name_project, name, txn]
202
+ @project_name = name
203
+ self
204
+ end
205
+
206
+ def unname_project(txn = {})
207
+ add_decision [:unname_project, txn]
208
+ @project_name = nil
209
+ self
210
+ end
211
+
212
+ def inherit_from(filepath_info)
213
+ decisions =
214
+ case filepath_info
215
+ when Hash
216
+ resolve_inheritance(filepath_info)
217
+ when %r{^https?://}
218
+ open_uri(filepath_info).read
219
+ else
220
+ Pathname(filepath_info).read
221
+ end
222
+
223
+ add_decision [:inherit_from, filepath_info]
224
+ @inherited_decisions << filepath_info
225
+ restore_inheritance(decisions)
226
+ end
227
+
228
+ def resolve_inheritance(filepath_info)
229
+ if (gem_name = filepath_info['gem'])
230
+ Pathname(gem_config_path(gem_name, filepath_info['path'])).read
231
+ else
232
+ open_uri(filepath_info['url'], filepath_info['authorization']).read
233
+ end
234
+ end
235
+
236
+ def gem_config_path(gem_name, relative_config_path)
237
+ spec = Gem::Specification.find_by_name(gem_name)
238
+ File.join(spec.gem_dir, relative_config_path)
239
+ rescue Gem::LoadError => e
240
+ raise Gem::LoadError,
241
+ "Unable to find gem #{gem_name}; is the gem installed? #{e}"
242
+ end
243
+
244
+ def remove_inheritance(filepath)
245
+ @decisions -= [[:inherit_from, filepath]]
246
+ @inherited_decisions.delete(filepath)
247
+ self
248
+ end
249
+
250
+ def add_decision(decision)
251
+ @decisions << decision unless @inherited
252
+ end
253
+
254
+ def restore_inheritance(decisions)
255
+ previous_value = @inherited
256
+ @inherited = true
257
+ self.class.restore(decisions, self)
258
+ @inherited = previous_value
259
+ self
260
+ end
261
+
262
+ def open_uri(uri, auth = nil)
263
+ header = {}
264
+ auth_header = resolve_authorization(auth)
265
+ header['Authorization'] = auth_header if auth_header
266
+
267
+ # ruby < 2.5.0 URI.open is private
268
+ if Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.5.0')
269
+ open(uri, header)
270
+ else
271
+ URI.open(uri, header)
272
+ end
273
+ end
274
+
275
+ def resolve_authorization(auth)
276
+ return unless auth
277
+
278
+ token_env = auth.match(/\$(\S.*)/)
279
+ return auth unless token_env
280
+
281
+ token = ENV[token_env[1]]
282
+ auth.sub(token_env[0], token)
283
+ end
284
+
285
+ #########
286
+ # PERSIST
287
+ #########
288
+
289
+ def self.fetch_saved(file)
290
+ restore(read!(file))
291
+ end
292
+
293
+ def save!(file)
294
+ write!(persist, file)
295
+ end
296
+
297
+ def self.restore(persisted, result = new)
298
+ return result unless persisted
299
+
300
+ # From https://makandracards.com/makandra/465149-ruby-the-yaml-safe_load-method-hides-some-pitfalls
301
+ actions = if Gem::Version.new(Psych::VERSION) >= Gem::Version.new('3.1.0.pre1')
302
+ YAML.safe_load(persisted, permitted_classes: [Symbol, Time], aliases: true)
303
+ else
304
+ YAML.safe_load(persisted, [Symbol, Time], [], true)
305
+ end
306
+
307
+ list_of_actions = (actions || []).map(&:first)
308
+
309
+ if (list_of_actions & %i[whitelist blacklist]).any?
310
+ 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'
311
+ end
312
+
313
+ (actions || []).each do |action, *args|
314
+ result.send(action, *args)
315
+ end
316
+ result
317
+ end
318
+
319
+ def persist
320
+ YAML.dump(@decisions)
321
+ end
322
+
323
+ def self.read!(file)
324
+ file.read if file.exist?
325
+ end
326
+
327
+ def write!(value, file)
328
+ file.dirname.mkpath
329
+ file.open('w+') do |f|
330
+ f.print value
331
+ end
332
+ end
333
+ end
334
+ 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
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module LicenseFinder
4
+ class License
5
+ class AnyMatcher
6
+ def initialize(*matchers)
7
+ @matchers = matchers
8
+ end
9
+
10
+ def matches_text?(text)
11
+ @matchers.any? { |m| m.matches_text? text }
12
+ end
13
+ end
14
+ end
15
+ end