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,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module LicenseFinder
4
+ class MixPackage < Package
5
+ def package_manager
6
+ 'Mix'
7
+ end
8
+
9
+ def package_url
10
+ "https://hex.pm/packages/#{CGI.escape(name)}/#{CGI.escape(version)}"
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,219 @@
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] = package_for_dependency(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 = package_for_dependency(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
+ # Read the dependency's package.json file in order to get details like the license, authors,
43
+ # and so on. In NPM versions < 7, this information was included in the output of `npm list`.
44
+ # In later versions, it no longer is, and has to be read from the package.json file instead.
45
+ def package_for_dependency(npm_json)
46
+ package_path = npm_json['path']
47
+ package_json_path = Pathname.new(package_path).join('package.json') unless package_path.nil?
48
+
49
+ if package_json_path.nil? || !package_json_path.exist?
50
+ # Ancient NPM versions did not have the "path" field. Resort to the old way of gathering
51
+ # the details, expecting them to be contained in the output of `npm list`.
52
+ NpmPackage.new(npm_json)
53
+ else
54
+ package_json = JSON.parse(package_json_path.read, max_nesting: false)
55
+ NpmPackage.new(npm_json, package_json)
56
+ end
57
+ end
58
+
59
+ def populate_groups(package_json)
60
+ package_json.groups.each do |group|
61
+ group.package_names.each do |package_name|
62
+ @packages.each_key do |identifier|
63
+ next unless identifier.name == package_name
64
+
65
+ dependency = @packages[identifier]
66
+ dependency.groups |= [group.name]
67
+ populate_child_groups(dependency, @packages)
68
+ end
69
+ end
70
+ end
71
+ end
72
+
73
+ def populate_child_groups(dependency, packages, populated_ids = [])
74
+ dependency.dependencies.each do |id|
75
+ next if populated_ids.include? id
76
+
77
+ populated_ids.push id
78
+ packages[id].groups |= dependency.groups
79
+ populate_child_groups(packages[id], packages, populated_ids)
80
+ end
81
+ end
82
+ end
83
+
84
+ def initialize(npm_json, package_json = npm_json)
85
+ @npm_json = npm_json
86
+ @json = package_json
87
+ @identifier = Identifier.from_hash(npm_json)
88
+ @dependencies = deps_from_json
89
+ super(@identifier.name,
90
+ @identifier.version,
91
+ description: package_json['description'],
92
+ homepage: package_json['homepage'],
93
+ authors: author_names,
94
+ spec_licenses: Package.license_names_from_standard_spec(package_json),
95
+ install_path: npm_json['path'],
96
+ children: @dependencies.map(&:name))
97
+ end
98
+
99
+ def author_names
100
+ names = []
101
+ if @json['author'].is_a?(Array)
102
+ # "author":["foo","bar"] isn't valid according to the NPM package.json schema, but can be found in the wild.
103
+ names += @json['author'].map { |a| author_name(a) }
104
+ else
105
+ names << author_name(@json['author']) unless @json['author'].nil?
106
+ end
107
+ names += @json['contributors'].map { |c| author_name(c) } if @json['contributors'].is_a?(Array)
108
+ names.compact.join(', ')
109
+ rescue TypeError
110
+ puts "Warning: Invalid author and/or contributors metadata found in package.json for #{@identifier}"
111
+ nil
112
+ end
113
+
114
+ def author_name(author)
115
+ if author.instance_of?(String)
116
+ author_name_from_combined(author)
117
+ else
118
+ author['name']
119
+ end
120
+ end
121
+
122
+ def author_name_from_combined(author)
123
+ matches = author.match(/^(.*?)\s*(<.*?>)?\s*(\(.*?\))?\s*$/)
124
+ matches[1]
125
+ end
126
+
127
+ def ==(other)
128
+ other.is_a?(NpmPackage) && @identifier == other.identifier
129
+ end
130
+
131
+ def to_s
132
+ @identifier.to_s
133
+ end
134
+
135
+ def package_manager
136
+ 'Npm'
137
+ end
138
+
139
+ def package_url
140
+ "https://www.npmjs.com/package/#{CGI.escape(name)}/v/#{CGI.escape(version)}"
141
+ end
142
+
143
+ private
144
+
145
+ def deps_from_json
146
+ @npm_json.fetch('dependencies', {}).values.map { |dep| Identifier.from_hash(dep) }.compact
147
+ end
148
+
149
+ class Identifier
150
+ attr_accessor :name, :version
151
+
152
+ def initialize(name, version)
153
+ @name = name
154
+ @version = version
155
+ end
156
+
157
+ def self.from_hash(hash)
158
+ name = hash['name']
159
+ version = hash['version']
160
+ return nil if name.nil? || name.empty? || version.nil? || version.empty?
161
+
162
+ Identifier.new(name, version)
163
+ end
164
+
165
+ def ==(other)
166
+ other.is_a?(Identifier) && @name == other.name && @version == other.version
167
+ end
168
+
169
+ def eql?(other)
170
+ self == other
171
+ end
172
+
173
+ def hash
174
+ [@name, @version].hash
175
+ end
176
+
177
+ def <=>(other)
178
+ sort_name = @name <=> other.name
179
+ sort_name.zero? ? @version <=> other.version : sort_name
180
+ end
181
+
182
+ def to_s
183
+ "#{@name} - #{@version}"
184
+ end
185
+ end
186
+
187
+ class Group
188
+ attr_accessor :name, :package_names
189
+
190
+ def initialize(name, hash)
191
+ @name = name
192
+ @package_names = hash.keys
193
+ end
194
+
195
+ def include?(identifier)
196
+ @package_names.include? identifier.name
197
+ end
198
+
199
+ def to_s
200
+ @name
201
+ end
202
+ end
203
+
204
+ class PackageJson
205
+ attr_reader :groups
206
+
207
+ DEPENDENCY_GROUPS = %w[dependencies devDependencies].freeze
208
+
209
+ def initialize(path)
210
+ json = JSON.parse(File.read(path), max_nesting: false)
211
+ @groups = DEPENDENCY_GROUPS.map { |name| Group.new(name, json.fetch(name, {})) }
212
+ end
213
+
214
+ def groups_for(identifier)
215
+ @groups.select { |g| g.include? identifier }.map(&:name)
216
+ end
217
+ end
218
+ end
219
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module LicenseFinder
4
+ class NugetPackage < Package
5
+ def package_manager
6
+ 'Nuget'
7
+ end
8
+
9
+ def package_url
10
+ "https://www.nuget.org/packages/#{CGI.escape(name)}/#{CGI.escape(version)}"
11
+ end
12
+ end
13
+ 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,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module LicenseFinder
4
+ class PNPMPackage < Package
5
+ def package_manager
6
+ 'PNPM'
7
+ end
8
+
9
+ def package_url
10
+ "https://www.npmjs.com/package/#{CGI.escape(name)}/v/#{CGI.escape(version)}"
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module LicenseFinder
4
+ class PubPackage < 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
+ 'Pub'
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module LicenseFinder
4
+ class RebarPackage < Package
5
+ def package_manager
6
+ 'Rebar'
7
+ end
8
+
9
+ def package_url
10
+ "https://hex.pm/packages/#{CGI.escape(name)}/#{CGI.escape(version)}"
11
+ end
12
+ end
13
+ 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,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module LicenseFinder
4
+ class YarnPackage < Package
5
+ def package_manager
6
+ 'Yarn'
7
+ end
8
+
9
+ def package_url
10
+ "https://yarn.pm/#{CGI.escape(name)}"
11
+ end
12
+ end
13
+ 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,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ module LicenseFinder
4
+ class Printer
5
+ attr_reader :padding
6
+
7
+ def initialize # :nodoc:
8
+ @base = nil
9
+ @mute = false
10
+ @padding = 0
11
+ @always_force = false
12
+ end
13
+
14
+ def say(message = '', color = nil, force_new_line = (message.to_s !~ /( |\t)\Z/))
15
+ buffer = prepare_message(message, *color)
16
+ buffer << "\n" if force_new_line && !message.to_s.end_with?("\n")
17
+
18
+ stdout.print(buffer)
19
+ stdout.flush
20
+ end
21
+
22
+ def prepare_message(message, *color)
23
+ spaces = ' ' * padding
24
+ spaces + set_color(message.to_s, *color)
25
+ end
26
+
27
+ def set_color(string, *) # :nodoc:
28
+ string
29
+ end
30
+
31
+ def padding=(value)
32
+ @padding = [0, value].max
33
+ end
34
+
35
+ def stdout
36
+ $stdout
37
+ end
38
+ end
39
+ 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,34 @@
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
+ @use_spdx_id = options[:use_spdx_id]
13
+ end
14
+
15
+ private
16
+
17
+ attr_reader :dependencies, :project_name, :use_spdx_id
18
+
19
+ def sorted_dependencies
20
+ dependencies.sort
21
+ end
22
+ end
23
+ end
24
+
25
+ require 'license_finder/reports/erb_report'
26
+ require 'license_finder/reports/csv_report'
27
+ require 'license_finder/reports/text_report'
28
+ require 'license_finder/reports/diff_report'
29
+ require 'license_finder/reports/merged_report'
30
+ require 'license_finder/reports/html_report'
31
+ require 'license_finder/reports/markdown_report'
32
+ require 'license_finder/reports/xml_report'
33
+ require 'license_finder/reports/json_report'
34
+ require 'license_finder/reports/junit_report'
@@ -0,0 +1,108 @@
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 approved_by approved_reason].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(&@use_spdx_id ? :standard_id : :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
+
99
+ def format_approved_by(dep)
100
+ dep.approved_manually? ? dep.manual_approval.who : ''
101
+ end
102
+
103
+ def format_approved_reason(dep)
104
+ dep.approved_manually? ? dep.manual_approval.why : ''
105
+ end
106
+
107
+ end
108
+ end
@@ -0,0 +1,29 @@
1
+ module LicenseFinder
2
+ class DiffReport < CsvReport
3
+ AVAILABLE_COLUMNS = AVAILABLE_COLUMNS + %w[status current_version previous_version project_paths]
4
+
5
+ def initialize(dependencies, options = {})
6
+ super(dependencies, options.merge(columns: build_columns(dependencies)))
7
+ end
8
+
9
+ def format_status(dep)
10
+ dep.status
11
+ end
12
+
13
+ def format_version(dep)
14
+ dep.version
15
+ end
16
+
17
+ def format_project_paths(dep)
18
+ dep.aggregate_paths.join(self.class::COMMA_SEP)
19
+ end
20
+
21
+ private
22
+
23
+ def build_columns(dependencies)
24
+ columns = %w[status name version licenses]
25
+ columns << 'project_paths' if dependencies.all?(&:merged_package?)
26
+ columns
27
+ end
28
+ end
29
+ end