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,131 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+
5
+ module LicenseFinder
6
+ class Conda < PackageManager
7
+ attr_reader :conda_bash_setup_script
8
+
9
+ def initialize(options = {})
10
+ @conda_bash_setup_script = options[:conda_bash_setup_script] || Pathname("#{ENV['HOME']}/miniconda3/etc/profile.d/conda.sh")
11
+ super
12
+ end
13
+
14
+ # This command is *not* directly executable. See .conda() below.
15
+ def prepare_command
16
+ "conda env create -f #{detected_package_path}"
17
+ end
18
+
19
+ def prepare
20
+ return if environment_exists?
21
+
22
+ prep_cmd = prepare_command
23
+ _stdout, stderr, status = Dir.chdir(project_path) { conda(prep_cmd) }
24
+ return if status.success?
25
+
26
+ log_errors stderr
27
+ raise "Prepare command '#{prep_cmd}' failed" unless @prepare_no_fail
28
+ end
29
+
30
+ def current_packages
31
+ conda_list.map do |entry|
32
+ case entry['channel']
33
+ when 'pypi'
34
+ # PyPI is much faster than `conda search`, use it when we can.
35
+ PipPackage.new(entry['name'], entry['version'], PyPI.definition(entry['name'], entry['version']))
36
+ else
37
+ CondaPackage.new(conda_search_info(entry))
38
+ end
39
+ end.compact
40
+ end
41
+
42
+ def possible_package_paths
43
+ [project_path.join('environment.yaml'), project_path.join('environment.yml')]
44
+ end
45
+
46
+ private
47
+
48
+ def environment_exists?
49
+ environments.grep(environment_name).any?
50
+ end
51
+
52
+ def environments
53
+ command = 'conda env list'
54
+ stdout, stderr, status = conda command
55
+
56
+ environments = []
57
+ if status.success?
58
+ environments = stdout.split("\n").grep_v(/^#/).map { |line| line.split.first }
59
+ else
60
+ log_errors_with_cmd command, stderr
61
+ end
62
+ environments
63
+ end
64
+
65
+ def environment_file
66
+ detected_package_path
67
+ end
68
+
69
+ def environment_name
70
+ @environment_name ||= YAML.load_file(environment_file).fetch('name')
71
+ end
72
+
73
+ def conda(command)
74
+ Open3.capture3('bash', '-c', "source #{conda_bash_setup_script} && #{command}")
75
+ end
76
+
77
+ def activated_conda(command)
78
+ Open3.capture3('bash', '-c', "source #{conda_bash_setup_script} && conda activate #{environment_name} && #{command}")
79
+ end
80
+
81
+ # Algorithm is based on
82
+ # https://bioinformatics.stackexchange.com/a/11226
83
+ # but completely recoded in Ruby. Like the poster, if the package is
84
+ # actually managed by conda, we assume that all the potential infos (for
85
+ # various architectures, versions of python, etc) have the same license.
86
+ def conda_list
87
+ command = 'conda list'
88
+ stdout, stderr, status = activated_conda(command)
89
+
90
+ if status.success?
91
+ conda_list = []
92
+ stdout.each_line do |line|
93
+ next if line =~ /^\s*#/
94
+
95
+ name, version, build, channel = line.split
96
+ conda_list << {
97
+ 'name' => name,
98
+ 'version' => version,
99
+ 'build' => build,
100
+ 'channel' => channel
101
+ }
102
+ end
103
+ conda_list
104
+ else
105
+ log_errors_with_cmd command, stderr
106
+ []
107
+ end
108
+ end
109
+
110
+ def conda_search_info(list_entry)
111
+ command = 'conda search --info --json '
112
+ command += "--channel #{list_entry['channel']} " if list_entry['channel'] && !list_entry['channel'].empty?
113
+ command += "'#{list_entry['name']} #{list_entry['version']}'"
114
+
115
+ # Errors from conda (in --json mode, at least) show up in stdout, not stderr
116
+ stdout, _stderr, status = activated_conda(command)
117
+
118
+ name = list_entry['name']
119
+
120
+ if status.success?
121
+ JSON(stdout).fetch(name).first
122
+ else
123
+ log_errors_with_cmd command, stdout
124
+ list_entry
125
+ end
126
+ rescue KeyError
127
+ logger.info('Conda', "Key error trying to find #{name} in\n#{JSON(stdout)}")
128
+ list_entry
129
+ end
130
+ end
131
+ end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'tomlrb'
4
+
5
+ module LicenseFinder
6
+ class Dep < PackageManager
7
+ def possible_package_paths
8
+ [project_path.join('Gopkg.lock')]
9
+ end
10
+
11
+ def current_packages
12
+ toml = Tomlrb.load_file(detected_package_path)
13
+ projects = toml['projects']
14
+
15
+ return [] if projects.nil?
16
+
17
+ projects.map do |project|
18
+ GoPackage.from_dependency({
19
+ 'ImportPath' => project['name'],
20
+ 'InstallPath' => project_path.join('vendor', project['name']),
21
+ 'Rev' => project['revision'],
22
+ 'Homepage' => repo_name(project['name'])
23
+ }, nil, true)
24
+ end
25
+ end
26
+
27
+ def repo_name(name)
28
+ name.split('/')[0..2].join('/')
29
+ end
30
+
31
+ def self.takes_priority_over
32
+ Go15VendorExperiment
33
+ end
34
+
35
+ def prepare_command
36
+ 'dep ensure -vendor-only'
37
+ end
38
+
39
+ def package_management_command
40
+ 'dep'
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,83 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'pathname'
4
+ require 'json'
5
+
6
+ module LicenseFinder
7
+ class Dotnet < PackageManager
8
+ class AssetFile
9
+ def initialize(path)
10
+ @manifest = JSON.parse(File.read(path))
11
+ end
12
+
13
+ def dependencies
14
+ libs = @manifest.fetch('libraries').reject do |_, v|
15
+ v.fetch('type') == 'project'
16
+ end
17
+
18
+ libs.keys.map do |name|
19
+ parts = name.split('/')
20
+ PackageMetadata.new(parts[0], parts[1], possible_spec_paths(name))
21
+ end
22
+ end
23
+
24
+ def possible_spec_paths(package_key)
25
+ lib = @manifest.fetch('libraries').fetch(package_key)
26
+ spec_filename = lib.fetch('files').find { |f| f.end_with?('.nuspec') }
27
+ return [] if spec_filename.nil?
28
+
29
+ @manifest.fetch('packageFolders').keys.map do |root|
30
+ Pathname(root).join(lib.fetch('path'), spec_filename).to_s
31
+ end
32
+ end
33
+ end
34
+
35
+ class PackageMetadata
36
+ attr_reader :name, :version, :possible_spec_paths
37
+
38
+ def initialize(name, version, possible_spec_paths)
39
+ @name = name
40
+ @version = version
41
+ @possible_spec_paths = possible_spec_paths
42
+ end
43
+
44
+ def read_license_urls
45
+ possible_spec_paths.flat_map do |path|
46
+ Nuget.nuspec_license_urls(File.read(path)) if File.exist? path
47
+ end.compact
48
+ end
49
+
50
+ def ==(other)
51
+ other.name == name && other.version == version && other.possible_spec_paths == possible_spec_paths
52
+ end
53
+ end
54
+
55
+ def possible_package_paths
56
+ paths = Dir[project_path.join('*.csproj')]
57
+ paths.map { |p| Pathname(p) }
58
+ end
59
+
60
+ def current_packages
61
+ package_metadatas = asset_files
62
+ .flat_map { |path| AssetFile.new(path).dependencies }
63
+ .uniq { |d| [d.name, d.version] }
64
+
65
+ package_metadatas.map do |d|
66
+ path = Dir.glob("#{Dir.home}/.nuget/packages/#{d.name.downcase}/#{d.version}").first
67
+ NugetPackage.new(d.name, d.version, spec_licenses: d.read_license_urls, install_path: path)
68
+ end
69
+ end
70
+
71
+ def asset_files
72
+ Dir[project_path.join('**/project.assets.json')]
73
+ end
74
+
75
+ def package_management_command
76
+ 'dotnet'
77
+ end
78
+
79
+ def prepare_command
80
+ "#{package_management_command} restore"
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ module LicenseFinder
4
+ class Erlangmk < PackageManager
5
+ def package_management_command
6
+ 'make'
7
+ end
8
+
9
+ def package_management_command_with_path
10
+ "#{package_management_command} --directory=#{project_path} --no-print-directory"
11
+ end
12
+
13
+ # The IS_DEP=1 is added because not all erlang.mk-based projects are
14
+ # updated to a version that is compatible with LicenseFinder
15
+ def prepare_command
16
+ "#{package_management_command_with_path} IS_DEP=1 fetch-deps"
17
+ end
18
+
19
+ def possible_package_paths
20
+ [
21
+ project_path.join('Erlang.mk'),
22
+ project_path.join('erlang.mk')
23
+ ]
24
+ end
25
+
26
+ def current_packages
27
+ deps.map do |dep|
28
+ ErlangmkPackage.new(dep)
29
+ end
30
+ end
31
+
32
+ private
33
+
34
+ def deps
35
+ command = "#{package_management_command_with_path} QUERY='name fetch_method repo version absolute_path' query-deps"
36
+ stdout, stderr, status = Cmd.run(command)
37
+ if status.success?
38
+ dep_re = Regexp.new('^\s*DEP')
39
+ line_re = Regexp.new('^[_a-z0-9]+:')
40
+ stdout.each_line.map(&:strip).select { |line| !(line.start_with?('make') || line =~ dep_re) && line =~ line_re }
41
+ elsif stderr.include? "No rule to make target 'query-deps'"
42
+ # The stderr check happens because not all erlang.mk-based projects are
43
+ # updated to a version that is compatible with LicenseFinder
44
+ []
45
+ else
46
+ raise "Command '#{command}' failed to execute: #{stderr}"
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ module LicenseFinder
4
+ class Glide < PackageManager
5
+ def possible_package_paths
6
+ [project_path.join('glide.lock')]
7
+ end
8
+
9
+ def current_packages
10
+ detected_path = detected_package_path
11
+
12
+ YAML.load_file(detected_path).fetch('imports').map do |package_hash|
13
+ import_path = package_hash.fetch('name')
14
+ license_path = project_path.join('vendor', import_path)
15
+
16
+ GoPackage.from_dependency({
17
+ 'ImportPath' => import_path,
18
+ 'InstallPath' => license_path,
19
+ 'Rev' => package_hash.fetch('version')
20
+ }, nil, true)
21
+ end
22
+ end
23
+
24
+ def self.takes_priority_over
25
+ Go15VendorExperiment
26
+ end
27
+
28
+ def package_management_command
29
+ 'glide'
30
+ end
31
+
32
+ def prepare_command
33
+ 'glide install'
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,87 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+
5
+ module LicenseFinder
6
+ class Go15VendorExperiment < PackageManager
7
+ def initialize(options = {})
8
+ super
9
+ @full_version = options[:go_full_version]
10
+ end
11
+
12
+ def active?
13
+ super && go_files_exist?
14
+ end
15
+
16
+ def go_files_exist?
17
+ !Dir[project_path.join('**/*.go')].empty? && !Dir[project_path.join('vendor/**/*.go')].empty?
18
+ end
19
+
20
+ def possible_package_paths
21
+ [project_path.join('vendor')]
22
+ end
23
+
24
+ def project_sha(path)
25
+ Dir.chdir(path) do
26
+ stdout, _stderr, status = Cmd.run('git rev-list --max-count 1 HEAD')
27
+ raise 'git rev-list failed' unless status.success?
28
+
29
+ stdout.strip
30
+ end
31
+ end
32
+
33
+ def current_packages
34
+ deps = go_list
35
+ vendored_deps = deps.select { |dep| detected_package_path.join(dep).exist? }
36
+ vendored_deps.map do |dep|
37
+ GoPackage.from_dependency({
38
+ 'ImportPath' => dep,
39
+ 'InstallPath' => detected_package_path.join(dep),
40
+ 'Rev' => 'vendored-' + project_sha(detected_package_path.join(dep)),
41
+ 'Homepage' => repo_name(dep)
42
+ }, nil, true)
43
+ end
44
+ end
45
+
46
+ def repo_name(name)
47
+ name.split('/')[0..2].join('/')
48
+ end
49
+
50
+ def package_management_command
51
+ 'go'
52
+ end
53
+
54
+ def go_list
55
+ Dir.chdir(project_path) do
56
+ # avoid checking canonical import path. some projects uses
57
+ # non-canonical import path and rely on the fact that the deps are
58
+ # checked in. Canonical paths are only checked by `go get'. We
59
+ # discovered that `go list' will print a warning and unfortunately exit
60
+ # with status code 1. Setting GOPATH to nil removes those warnings.
61
+ orig_gopath = ENV['GOPATH']
62
+ ENV['GOPATH'] = nil
63
+ val, _stderr, status = Cmd.run('go list -f "{{join .Deps \"\n\"}}" ./...')
64
+ ENV['GOPATH'] = orig_gopath
65
+ return [] unless status.success?
66
+
67
+ # Select non-standard packages. `go list std` returns the list of standard
68
+ # dependencies. We then filter those dependencies out of the full list of
69
+ # dependencies.
70
+ deps = val.split("\n")
71
+ Cmd.run('go list std').first.split("\n").each do |std|
72
+ deps.delete_if do |dep|
73
+ dep =~ %r{(\/|^)#{std}(\/|$)}
74
+ end
75
+ end
76
+ deps.map do |d|
77
+ dep_parts = d.split('/')
78
+ if dep_parts.length > 2
79
+ dep_parts[0..2].join('/')
80
+ else
81
+ d
82
+ end
83
+ end
84
+ end
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,80 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+
5
+ module LicenseFinder
6
+ class GoDep < PackageManager
7
+ OLD_GODEP_VENDOR_PATH = 'Godeps/_workspace/src'
8
+ GODEP_VENDOR_PATH = 'vendor'
9
+
10
+ def initialize(options = {})
11
+ super
12
+ @full_version = options[:go_full_version]
13
+ end
14
+
15
+ def current_packages
16
+ packages_from_json(detected_package_path.read)
17
+ # godep includes subpackages as a seperate dependency, we can de-dup that
18
+ end
19
+
20
+ def self.takes_priority_over
21
+ Go15VendorExperiment
22
+ end
23
+
24
+ def possible_package_paths
25
+ [project_path.join('Godeps/Godeps.json')]
26
+ end
27
+
28
+ def package_management_command
29
+ 'godep'
30
+ end
31
+
32
+ private
33
+
34
+ def install_prefix
35
+ @install_prefix ||= if project_path.join(OLD_GODEP_VENDOR_PATH).directory?
36
+ project_path.join(OLD_GODEP_VENDOR_PATH)
37
+ elsif project_path.join(GODEP_VENDOR_PATH).directory?
38
+ project_path.join(GODEP_VENDOR_PATH)
39
+ else
40
+ download_dependencies
41
+ Pathname(ENV['GOPATH'] ? ENV['GOPATH'] + '/src' : ENV['HOME'] + '/go/src')
42
+ end
43
+ end
44
+
45
+ def download_dependencies
46
+ command = "#{package_management_command} restore"
47
+ _, stderr, status = Dir.chdir(project_path) { Cmd.run(command) }
48
+ raise "Command '#{command}' failed to execute: #{stderr}" if !status.success? && status.exitstatus != 1
49
+ end
50
+
51
+ def packages_from_json(json_string)
52
+ all_packages = JSON.parse(json_string)['Deps']
53
+
54
+ return [] unless all_packages
55
+
56
+ packages_grouped_by_revision = all_packages.group_by { |package| package['Rev'] }
57
+ result = []
58
+
59
+ packages_grouped_by_revision.each do |_sha, packages_in_group|
60
+ all_paths_in_group = packages_in_group.map { |p| p['ImportPath'] }
61
+ common_paths = CommonPathHelper.longest_common_paths(all_paths_in_group)
62
+ package_info = packages_in_group.first
63
+
64
+ common_paths.each do |common_path|
65
+ dependency_info_hash = {
66
+ 'Homepage' => common_path,
67
+ 'ImportPath' => common_path,
68
+ 'InstallPath' => package_info['InstallPath'],
69
+ 'Rev' => package_info['Rev']
70
+ }
71
+
72
+ result << GoPackage.from_dependency(dependency_info_hash,
73
+ install_prefix,
74
+ @full_version)
75
+ end
76
+ end
77
+ result
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,93 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'license_finder/packages/go_package'
4
+
5
+ module LicenseFinder
6
+ class GoModules < PackageManager
7
+ PACKAGES_FILE = 'go.mod'
8
+
9
+ class << self
10
+ def takes_priority_over
11
+ Go15VendorExperiment
12
+ end
13
+ end
14
+
15
+ def active?
16
+ mod_files?
17
+ end
18
+
19
+ def current_packages
20
+ packages = packages_info.map do |package|
21
+ name, version, install_path = package.split(',')
22
+ read_package(install_path, name, version) if install_path.to_s != ''
23
+ end.compact
24
+ packages.reject do |package|
25
+ Pathname(package.install_path).cleanpath == Pathname(project_path).cleanpath
26
+ end
27
+ end
28
+
29
+ private
30
+
31
+ def packages_info
32
+ Dir.chdir(project_path) do
33
+ # Explanations:
34
+ # * Only list dependencies (packages not listed in the project directory)
35
+ # (.DepOnly)
36
+ # * Ignore packages that have nil modules
37
+ # (.Module)
38
+ # * Ignore standard library packages
39
+ # (not .Standard)
40
+ # * Replacement modules are respected
41
+ # (or .Module.Replace .Module)
42
+ # * Module cache directory or (vendored) package directory
43
+ # (or $mod.Dir .Dir)
44
+ format_str = \
45
+ '{{ if and (.DepOnly) (.Module) (not .Standard) }}'\
46
+ '{{ $mod := (or .Module.Replace .Module) }}'\
47
+ '{{ $mod.Path }},{{ $mod.Version }},{{ or $mod.Dir .Dir }}'\
48
+ '{{ end }}'
49
+
50
+ # The module list flag (`-m`) is intentionally not used here. If the module
51
+ # dependency tree were followed, transitive dependencies that are never imported
52
+ # may be included.
53
+ #
54
+ # Instead, the owning module is listed for each imported package. This better
55
+ # matches the implementation of other Go package managers.
56
+ #
57
+ # TODO: Figure out a way to make the vendor directory work (i.e. remove the
58
+ # -mod=readonly flag). Each of the imported packages gets listed separatly,
59
+ # confusing the issue as to which package is the root of the module.
60
+ go_list_cmd = "GO111MODULE=on go list -mod=readonly -deps -f '#{format_str}' ./..."
61
+ info_output, stderr, status = Cmd.run(go_list_cmd)
62
+ log_errors_with_cmd(go_list_cmd, "Getting the dependencies from go list failed \n\t#{stderr}") unless status.success?
63
+ raise "Command '#{go_list_cmd}' failed to execute" unless status.success?
64
+
65
+ # Since many packages may belong to a single module, #uniq is used to deduplicate
66
+ info_output.split("\n").uniq
67
+ end
68
+ end
69
+
70
+ def mod_files?
71
+ mod_file_paths.any?
72
+ end
73
+
74
+ def mod_file_paths
75
+ Dir[project_path.join(PACKAGES_FILE)]
76
+ end
77
+
78
+ def read_package(install_path, name, version)
79
+ info = {
80
+ 'ImportPath' => name,
81
+ 'InstallPath' => install_path,
82
+ 'Rev' => version,
83
+ 'Homepage' => repo_name(name)
84
+ }
85
+
86
+ GoPackage.from_dependency(info, nil, true)
87
+ end
88
+
89
+ def repo_name(name)
90
+ name.split('/')[0..2].join('/')
91
+ end
92
+ end
93
+ end