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,154 @@
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
+ path = Dir.glob("#{Dir.home}/.nuget/packages/#{dep.name.downcase}/#{dep.version}").first
55
+
56
+ memo[dep.name] ||= NugetPackage.new(dep.name, dep.version, spec_licenses: licenses, install_path: path)
57
+ memo[dep.name].groups << dep.assembly unless memo[dep.name].groups.include? dep.assembly
58
+ end.values
59
+ end
60
+
61
+ def license_urls(dep)
62
+ files = Dir["**/#{dep.name}.#{dep.version}.nupkg"]
63
+ return nil if files.empty?
64
+
65
+ file = files.first
66
+ Zip::File.open file do |zipfile|
67
+ content = zipfile.read(dep.name + '.nuspec')
68
+ Nuget.nuspec_license_urls(content)
69
+ end
70
+ end
71
+
72
+ def dependencies
73
+ assemblies.flat_map(&:dependencies)
74
+ end
75
+
76
+ def nuget_binary
77
+ legacy_vcproj = Dir['**/*.vcproj'].any?
78
+
79
+ if legacy_vcproj
80
+ '/usr/local/bin/nugetv3.5.0.exe'
81
+ else
82
+ '/usr/local/bin/nuget.exe'
83
+ end
84
+ end
85
+
86
+ def package_management_command
87
+ return 'nuget' if LicenseFinder::Platform.windows?
88
+
89
+ "mono #{nuget_binary}"
90
+ end
91
+
92
+ def prepare
93
+ Dir.chdir(project_path) do
94
+ cmd = prepare_command
95
+ stdout, stderr, status = Cmd.run(cmd)
96
+ return if status.success?
97
+
98
+ log_errors stderr
99
+
100
+ if stderr.include?('-PackagesDirectory')
101
+ logger.info cmd, 'trying fallback prepare command', color: :magenta
102
+
103
+ cmd = "#{cmd} -PackagesDirectory /#{Dir.home}/.nuget/packages"
104
+ stdout, stderr, status = Cmd.run(cmd)
105
+ return if status.success?
106
+
107
+ log_errors_with_cmd(cmd, stderr)
108
+ end
109
+
110
+ error_message = "Prepare command '#{cmd}' failed\n#{stderr}"
111
+ error_message += "\n#{stdout}\n" if !stdout.nil? && !stdout.empty?
112
+ raise error_message unless @prepare_no_fail
113
+ end
114
+ end
115
+
116
+ def prepare_command
117
+ cmd = package_management_command
118
+ sln_files = Dir['*.sln']
119
+ cmds = []
120
+ if sln_files.count > 1
121
+ sln_files.each do |sln|
122
+ cmds << "#{cmd} restore #{sln}"
123
+ end
124
+ else
125
+ cmds << "#{cmd} restore"
126
+ end
127
+
128
+ cmds.join(' && ')
129
+ end
130
+
131
+ def installed?(logger = Core.default_logger)
132
+ _stdout, _stderr, status = Cmd.run(nuget_check)
133
+ if status.success?
134
+ logger.debug self.class, 'is installed', color: :green
135
+ else
136
+ logger.info self.class, 'is not installed', color: :red
137
+ end
138
+ status.success?
139
+ end
140
+
141
+ def nuget_check
142
+ return 'where nuget' if LicenseFinder::Platform.windows?
143
+
144
+ "which mono && ls #{nuget_binary}"
145
+ end
146
+
147
+ def self.nuspec_license_urls(specfile_content)
148
+ xml = REXML::Document.new(specfile_content)
149
+ REXML::XPath.match(xml, '//metadata//licenseUrl')
150
+ .map(&:get_text)
151
+ .map(&:to_s)
152
+ end
153
+ end
154
+ 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 = '2'
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,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,50 @@
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
+ options = {
21
+ headers: true
22
+ }
23
+
24
+ contents = CSV.parse(text, options)
25
+ contents.map do |row|
26
+ group_id, name, version = row['Dependency'].split('#').map(&:strip)
27
+ spec = {
28
+ 'artifactId' => name,
29
+ 'groupId' => group_id,
30
+ 'version' => version,
31
+ 'licenses' => [{ 'name' => row['License'] }]
32
+ }
33
+
34
+ path = File.join("#{Dir.home}/.ivy2/cache", "#{spec['groupId']}/#{spec['artifactId']}")
35
+ SbtPackage.new(spec, logger: logger, include_groups: @include_groups, install_path: path)
36
+ end
37
+ end
38
+
39
+ packages.uniq
40
+ end
41
+
42
+ def package_management_command
43
+ 'sbt'
44
+ end
45
+
46
+ def possible_package_paths
47
+ [project_path.join('build.sbt')]
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,93 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+
5
+ module LicenseFinder
6
+ class Spm < PackageManager
7
+ class SpmError < RuntimeError; end
8
+
9
+ def current_packages
10
+ unless File.exist?(workspace_state_path)
11
+ raise SpmError, 'No checked-out SPM packages found.
12
+ Please install your dependencies first.'
13
+ end
14
+
15
+ workspace_state = JSON.parse(IO.read(workspace_state_path))
16
+ workspace_state['object']['dependencies'].map do |dependency|
17
+ package_ref = dependency['packageRef']
18
+ checkout_state = dependency['state']['checkoutState']
19
+
20
+ subpath = dependency['subpath']
21
+ package_name = package_ref['name']
22
+ package_version = checkout_state['version'] || checkout_state['revision']
23
+ homepage = package_ref['path']
24
+
25
+ SpmPackage.new(
26
+ package_name,
27
+ package_version,
28
+ license_text(subpath),
29
+ logger: logger,
30
+ install_path: project_checkout(subpath),
31
+ homepage: homepage
32
+ )
33
+ end
34
+ end
35
+
36
+ def package_management_command
37
+ LicenseFinder::Platform.darwin? ? 'xcodebuild' : 'swift'
38
+ end
39
+
40
+ def prepare_command
41
+ LicenseFinder::Platform.darwin? ? 'xcodebuild -resolvePackageDependencies' : 'swift package resolve'
42
+ end
43
+
44
+ def possible_package_paths
45
+ [workspace_state_path]
46
+ end
47
+
48
+ private
49
+
50
+ def resolved_package
51
+ if File.exist?(resolved_path)
52
+ @resolved_file ||= IO.read(resolved_path)
53
+ else
54
+ raise SpmError, 'No Package.resolved found.
55
+ Please install your dependencies first and provide it via environment variable
56
+ SPM_PACKAGE_RESOLVED'
57
+ end
58
+ end
59
+
60
+ def resolved_path
61
+ # Xcode projects have SPM packages info under project's derived data location
62
+ derived_data_folder = ENV['SPM_DERIVED_DATA']
63
+ if derived_data_folder
64
+ pathname = Pathname.new(derived_data_folder)
65
+ pathname.absolute? ? pathname : project_path.join(derived_data_folder)
66
+ else
67
+ project_path.join('.build')
68
+ end
69
+ end
70
+
71
+ def workspace_state_path
72
+ resolved_path.join('workspace-state.json')
73
+ end
74
+
75
+ def license_text(subpath)
76
+ license_path = license_pattern(subpath).find { |f| File.exist?(f) }
77
+ license_path.nil? ? nil : IO.read(license_path)
78
+ end
79
+
80
+ def project_checkout(subpath)
81
+ resolved_path.join('checkouts', subpath)
82
+ end
83
+
84
+ def license_pattern(subpath)
85
+ checkout_path = project_checkout(subpath)
86
+ Dir.glob(checkout_path.join('LICENSE*'), File::FNM_CASEFOLD)
87
+ end
88
+
89
+ def name_version_from_line(cartfile_line)
90
+ cartfile_line.split(' ')[1, 2].map { |f| f.split('/').last.delete('"').gsub('.git', '') }
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ module LicenseFinder
4
+ class Trash < PackageManager
5
+ class << self
6
+ def package_management_command
7
+ 'trash'
8
+ end
9
+
10
+ def takes_priority_over
11
+ Go15VendorExperiment
12
+ end
13
+ end
14
+
15
+ def prepare_command
16
+ 'trash'
17
+ end
18
+
19
+ def possible_package_paths
20
+ [project_path.join('vendor.conf')]
21
+ end
22
+
23
+ def current_packages
24
+ dependencies_path = project_path.join('trash.lock')
25
+
26
+ YAML.load_file(dependencies_path).fetch('import').map do |package_hash|
27
+ import_path = package_hash.fetch('package')
28
+ license_path = project_path.join('vendor', import_path)
29
+
30
+ GoPackage.from_dependency({
31
+ 'ImportPath' => import_path,
32
+ 'InstallPath' => license_path,
33
+ 'Rev' => package_hash.fetch('version'),
34
+ 'Homepage' => repo_name(import_path)
35
+ }, nil, true)
36
+ end
37
+ end
38
+
39
+ def repo_name(name)
40
+ name.split('/')[0..2].join('/')
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,107 @@
1
+ # frozen_string_literal: true
2
+
3
+ module LicenseFinder
4
+ class Yarn < PackageManager
5
+ SHELL_COMMAND = 'yarn licenses list --no-progress --json'
6
+
7
+ def possible_package_paths
8
+ [project_path.join('yarn.lock')]
9
+ end
10
+
11
+ def current_packages
12
+ cmd = "#{Yarn::SHELL_COMMAND}#{production_flag}"
13
+ suffix = " --cwd #{project_path}" unless project_path.nil?
14
+ cmd += suffix unless suffix.nil?
15
+
16
+ stdout, _stderr, status = Cmd.run(cmd)
17
+ return [] unless status.success?
18
+
19
+ packages = []
20
+ incompatible_packages = []
21
+
22
+ json_strings = stdout.encode('ASCII', invalid: :replace, undef: :replace, replace: '?').split("\n")
23
+ json_objects = json_strings.map { |json_object| JSON.parse(json_object) }
24
+
25
+ if json_objects.last['type'] == 'table'
26
+ license_json = json_objects.pop['data']
27
+ packages = packages_from_json(license_json)
28
+ end
29
+
30
+ json_objects.each do |json_object|
31
+ match = /(?<name>[\w,\-]+)@(?<version>(\d+\.?)+)/ =~ json_object['data'].to_s
32
+ if match
33
+ package = YarnPackage.new(name, version, spec_licenses: ['unknown'])
34
+ incompatible_packages.push(package)
35
+ end
36
+ end
37
+
38
+ packages + incompatible_packages.uniq
39
+ end
40
+
41
+ def prepare
42
+ prep_cmd = "#{prepare_command}#{production_flag}"
43
+ _stdout, stderr, status = Dir.chdir(project_path) { Cmd.run(prep_cmd) }
44
+ return if status.success?
45
+
46
+ log_errors stderr
47
+ raise "Prepare command '#{prep_cmd}' failed" unless @prepare_no_fail
48
+ end
49
+
50
+ def self.takes_priority_over
51
+ NPM
52
+ end
53
+
54
+ def package_management_command
55
+ 'yarn'
56
+ end
57
+
58
+ def prepare_command
59
+ 'yarn install --ignore-engines --ignore-scripts'
60
+ end
61
+
62
+ private
63
+
64
+ def packages_from_json(json_data)
65
+ body = json_data['body']
66
+ head = json_data['head']
67
+
68
+ packages = body.map do |json_package|
69
+ Hash[head.zip(json_package)]
70
+ end
71
+
72
+ valid_packages = filter_yarn_internal_package(packages)
73
+
74
+ valid_packages.map do |package_hash|
75
+ YarnPackage.new(
76
+ package_hash['Name'],
77
+ package_hash['Version'],
78
+ spec_licenses: [package_hash['License']],
79
+ homepage: package_hash['VendorUrl'],
80
+ authors: package_hash['VendorName'],
81
+ install_path: project_path.join(modules_folder, package_hash['Name'])
82
+ )
83
+ end
84
+ end
85
+
86
+ def modules_folder
87
+ return @modules_folder if @modules_folder
88
+
89
+ stdout, _stderr, status = Cmd.run('yarn config get modules-folder')
90
+ @modules_folder = 'node_modules' if !status.success? || stdout.strip == 'undefined'
91
+ @modules_folder ||= stdout.strip
92
+ end
93
+
94
+ # remove fake package created by yarn [Yarn Bug]
95
+ def filter_yarn_internal_package(all_packages)
96
+ internal_package_pattern = /workspace-aggregator-[a-zA-z0-9]{8}-[a-zA-z0-9]{4}-[a-zA-z0-9]{4}-[a-zA-z0-9]{4}-[a-zA-z0-9]{12}/
97
+ yarn_internal_package = all_packages.find { |package| internal_package_pattern.match(package['Name']) }
98
+ all_packages - [yarn_internal_package]
99
+ end
100
+
101
+ def production_flag
102
+ return '' if @ignored_groups.nil?
103
+
104
+ @ignored_groups.include?('devDependencies') ? ' --production' : ''
105
+ end
106
+ end
107
+ end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ module LicenseFinder
4
+ module Activation
5
+ # An Activation reports that a license has been activated for a package, and
6
+ # tracks the source of that information
7
+ Basic = Struct.new(:package, :license)
8
+
9
+ class FromDecision < Basic
10
+ def sources
11
+ ['from decision']
12
+ end
13
+ end
14
+
15
+ class FromSpec < Basic
16
+ def sources
17
+ ['from spec']
18
+ end
19
+ end
20
+
21
+ class FromFiles < Basic
22
+ def initialize(package, license, files)
23
+ super(package, license)
24
+ @files = files
25
+ end
26
+
27
+ attr_reader :files
28
+
29
+ def sources
30
+ files.map { |file| "from file '#{file.path}'" }
31
+ end
32
+ end
33
+
34
+ class None < Basic
35
+ def sources
36
+ []
37
+ end
38
+ end
39
+ end
40
+ end