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,181 @@
1
+ # frozen_string_literal: false
2
+
3
+ module LicenseFinder
4
+ # Super-class for the different package managers
5
+ # (Bundler, NPM, Pip, etc.)
6
+ #
7
+ # For guidance on adding a new package manager use the shared behavior
8
+ #
9
+ # it_behaves_like "a PackageManager"
10
+ #
11
+ # Additional guidelines are:
12
+ #
13
+ # - implement #current_packages, to return a list of `Package`s this package manager is tracking
14
+ # - implement #possible_package_paths, an array of `Pathname`s which are the possible locations which contain a configuration file/folder indicating the package manager is in use.
15
+ # - implement(Optional) #package_management_command, string for invoking the package manager
16
+ # - implement(Optional) #prepare_command, string for fetching dependencies for package manager (runs when the --prepare flag is passed to license_finder)
17
+
18
+ class PackageManager
19
+ include LicenseFinder::SharedHelpers
20
+
21
+ class << self
22
+ def takes_priority_over
23
+ nil
24
+ end
25
+
26
+ def id
27
+ name.split('::').last.downcase
28
+ end
29
+ end
30
+
31
+ def installed?(logger = Core.default_logger)
32
+ if package_management_command.nil?
33
+ logger.debug self.class, 'no command defined' # TODO: comment me out
34
+ true
35
+ elsif command_exists?(package_management_command)
36
+ logger.debug self.class, 'is installed', color: :green
37
+ true
38
+ else
39
+ logger.info self.class, 'is not installed', color: :red
40
+ false
41
+ end
42
+ end
43
+
44
+ # see class description
45
+ def package_management_command
46
+ nil
47
+ end
48
+
49
+ # see class description
50
+ def prepare_command
51
+ nil
52
+ end
53
+
54
+ def command_exists?(command)
55
+ _stdout, _stderr, status =
56
+ if LicenseFinder::Platform.windows?
57
+ Cmd.run("where #{command}")
58
+ else
59
+ Cmd.run("which #{command}")
60
+ end
61
+
62
+ status.success?
63
+ end
64
+
65
+ def initialize(options = {})
66
+ @prepare_no_fail = options[:prepare_no_fail]
67
+ @logger = options[:logger] || Core.default_logger
68
+ @project_path = options[:project_path]
69
+ @log_directory = options[:log_directory]
70
+ @ignored_groups = options[:ignored_groups]
71
+ end
72
+
73
+ def active?
74
+ path = detected_package_path
75
+ path&.exist?
76
+ end
77
+
78
+ def project_root?
79
+ active?
80
+ end
81
+
82
+ def detected_package_path
83
+ possible_package_paths.find(&:exist?)
84
+ end
85
+
86
+ def prepare
87
+ if prepare_command
88
+ stdout, stderr, status = Dir.chdir(project_path) { Cmd.run(prepare_command) }
89
+ unless status.success?
90
+ log_errors stderr
91
+
92
+ error_message = "Prepare command '#{prepare_command}' failed\n#{stderr}"
93
+
94
+ error_message == error_message.concat("\n#{stdout}\n") if !stdout.nil? && !stdout.empty?
95
+
96
+ raise error_message unless @prepare_no_fail
97
+ end
98
+ else
99
+ logger.debug self.class, 'no prepare step provided', color: :red
100
+ end
101
+ end
102
+
103
+ def current_packages_with_relations
104
+ begin
105
+ packages = current_packages
106
+ rescue StandardError => e
107
+ raise e unless @prepare_no_fail
108
+
109
+ packages = []
110
+ end
111
+
112
+ packages.each do |parent|
113
+ parent.children.each do |child_name|
114
+ child = packages.detect { |child_package| child_package.name == child_name }
115
+ child.parents << parent.name if child
116
+ end
117
+ end
118
+ packages
119
+ end
120
+
121
+ private
122
+
123
+ attr_reader :logger, :project_path
124
+
125
+ def log_errors(stderr)
126
+ log_errors_with_cmd(prepare_command, stderr)
127
+ end
128
+
129
+ def log_errors_with_cmd(prep_cmd, stderr)
130
+ logger.info(prep_cmd, 'did not succeed.', color: :red)
131
+ logger.info(prep_cmd, stderr, color: :red)
132
+ log_to_file(prep_cmd, stderr)
133
+ end
134
+
135
+ def log_to_file(prep_cmd, contents)
136
+ FileUtils.mkdir_p @log_directory
137
+
138
+ # replace whitespace with underscores and remove slashes
139
+ log_file_name = package_management_command&.gsub(/\s/, '_')&.gsub(%r{/}, '')
140
+ log_file = File.join(@log_directory, "prepare_#{log_file_name || 'errors'}.log")
141
+
142
+ File.open(log_file, 'w') do |f|
143
+ f.write("Prepare command \"#{prep_cmd}\" failed with:\n")
144
+ f.write("#{contents}\n\n")
145
+ end
146
+ end
147
+ end
148
+ end
149
+
150
+ require 'license_finder/package_managers/bower'
151
+ require 'license_finder/package_managers/go_workspace'
152
+ require 'license_finder/package_managers/go_15vendorexperiment'
153
+ require 'license_finder/package_managers/go_dep'
154
+ require 'license_finder/package_managers/gvt'
155
+ require 'license_finder/package_managers/glide'
156
+ require 'license_finder/package_managers/govendor'
157
+ require 'license_finder/package_managers/go_modules'
158
+ require 'license_finder/package_managers/trash'
159
+ require 'license_finder/package_managers/bundler'
160
+ require 'license_finder/package_managers/npm'
161
+ require 'license_finder/package_managers/yarn'
162
+ require 'license_finder/package_managers/pip'
163
+ require 'license_finder/package_managers/pipenv'
164
+ require 'license_finder/package_managers/maven'
165
+ require 'license_finder/package_managers/mix'
166
+ require 'license_finder/package_managers/cocoa_pods'
167
+ require 'license_finder/package_managers/carthage'
168
+ require 'license_finder/package_managers/spm'
169
+ require 'license_finder/package_managers/gradle'
170
+ require 'license_finder/package_managers/rebar'
171
+ require 'license_finder/package_managers/erlangmk'
172
+ require 'license_finder/package_managers/nuget'
173
+ require 'license_finder/package_managers/dotnet'
174
+ require 'license_finder/package_managers/dep'
175
+ require 'license_finder/package_managers/conan'
176
+ require 'license_finder/package_managers/sbt'
177
+ require 'license_finder/package_managers/cargo'
178
+ require 'license_finder/package_managers/composer'
179
+ require 'license_finder/package_managers/conda'
180
+
181
+ require 'license_finder/package'
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+
5
+ module LicenseFinder
6
+ class Bower < PackageManager
7
+ def current_packages
8
+ bower_output.map do |package|
9
+ BowerPackage.new(package, logger: logger)
10
+ end
11
+ end
12
+
13
+ def package_management_command
14
+ 'bower'
15
+ end
16
+
17
+ def prepare_command
18
+ 'bower install'
19
+ end
20
+
21
+ def possible_package_paths
22
+ [project_path.join('bower.json')]
23
+ end
24
+
25
+ private
26
+
27
+ def bower_output
28
+ command = "#{package_management_command} list --json -l action --allow-root"
29
+ stdout, stderr, status = Dir.chdir(project_path) { Cmd.run(command) }
30
+ raise "Command '#{command}' failed to execute: #{stderr}" unless status.success?
31
+
32
+ JSON(stdout)
33
+ .fetch('dependencies', {})
34
+ .values
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,110 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler'
4
+ require 'securerandom'
5
+
6
+ module LicenseFinder
7
+ class Bundler < PackageManager
8
+ def initialize(options = {})
9
+ super
10
+ @ignored_groups = options[:ignored_groups]
11
+ @definition = options[:definition] # dependency injection for tests
12
+ end
13
+
14
+ def current_packages
15
+ logger.debug self.class, "including groups #{included_groups.inspect}"
16
+ details.map do |gem_detail, bundle_detail|
17
+ BundlerPackage.new(gem_detail, bundle_detail, logger: logger).tap do |package|
18
+ log_package_dependencies package
19
+ end
20
+ end
21
+ end
22
+
23
+ def package_management_command
24
+ 'bundle'
25
+ end
26
+
27
+ def prepare_command
28
+ ignored_groups_argument = !ignored_groups.empty? ? "--without #{ignored_groups.to_a.join(' ')}" : ''
29
+
30
+ gem_path = "lf-bundler-gems-#{SecureRandom.uuid}"
31
+ logger.info self.class, "Running bundle install for #{Dir.pwd} with path #{gem_path}", color: :blue
32
+
33
+ "bundle install #{ignored_groups_argument} --path #{gem_path}".strip
34
+ end
35
+
36
+ def possible_package_paths
37
+ [project_path.join(gemfile)]
38
+ end
39
+
40
+ private
41
+
42
+ attr_reader :ignored_groups
43
+
44
+ def definition
45
+ ENV['BUNDLE_GEMFILE'] = "#{project_path}/#{gemfile}"
46
+
47
+ @definition ||= ::Bundler::Definition.build(detected_package_path, lockfile_path, nil)
48
+ end
49
+
50
+ def details
51
+ gem_details.map do |gem_detail|
52
+ bundle_detail = bundler_details.detect { |bundler_detail| bundler_detail.name == gem_detail.name }
53
+ [gem_detail, bundle_detail]
54
+ end
55
+ end
56
+
57
+ def gem_details
58
+ return @gem_details if @gem_details
59
+
60
+ # clear gem paths before running specs_for
61
+ Gem.clear_paths
62
+ if bundler_config_path_found
63
+ ::Bundler.reset!
64
+ ::Bundler.configure
65
+ end
66
+ @gem_details = definition.specs_for(included_groups)
67
+ end
68
+
69
+ def bundler_details
70
+ @bundler_details ||= definition.dependencies
71
+ end
72
+
73
+ def included_groups
74
+ definition.groups - ignored_groups.map(&:to_sym)
75
+ end
76
+
77
+ def lockfile_path
78
+ project_path.join(lockfile)
79
+ end
80
+
81
+ def bundler_config_path_found
82
+ config_file = project_path.join('.bundle/config')
83
+
84
+ return false unless File.exist?(config_file)
85
+
86
+ content = File.readlines(config_file)
87
+ content.grep(/BUNDLE_PATH/).count.positive?
88
+ end
89
+
90
+ def log_package_dependencies(package)
91
+ dependencies = package.children
92
+ if dependencies.empty?
93
+ logger.debug self.class, format("package '%s' has no dependencies", package.name)
94
+ else
95
+ logger.debug self.class, format("package '%s' has dependencies:", package.name)
96
+ dependencies.each do |dep|
97
+ logger.debug self.class, format('- %s', dep)
98
+ end
99
+ end
100
+ end
101
+
102
+ def gemfile
103
+ File.basename(ENV['BUNDLE_GEMFILE'] || 'Gemfile')
104
+ end
105
+
106
+ def lockfile
107
+ "#{gemfile}.lock"
108
+ end
109
+ end
110
+ end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+
5
+ module LicenseFinder
6
+ class Cargo < PackageManager
7
+ def current_packages
8
+ cargo_output.map do |package|
9
+ path = Dir.glob("#{Dir.home}/.cargo/registry/src/**/#{package['name']}-#{package['version']}").first
10
+ CargoPackage.new(package, logger: logger, install_path: path)
11
+ end
12
+ end
13
+
14
+ def package_management_command
15
+ 'cargo'
16
+ end
17
+
18
+ def prepare_command
19
+ 'cargo fetch'
20
+ end
21
+
22
+ def possible_package_paths
23
+ [project_path.join('Cargo.lock'), project_path.join('Cargo.toml')]
24
+ end
25
+
26
+ private
27
+
28
+ def cargo_output
29
+ command = "#{package_management_command} metadata --format-version=1"
30
+
31
+ stdout, stderr, status = Dir.chdir(project_path) { Cmd.run(command) }
32
+ raise "Command '#{command}' failed to execute: #{stderr}" unless status.success?
33
+
34
+ JSON(stdout)
35
+ .fetch('packages', [])
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,68 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+
5
+ module LicenseFinder
6
+ class Carthage < PackageManager
7
+ class CarthageError < RuntimeError; end
8
+
9
+ def current_packages
10
+ cartfile.each_line.map do |line|
11
+ name, version = name_version_from_line line
12
+
13
+ CarthagePackage.new(
14
+ name,
15
+ version,
16
+ license_text(name),
17
+ logger: logger,
18
+ install_path: project_checkout(name)
19
+ )
20
+ end
21
+ end
22
+
23
+ def package_management_command
24
+ LicenseFinder::Platform.darwin? ? 'carthage' : nil
25
+ end
26
+
27
+ def possible_package_paths
28
+ [public_dependency_path]
29
+ end
30
+
31
+ private
32
+
33
+ def cartfile
34
+ if File.exist?(resolved_path)
35
+ @cartfile ||= IO.read(resolved_path)
36
+ else
37
+ raise CarthageError, 'No Cartfile.resolved found.
38
+ Please install your dependencies first.'
39
+ end
40
+ end
41
+
42
+ def public_dependency_path
43
+ project_path.join('Cartfile')
44
+ end
45
+
46
+ def resolved_path
47
+ project_path.join('Cartfile.resolved')
48
+ end
49
+
50
+ def project_checkout(name)
51
+ project_path.join('Carthage', 'Checkouts', name)
52
+ end
53
+
54
+ def license_text(name)
55
+ license_path = license_pattern(name).find { |f| File.exist?(f) }
56
+ license_path.nil? ? nil : IO.read(license_path)
57
+ end
58
+
59
+ def license_pattern(name)
60
+ checkout_path = project_checkout(name)
61
+ Dir.glob(checkout_path.join('LICENSE*'), File::FNM_CASEFOLD)
62
+ end
63
+
64
+ def name_version_from_line(cartfile_line)
65
+ cartfile_line.split(' ')[1, 2].map { |f| f.split('/').last.delete('"').gsub('.git', '') }
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,61 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+
5
+ module LicenseFinder
6
+ class CocoaPods < PackageManager
7
+ def current_packages
8
+ podfile = YAML.load_file(lockfile_path)
9
+
10
+ podfile['PODS'].map do |pod|
11
+ pod = pod.keys.first if pod.is_a?(Hash)
12
+
13
+ name, version = pod.scan(/(.*)\s\((.*)\)/).flatten
14
+
15
+ CocoaPodsPackage.new(
16
+ name,
17
+ version,
18
+ license_texts[name],
19
+ logger: logger
20
+ )
21
+ end
22
+ end
23
+
24
+ def package_management_command
25
+ LicenseFinder::Platform.darwin? ? 'pod' : nil
26
+ end
27
+
28
+ def possible_package_paths
29
+ [project_path.join('Podfile')]
30
+ end
31
+
32
+ private
33
+
34
+ def lockfile_path
35
+ project_path.join('Podfile.lock')
36
+ end
37
+
38
+ def license_texts
39
+ # package name => license text
40
+ @license_texts ||= read_plist(acknowledgements_path)['PreferenceSpecifiers']
41
+ .each_with_object({}) { |hash, memo| memo[hash['Title']] = hash['FooterText'] }
42
+ end
43
+
44
+ def acknowledgements_path
45
+ search_paths = ['Pods/Pods-acknowledgements.plist',
46
+ 'Pods/Target Support Files/Pods/Pods-acknowledgements.plist',
47
+ 'Pods/Target Support Files/Pods-*/Pods-*-acknowledgements.plist']
48
+
49
+ result = Dir[*search_paths.map { |path| File.join(project_path, path) }].first
50
+ raise "Found a Podfile but no Pods directory in #{project_path}. Try running pod install before running license_finder." if result.nil?
51
+
52
+ result
53
+ end
54
+
55
+ def read_plist(pathname)
56
+ transformed_pathname = pathname.gsub!(%r{[^0-9A-Za-z. \-'/]}, '')
57
+ transformed_pathname = pathname if transformed_pathname.nil?
58
+ JSON.parse(`plutil -convert json -o - '#{transformed_pathname}'`)
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,63 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+
5
+ module LicenseFinder
6
+ class Composer < PackageManager
7
+ def initialize(options = {})
8
+ super
9
+ @check_require_only = !!options[:composer_check_require_only]
10
+ end
11
+
12
+ def possible_package_paths
13
+ [project_path.join('composer.lock'), project_path.join('composer.json')]
14
+ end
15
+
16
+ def current_packages
17
+ dependency_list.map do |name, dependency|
18
+ path_command = "composer show #{name} -P"
19
+ stdout, _stderr, status = Dir.chdir(project_path) { Cmd.run(path_command) }
20
+
21
+ path = status.success? ? stdout.split(' ').last : ''
22
+ ComposerPackage.new(name, dependency['version'], spec_licenses: dependency['license'], install_path: path)
23
+ end
24
+ end
25
+
26
+ def prepare
27
+ _stdout, stderr, status = Dir.chdir(project_path) { Cmd.run(prepare_command) }
28
+ return if status.success?
29
+
30
+ log_errors stderr
31
+ raise "Prepare command '#{Composer.prepare_command}' failed" unless @prepare_no_fail
32
+ end
33
+
34
+ def package_management_command
35
+ 'composer'
36
+ end
37
+
38
+ def prepare_command
39
+ 'composer install --no-plugins --no-scripts --ignore-platform-reqs --no-interaction'
40
+ end
41
+
42
+ def package_path
43
+ project_path.join('composer.json')
44
+ end
45
+
46
+ def lockfile_path
47
+ project_path.join('composer.lock')
48
+ end
49
+
50
+ def dependency_list
51
+ json ||= composer_json
52
+ json.fetch('dependencies', {}).reject { |_, d| d.is_a?(String) }
53
+ end
54
+
55
+ def composer_json
56
+ command = "composer licenses --format=json#{@check_require_only ? ' --no-dev' : ''}"
57
+ stdout, stderr, status = Dir.chdir(project_path) { Cmd.run(command) }
58
+ raise "Command '#{command}' failed to execute: #{stderr}" unless status.success?
59
+
60
+ JSON(stdout)
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'license_finder/package_utils/conan_info_parser'
4
+
5
+ module LicenseFinder
6
+ class Conan < PackageManager
7
+ def possible_package_paths
8
+ [project_path.join('conanfile.txt')]
9
+ end
10
+
11
+ def current_packages
12
+ install_command = 'conan install .'
13
+ info_command = 'conan info .'
14
+ Dir.chdir(project_path) { Cmd.run(install_command) }
15
+ info_output, _stderr, _status = Dir.chdir(project_path) { Cmd.run(info_command) }
16
+
17
+ info_parser = ConanInfoParser.new
18
+
19
+ deps = info_parser.parse(info_output)
20
+ deps.map do |dep|
21
+ name, version = dep['name'].split('@').first.split('/')
22
+ url = dep['URL']
23
+ license_file_path = Dir.glob("#{project_path}/licenses/#{name}/**/LICENSE*").first
24
+ ConanPackage.new(name, version, File.open(license_file_path).read, url) unless name == 'PROJECT'
25
+ end.compact
26
+ end
27
+ end
28
+ end