gitlab-license_finder 6.14.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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