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,159 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rexml/document'
4
+ require 'zip'
5
+
6
+ module LicenseFinder
7
+ class Nuget < PackageManager
8
+ class Assembly
9
+ attr_reader :name, :path
10
+
11
+ def initialize(path, name)
12
+ @path = path
13
+ @name = name
14
+ end
15
+
16
+ def dependencies
17
+ xml = REXML::Document.new(File.read(path.join('packages.config')))
18
+ packages = REXML::XPath.match(xml, '//package')
19
+ packages.map do |p|
20
+ attrs = p.attributes
21
+ Dependency.new(attrs['id'], attrs['version'], name)
22
+ end
23
+ end
24
+ end
25
+
26
+ Dependency = Struct.new(:name, :version, :assembly)
27
+
28
+ def possible_package_paths
29
+ path = project_path.join('vendor/*.nupkg')
30
+ nuget_dir = Dir[path].map { |pkg| File.dirname(pkg) }.uniq
31
+
32
+ # Presence of a .sln is a good indicator for a dotnet solution
33
+ # cf.: https://docs.microsoft.com/en-us/nuget/tools/cli-ref-restore#remarks
34
+ path = project_path.join('*.sln')
35
+ solution_file = Dir[path].first
36
+
37
+ possible_paths = [project_path.join('packages.config'), project_path.join('.nuget')]
38
+ possible_paths.unshift(Pathname(solution_file)) unless solution_file.nil?
39
+ possible_paths.unshift(Pathname(nuget_dir.first)) unless nuget_dir.empty?
40
+ possible_paths
41
+ end
42
+
43
+ def assemblies
44
+ Dir.glob(project_path.join('**', 'packages.config'), File::FNM_DOTMATCH).map do |d|
45
+ path = Pathname.new(d).dirname
46
+ name = path.basename.to_s
47
+ Assembly.new path, name
48
+ end
49
+ end
50
+
51
+ def current_packages
52
+ dependencies.each_with_object({}) do |dep, memo|
53
+ licenses = license_urls(dep)
54
+ licenses&.map! do |license|
55
+ license.gsub('https://licenses.nuget.org/', '')
56
+ end
57
+
58
+ path = Dir.glob("#{Dir.home}/.nuget/packages/#{dep.name.downcase}/#{dep.version}").first
59
+
60
+ memo[dep.name] ||= NugetPackage.new(dep.name, dep.version, spec_licenses: licenses, install_path: path)
61
+ memo[dep.name].groups << dep.assembly unless memo[dep.name].groups.include? dep.assembly
62
+ end.values
63
+ end
64
+
65
+ def license_urls(dep)
66
+ files = Dir["**/#{dep.name}.#{dep.version}.nupkg"]
67
+
68
+ return nil if files.empty?
69
+
70
+ file = files.first
71
+ Zip::File.open file do |zipfile|
72
+ content = zipfile.read("#{dep.name}.nuspec")
73
+ Nuget.nuspec_license_urls(content)
74
+ end
75
+ end
76
+
77
+ def dependencies
78
+ assemblies.flat_map(&:dependencies)
79
+ end
80
+
81
+ def nuget_binary
82
+ legacy_vcproj = Dir['**/*.vcproj'].any?
83
+
84
+ if legacy_vcproj
85
+ '/usr/local/bin/nugetv3.5.0.exe'
86
+ else
87
+ '/usr/local/bin/nuget.exe'
88
+ end
89
+ end
90
+
91
+ def package_management_command
92
+ return 'nuget' if LicenseFinder::Platform.windows?
93
+
94
+ "mono #{nuget_binary}"
95
+ end
96
+
97
+ def prepare
98
+ Dir.chdir(project_path) do
99
+ cmd = prepare_command
100
+ stdout, stderr, status = Cmd.run(cmd)
101
+ return if status.success?
102
+
103
+ log_errors stderr
104
+
105
+ if stderr.include?('-PackagesDirectory')
106
+ logger.info cmd, 'trying fallback prepare command', color: :magenta
107
+
108
+ cmd = "#{cmd} -PackagesDirectory /#{Dir.home}/.nuget/packages"
109
+ stdout, stderr, status = Cmd.run(cmd)
110
+ return if status.success?
111
+
112
+ log_errors_with_cmd(cmd, stderr)
113
+ end
114
+
115
+ error_message = "Prepare command '#{cmd}' failed\n#{stderr}"
116
+ error_message += "\n#{stdout}\n" if !stdout.nil? && !stdout.empty?
117
+ raise error_message unless @prepare_no_fail
118
+ end
119
+ end
120
+
121
+ def prepare_command
122
+ cmd = package_management_command
123
+ sln_files = Dir['*.sln']
124
+ cmds = []
125
+ if sln_files.count > 1
126
+ sln_files.each do |sln|
127
+ cmds << "#{cmd} restore #{sln}"
128
+ end
129
+ else
130
+ cmds << "#{cmd} restore"
131
+ end
132
+
133
+ cmds.join(' && ')
134
+ end
135
+
136
+ def installed?(logger = Core.default_logger)
137
+ _stdout, _stderr, status = Cmd.run(nuget_check)
138
+ if status.success?
139
+ logger.debug self.class, 'is installed', color: :green
140
+ else
141
+ logger.info self.class, 'is not installed', color: :red
142
+ end
143
+ status.success?
144
+ end
145
+
146
+ def nuget_check
147
+ return 'where nuget' if LicenseFinder::Platform.windows?
148
+
149
+ "which mono && ls #{nuget_binary}"
150
+ end
151
+
152
+ def self.nuspec_license_urls(specfile_content)
153
+ xml = REXML::Document.new(specfile_content)
154
+ REXML::XPath.match(xml, '//metadata//licenseUrl')
155
+ .map(&:get_text)
156
+ .map(&:to_s)
157
+ end
158
+ end
159
+ end
@@ -0,0 +1,70 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+
5
+ module LicenseFinder
6
+ class Pip < PackageManager
7
+ DEFAULT_VERSION = '3'
8
+
9
+ def initialize(options = {})
10
+ super
11
+ @requirements_path = options[:pip_requirements_path] || Pathname('requirements.txt')
12
+ @python_version = options[:python_version] || DEFAULT_VERSION
13
+ raise "Invalid python version \'#{@python_version}\'. Valid versions are '2' or '3'." unless %w[2 3].include?(@python_version)
14
+ end
15
+
16
+ def current_packages
17
+ pip_output.map do |name, version, children, location|
18
+ PipPackage.new(
19
+ name,
20
+ version,
21
+ PyPI.definition(name, version),
22
+ logger: logger,
23
+ children: children,
24
+ install_path: Pathname(location).join(name)
25
+ )
26
+ end
27
+ end
28
+
29
+ def package_management_command
30
+ "pip#{@python_version}"
31
+ end
32
+
33
+ def prepare_command
34
+ "pip#{@python_version} install"
35
+ end
36
+
37
+ def prepare
38
+ prep_cmd = "#{prepare_command} -r #{@requirements_path}"
39
+ _stdout, stderr, status = Dir.chdir(project_path) { Cmd.run(prep_cmd) }
40
+ return if status.success?
41
+
42
+ log_errors stderr
43
+ raise "Prepare command '#{prep_cmd}' failed" unless @prepare_no_fail
44
+ end
45
+
46
+ def possible_package_paths
47
+ if project_path.nil?
48
+ [@requirements_path]
49
+ else
50
+ [project_path.join(@requirements_path)]
51
+ end
52
+ end
53
+
54
+ private
55
+
56
+ def pip_output
57
+ command = "python#{@python_version == '2' ? '' : '3'} #{LicenseFinder::BIN_PATH.join('license_finder_pip.py')} #{detected_package_path}"
58
+ stdout, stderr, status = Cmd.run(command)
59
+
60
+ if status.success?
61
+ JSON(stdout).map do |package|
62
+ package.values_at('name', 'version', 'dependencies', 'location')
63
+ end
64
+ else
65
+ log_errors "LicenseFinder command '#{command}' failed:\n\t#{stderr}"
66
+ []
67
+ end
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,63 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+ require 'license_finder/package_utils/pypi'
5
+
6
+ module LicenseFinder
7
+ class Pipenv < PackageManager
8
+ def initialize(options = {})
9
+ super
10
+ @lockfile = Pathname('Pipfile.lock')
11
+ end
12
+
13
+ def current_packages
14
+ @current_packages ||=
15
+ begin
16
+ packages = {}
17
+ each_dependency(groups: allowed_groups) do |name, data, group|
18
+ version = canonicalize(data['version'] || 'unknown')
19
+ package = packages.fetch(key_for(name, version)) do |key|
20
+ packages[key] = build_package_for(name, version)
21
+ end
22
+ package.groups << group
23
+ end
24
+ packages.values
25
+ end
26
+ end
27
+
28
+ def possible_package_paths
29
+ project_path ? [project_path.join(@lockfile)] : [@lockfile]
30
+ end
31
+
32
+ private
33
+
34
+ def each_dependency(groups: [])
35
+ dependencies = JSON.parse(IO.read(detected_package_path))
36
+ groups.each do |group|
37
+ dependencies[group].each do |name, data|
38
+ yield name, data, group
39
+ end
40
+ end
41
+ end
42
+
43
+ def canonicalize(version)
44
+ version.sub(/^==/, '')
45
+ end
46
+
47
+ def build_package_for(name, version)
48
+ PipPackage.new(name, version, PyPI.definition(name, version))
49
+ end
50
+
51
+ def key_for(name, version)
52
+ "#{name}-#{version}"
53
+ end
54
+
55
+ def allowed_groups
56
+ %w[default develop] - ignored_groups.to_a
57
+ end
58
+
59
+ def ignored_groups
60
+ @ignored_groups || []
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,126 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+ require 'tempfile'
5
+
6
+ module LicenseFinder
7
+ class PNPM < PackageManager
8
+ def initialize(options = {})
9
+ super
10
+ @pnpm_options = options[:pnpm_options]
11
+ end
12
+
13
+ SHELL_COMMAND = 'pnpm licenses list --json --long'
14
+
15
+ def possible_package_paths
16
+ [project_path.join('pnpm-lock.yaml')]
17
+ end
18
+
19
+ def self.takes_priority_over
20
+ NPM
21
+ end
22
+
23
+ def current_packages
24
+ # check if the minimum version of PNPM is met
25
+ raise 'The minimum PNPM version is not met, requires 7.17.0 or later' unless supported_pnpm?
26
+
27
+ # check if the project directory has workspace file
28
+ cmd = PNPM::SHELL_COMMAND.to_s
29
+ cmd += ' --no-color'
30
+ cmd += ' --recursive' unless project_has_workspaces == false
31
+ cmd += " --dir #{project_path}" unless project_path.nil?
32
+ cmd += " #{@pnpm_options}" unless @pnpm_options.nil?
33
+
34
+ stdout, stderr, status = Cmd.run(cmd)
35
+ raise "Command '#{cmd}' failed to execute: #{stderr}" unless status.success?
36
+
37
+ json_objects = JSON.parse(stdout)
38
+ get_pnpm_packages(json_objects)
39
+ end
40
+
41
+ def get_pnpm_packages(json_objects)
42
+ packages = []
43
+ incompatible_packages = []
44
+
45
+ json_objects.map do |_, value|
46
+ value.each do |pkg|
47
+ name = pkg['name']
48
+
49
+ if pkg['version']
50
+ version = pkg['version']
51
+ elsif pkg['versions']
52
+ version = pkg['versions'][0]
53
+ end
54
+
55
+ license = pkg['license']
56
+ homepage = pkg['vendorUrl']
57
+ author = pkg['vendorName']
58
+ module_path = pkg['path']
59
+
60
+ package = PNPMPackage.new(
61
+ name,
62
+ version,
63
+ spec_licenses: [license],
64
+ homepage: homepage,
65
+ authors: author,
66
+ install_path: module_path
67
+ )
68
+ packages << package
69
+ end
70
+ end
71
+
72
+ packages + incompatible_packages.uniq
73
+ end
74
+
75
+ def package_management_command
76
+ 'pnpm'
77
+ end
78
+
79
+ def prepare_command
80
+ 'pnpm install --no-lockfile --ignore-scripts'
81
+ end
82
+
83
+ def prepare
84
+ prep_cmd = "#{prepare_command}#{production_flag}"
85
+ _stdout, stderr, status = Dir.chdir(project_path) { Cmd.run(prep_cmd) }
86
+
87
+ return if status.success?
88
+
89
+ log_errors stderr
90
+ raise "Prepare command '#{prep_cmd}' failed" unless @prepare_no_fail
91
+ end
92
+
93
+ private
94
+
95
+ def project_has_workspaces
96
+ Dir.chdir(project_path) do
97
+ return File.file?('pnpm-workspace.yaml')
98
+ end
99
+ end
100
+
101
+ # PNPM introduced the licenses command in 7.17.0
102
+ def supported_pnpm?
103
+ Dir.chdir(project_path) do
104
+ version_string, stderr_str, status = Cmd.run('pnpm --version')
105
+ raise "Command 'pnpm -v' failed to execute: #{stderr_str}" unless status.success?
106
+
107
+ version = version_string.split('.').map(&:to_i)
108
+ major = version[0]
109
+ minor = version[1]
110
+ patch = version[1]
111
+
112
+ return true if major > 7
113
+ return true if major == 7 && minor > 17
114
+ return true if major == 7 && minor == 17 && patch >= 0
115
+
116
+ return false
117
+ end
118
+ end
119
+
120
+ def production_flag
121
+ return '' if @ignored_groups.nil?
122
+
123
+ @ignored_groups.include?('devDependencies') ? ' --prod' : ''
124
+ end
125
+ end
126
+ end
@@ -0,0 +1,86 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+ require 'yaml'
5
+
6
+ module LicenseFinder
7
+ class Pub < PackageManager
8
+ class PubError < RuntimeError; end
9
+
10
+ def current_packages
11
+ unless File.exist?('pubspec.lock')
12
+ raise PubError, "No checked-out Pub packages found.
13
+ Please install your dependencies first."
14
+ end
15
+
16
+ if ENV['PUB_CACHE'].nil? || ENV['PUB_CACHE'].eql?('')
17
+ raise PubError, 'While PUB_CACHE environment variable is empty, retrieving package licenses is impossible. Please set the PUB_CACHE env variable (default: ~/.pub)'
18
+ end
19
+
20
+ stdout, _stderr, _status = Cmd.run('flutter pub deps --json')
21
+ yaml_deps = JSON.parse(stdout)
22
+ yaml_deps['packages'].map do |dependency|
23
+ package_name = dependency['name']
24
+ subpath = "#{dependency['name']}-#{dependency['version']}"
25
+ package_version = dependency['version']
26
+
27
+ project_repo = dependency['source'] == 'git' ? Pathname("#{ENV['PUB_CACHE']}/git/#{dependency['name']}-*/") : Pathname("#{ENV['PUB_CACHE']}/hosted/pub.dartlang.org/#{subpath}")
28
+
29
+ homepage = read_repository_home(project_repo)
30
+ homepage = "https://pub.dev/packages/#{package_name}" if homepage.nil? || homepage.empty?
31
+ PubPackage.new(
32
+ package_name,
33
+ package_version,
34
+ license_text(project_repo),
35
+ logger: logger,
36
+ install_path: project_repo,
37
+ homepage: homepage
38
+ )
39
+ end
40
+ end
41
+
42
+ def possible_package_paths
43
+ [project_path.join('pubspec.lock')]
44
+ end
45
+
46
+ def package_management_command
47
+ 'flutter'
48
+ end
49
+
50
+ def prepare_command
51
+ 'flutter pub get'
52
+ end
53
+
54
+ def prepare
55
+ prep_cmd = "#{prepare_command} #{production_flag}"
56
+ _stdout, stderr, status = Dir.chdir(project_path) { Cmd.run(prep_cmd) }
57
+
58
+ return if status.success?
59
+
60
+ log_errors stderr
61
+ raise "Prepare command '#{prep_cmd}' failed" unless @prepare_no_fail
62
+ end
63
+
64
+ private
65
+
66
+ def license_text(subpath)
67
+ license_path = license_pattern(subpath).find { |f| File.exist?(f) }
68
+ license_path.nil? ? nil : IO.read(license_path)
69
+ end
70
+
71
+ def license_pattern(subpath)
72
+ Dir.glob(subpath.join('LICENSE*'), File::FNM_CASEFOLD)
73
+ end
74
+
75
+ def production_flag
76
+ return '' if @ignored_groups.nil?
77
+
78
+ @ignored_groups.include?('devDependencies') ? '' : 'no-'
79
+ end
80
+
81
+ def read_repository_home(project_repo)
82
+ package_yaml = project_repo.join('pubspec.yaml')
83
+ YAML.load(IO.read(package_yaml))['repository'] if Dir.exist?(project_repo) && File.exist?(package_yaml)
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,65 @@
1
+ # frozen_string_literal: true
2
+
3
+ module LicenseFinder
4
+ class Rebar < PackageManager
5
+ def initialize(options = {})
6
+ super
7
+ @command = options[:rebar_command] || package_management_command
8
+ @deps_path = Pathname(options[:rebar_deps_dir] || File.join(project_path, '_build/default/lib'))
9
+ end
10
+
11
+ def current_packages
12
+ rebar_deps.map do |name, version|
13
+ licenses, homepage = dep_info(name)
14
+ RebarPackage.new(
15
+ name,
16
+ version,
17
+ install_path: @deps_path.join(name),
18
+ homepage: homepage,
19
+ spec_licenses: licenses.nil? ? [] : [licenses],
20
+ logger: logger
21
+ )
22
+ end
23
+ end
24
+
25
+ def package_management_command
26
+ 'rebar3'
27
+ end
28
+
29
+ def possible_package_paths
30
+ [project_path.join('rebar.config')]
31
+ end
32
+
33
+ private
34
+
35
+ def rebar_deps
36
+ command = "#{@command} tree"
37
+ stdout, stderr, status = Dir.chdir(project_path) { Cmd.run(command) }
38
+ raise "Command '#{command}' failed to execute: #{stderr}" unless status.success?
39
+
40
+ stdout
41
+ .each_line
42
+ .reject { |line| line.start_with?('=') || line.include?('project app') }
43
+ .map do |line|
44
+ matches = line.match(/(?<name>\w+)─(?<version>\S+)\s*/)
45
+ [matches[:name], matches[:version]] if matches
46
+ end.compact
47
+ end
48
+
49
+ def dep_info(name)
50
+ command = "#{@command} pkgs #{name}"
51
+ stdout, _, status = Cmd.run(command)
52
+ return [nil, nil] unless status.success?
53
+
54
+ licenses = nil
55
+ homepage = nil
56
+
57
+ stdout.scan(/Licenses: (?<licenses>.+)|(?<homepage>(https|http).*)/) do |pkg_licenses, pkg_homepage|
58
+ licenses ||= pkg_licenses
59
+ homepage ||= pkg_homepage
60
+ end
61
+
62
+ [licenses, homepage]
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'csv'
4
+ require 'license_finder/package_utils/sbt_dependency_finder'
5
+
6
+ module LicenseFinder
7
+ class Sbt < PackageManager
8
+ def initialize(options = {})
9
+ super
10
+ @include_groups = options[:sbt_include_groups]
11
+ end
12
+
13
+ def current_packages
14
+ command = "#{package_management_command} dumpLicenseReport"
15
+ _stdout, stderr, status = Dir.chdir(project_path) { Cmd.run(command) }
16
+ raise "Command '#{command}' failed to execute: #{stderr}" unless status.success?
17
+
18
+ dependencies = SbtDependencyFinder.new(project_path).dependencies
19
+ packages = dependencies.flat_map do |text|
20
+ contents = CSV.parse(text, headers: true)
21
+ contents.map do |row|
22
+ group_id, name, version = row['Dependency'].split('#').map(&:strip)
23
+ spec = {
24
+ 'artifactId' => name,
25
+ 'groupId' => group_id,
26
+ 'version' => version,
27
+ 'licenses' => [{ 'name' => row['License'] }]
28
+ }
29
+
30
+ path = File.join("#{Dir.home}/.ivy2/cache", "#{spec['groupId']}/#{spec['artifactId']}")
31
+ SbtPackage.new(spec, logger: logger, include_groups: @include_groups, install_path: path)
32
+ end
33
+ end
34
+
35
+ packages.uniq
36
+ end
37
+
38
+ def package_management_command
39
+ 'sbt'
40
+ end
41
+
42
+ def possible_package_paths
43
+ [project_path.join('build.sbt')]
44
+ end
45
+ end
46
+ end