gitlab-license_finder 6.14.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (180) hide show
  1. checksums.yaml +7 -0
  2. data/.force-build +0 -0
  3. data/.gitignore +13 -0
  4. data/.rspec +1 -0
  5. data/.rubocop.yml +70 -0
  6. data/CHANGELOG.md +981 -0
  7. data/CONTRIBUTING.md +121 -0
  8. data/Dockerfile +249 -0
  9. data/Gemfile +2 -0
  10. data/LICENSE +22 -0
  11. data/README.md +555 -0
  12. data/Rakefile +77 -0
  13. data/TODO.md +12 -0
  14. data/VERSION +1 -0
  15. data/appveyor.yml +21 -0
  16. data/bin/license_finder +6 -0
  17. data/bin/license_finder_pip.py +43 -0
  18. data/ci/pipelines/pull-request.yml.erb +141 -0
  19. data/ci/pipelines/release.yml.erb +200 -0
  20. data/ci/scripts/containerize-tests.sh +14 -0
  21. data/ci/scripts/pushscript.sh +32 -0
  22. data/ci/scripts/run-rubocop.sh +15 -0
  23. data/ci/scripts/run-tests.sh +24 -0
  24. data/ci/scripts/test.ps1 +81 -0
  25. data/ci/scripts/updateChangelog.sh +84 -0
  26. data/ci/tasks/build-and-push-gem.yml +10 -0
  27. data/ci/tasks/build-windows.yml +6 -0
  28. data/ci/tasks/build.yml +16 -0
  29. data/ci/tasks/rubocop.yml +15 -0
  30. data/ci/tasks/run-tests.yml +10 -0
  31. data/ci/tasks/update-changelog.yml +18 -0
  32. data/dlf +12 -0
  33. data/examples/Gemfile +4 -0
  34. data/examples/custom_erb_template.rb +24 -0
  35. data/examples/extract_license_data.rb +63 -0
  36. data/examples/sample_template.erb +7 -0
  37. data/lib/license_finder/cli/approvals.rb +28 -0
  38. data/lib/license_finder/cli/base.rb +107 -0
  39. data/lib/license_finder/cli/dependencies.rb +44 -0
  40. data/lib/license_finder/cli/ignored_dependencies.rb +32 -0
  41. data/lib/license_finder/cli/ignored_groups.rb +32 -0
  42. data/lib/license_finder/cli/inherited_decisions.rb +50 -0
  43. data/lib/license_finder/cli/licenses.rb +26 -0
  44. data/lib/license_finder/cli/main.rb +221 -0
  45. data/lib/license_finder/cli/makes_decisions.rb +38 -0
  46. data/lib/license_finder/cli/patched_thor.rb +33 -0
  47. data/lib/license_finder/cli/permitted_licenses.rb +32 -0
  48. data/lib/license_finder/cli/project_name.rb +32 -0
  49. data/lib/license_finder/cli/restricted_licenses.rb +32 -0
  50. data/lib/license_finder/cli.rb +20 -0
  51. data/lib/license_finder/configuration.rb +186 -0
  52. data/lib/license_finder/core.rb +118 -0
  53. data/lib/license_finder/decision_applier.rb +70 -0
  54. data/lib/license_finder/decisions.rb +312 -0
  55. data/lib/license_finder/decisions_factory.rb +13 -0
  56. data/lib/license_finder/diff.rb +51 -0
  57. data/lib/license_finder/license/any_matcher.rb +15 -0
  58. data/lib/license_finder/license/definitions.rb +366 -0
  59. data/lib/license_finder/license/header_matcher.rb +17 -0
  60. data/lib/license_finder/license/matcher.rb +24 -0
  61. data/lib/license_finder/license/none_matcher.rb +11 -0
  62. data/lib/license_finder/license/template.rb +19 -0
  63. data/lib/license_finder/license/templates/0BSD.txt +10 -0
  64. data/lib/license_finder/license/templates/Apache1_1.txt +16 -0
  65. data/lib/license_finder/license/templates/Apache2.txt +172 -0
  66. data/lib/license_finder/license/templates/BSD.txt +24 -0
  67. data/lib/license_finder/license/templates/CC01.txt +30 -0
  68. data/lib/license_finder/license/templates/CDDL1.txt +131 -0
  69. data/lib/license_finder/license/templates/EPL1.txt +86 -0
  70. data/lib/license_finder/license/templates/GPLv2.txt +339 -0
  71. data/lib/license_finder/license/templates/GPLv3.txt +674 -0
  72. data/lib/license_finder/license/templates/ISC.txt +2 -0
  73. data/lib/license_finder/license/templates/LGPL.txt +165 -0
  74. data/lib/license_finder/license/templates/LGPL2_1.txt +169 -0
  75. data/lib/license_finder/license/templates/MIT.txt +9 -0
  76. data/lib/license_finder/license/templates/MPL1_1.txt +469 -0
  77. data/lib/license_finder/license/templates/MPL2.txt +373 -0
  78. data/lib/license_finder/license/templates/NewBSD.txt +21 -0
  79. data/lib/license_finder/license/templates/OFL.txt +91 -0
  80. data/lib/license_finder/license/templates/Python.txt +47 -0
  81. data/lib/license_finder/license/templates/Ruby.txt +52 -0
  82. data/lib/license_finder/license/templates/SimplifiedBSD.txt +19 -0
  83. data/lib/license_finder/license/templates/WTFPL.txt +14 -0
  84. data/lib/license_finder/license/templates/Zlib.txt +17 -0
  85. data/lib/license_finder/license/text.rb +45 -0
  86. data/lib/license_finder/license.rb +117 -0
  87. data/lib/license_finder/license_aggregator.rb +59 -0
  88. data/lib/license_finder/logger.rb +69 -0
  89. data/lib/license_finder/package.rb +202 -0
  90. data/lib/license_finder/package_delta.rb +61 -0
  91. data/lib/license_finder/package_manager.rb +181 -0
  92. data/lib/license_finder/package_managers/bower.rb +37 -0
  93. data/lib/license_finder/package_managers/bundler.rb +110 -0
  94. data/lib/license_finder/package_managers/cargo.rb +38 -0
  95. data/lib/license_finder/package_managers/carthage.rb +68 -0
  96. data/lib/license_finder/package_managers/cocoa_pods.rb +61 -0
  97. data/lib/license_finder/package_managers/composer.rb +63 -0
  98. data/lib/license_finder/package_managers/conan.rb +28 -0
  99. data/lib/license_finder/package_managers/conda.rb +131 -0
  100. data/lib/license_finder/package_managers/dep.rb +43 -0
  101. data/lib/license_finder/package_managers/dotnet.rb +83 -0
  102. data/lib/license_finder/package_managers/erlangmk.rb +50 -0
  103. data/lib/license_finder/package_managers/glide.rb +36 -0
  104. data/lib/license_finder/package_managers/go_15vendorexperiment.rb +87 -0
  105. data/lib/license_finder/package_managers/go_dep.rb +80 -0
  106. data/lib/license_finder/package_managers/go_modules.rb +93 -0
  107. data/lib/license_finder/package_managers/go_workspace.rb +116 -0
  108. data/lib/license_finder/package_managers/govendor.rb +73 -0
  109. data/lib/license_finder/package_managers/gradle.rb +99 -0
  110. data/lib/license_finder/package_managers/gvt.rb +69 -0
  111. data/lib/license_finder/package_managers/maven.rb +65 -0
  112. data/lib/license_finder/package_managers/mix.rb +131 -0
  113. data/lib/license_finder/package_managers/npm.rb +57 -0
  114. data/lib/license_finder/package_managers/nuget.rb +154 -0
  115. data/lib/license_finder/package_managers/pip.rb +70 -0
  116. data/lib/license_finder/package_managers/pipenv.rb +63 -0
  117. data/lib/license_finder/package_managers/rebar.rb +65 -0
  118. data/lib/license_finder/package_managers/sbt.rb +50 -0
  119. data/lib/license_finder/package_managers/spm.rb +93 -0
  120. data/lib/license_finder/package_managers/trash.rb +43 -0
  121. data/lib/license_finder/package_managers/yarn.rb +107 -0
  122. data/lib/license_finder/package_utils/activation.rb +40 -0
  123. data/lib/license_finder/package_utils/conan_info_parser.rb +77 -0
  124. data/lib/license_finder/package_utils/gradle_dependency_finder.rb +15 -0
  125. data/lib/license_finder/package_utils/license_files.rb +41 -0
  126. data/lib/license_finder/package_utils/licensing.rb +39 -0
  127. data/lib/license_finder/package_utils/maven_dependency_finder.rb +15 -0
  128. data/lib/license_finder/package_utils/notice_files.rb +40 -0
  129. data/lib/license_finder/package_utils/possible_license_file.rb +27 -0
  130. data/lib/license_finder/package_utils/pypi.rb +41 -0
  131. data/lib/license_finder/package_utils/sbt_dependency_finder.rb +15 -0
  132. data/lib/license_finder/packages/bower_package.rb +42 -0
  133. data/lib/license_finder/packages/bundler_package.rb +33 -0
  134. data/lib/license_finder/packages/cargo_package.rb +28 -0
  135. data/lib/license_finder/packages/carthage_package.rb +18 -0
  136. data/lib/license_finder/packages/cocoa_pods_package.rb +22 -0
  137. data/lib/license_finder/packages/composer_package.rb +13 -0
  138. data/lib/license_finder/packages/conan_package.rb +23 -0
  139. data/lib/license_finder/packages/conda_package.rb +74 -0
  140. data/lib/license_finder/packages/erlangmk_package.rb +114 -0
  141. data/lib/license_finder/packages/go_package.rb +32 -0
  142. data/lib/license_finder/packages/gradle_package.rb +30 -0
  143. data/lib/license_finder/packages/manual_package.rb +27 -0
  144. data/lib/license_finder/packages/maven_package.rb +27 -0
  145. data/lib/license_finder/packages/merged_package.rb +44 -0
  146. data/lib/license_finder/packages/mix_package.rb +13 -0
  147. data/lib/license_finder/packages/npm_package.rb +171 -0
  148. data/lib/license_finder/packages/nuget_package.rb +13 -0
  149. data/lib/license_finder/packages/pip_package.rb +50 -0
  150. data/lib/license_finder/packages/rebar_package.rb +13 -0
  151. data/lib/license_finder/packages/sbt_package.rb +22 -0
  152. data/lib/license_finder/packages/spm_package.rb +18 -0
  153. data/lib/license_finder/packages/yarn_package.rb +13 -0
  154. data/lib/license_finder/platform.rb +15 -0
  155. data/lib/license_finder/project_finder.rb +62 -0
  156. data/lib/license_finder/report.rb +33 -0
  157. data/lib/license_finder/reports/csv_report.rb +99 -0
  158. data/lib/license_finder/reports/diff_report.rb +29 -0
  159. data/lib/license_finder/reports/erb_report.rb +58 -0
  160. data/lib/license_finder/reports/html_report.rb +13 -0
  161. data/lib/license_finder/reports/json_report.rb +30 -0
  162. data/lib/license_finder/reports/junit_report.rb +19 -0
  163. data/lib/license_finder/reports/markdown_report.rb +9 -0
  164. data/lib/license_finder/reports/merged_report.rb +16 -0
  165. data/lib/license_finder/reports/templates/bootstrap.css +9 -0
  166. data/lib/license_finder/reports/templates/html_report.erb +113 -0
  167. data/lib/license_finder/reports/templates/junit_report.erb +41 -0
  168. data/lib/license_finder/reports/templates/markdown_report.erb +49 -0
  169. data/lib/license_finder/reports/templates/xml_report.erb +19 -0
  170. data/lib/license_finder/reports/text_report.rb +12 -0
  171. data/lib/license_finder/reports/xml_report.rb +19 -0
  172. data/lib/license_finder/scanner.rb +83 -0
  173. data/lib/license_finder/shared_helpers/cmd.rb +13 -0
  174. data/lib/license_finder/shared_helpers/common_path.rb +29 -0
  175. data/lib/license_finder/version.rb +6 -0
  176. data/lib/license_finder.rb +14 -0
  177. data/license_finder.gemspec +72 -0
  178. data/release/instructions.md +8 -0
  179. data/swift-all-keys.asc +240 -0
  180. 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,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module LicenseFinder
4
+ class ComposerPackage < Package
5
+ def package_manager
6
+ 'Composer'
7
+ end
8
+
9
+ def package_url
10
+ "https://packagist.org/packages/#{CGI.escape(name)}##{CGI.escape(version)}"
11
+ end
12
+ end
13
+ 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