gitlab-license_finder 6.14.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.force-build +0 -0
- data/.gitignore +13 -0
- data/.rspec +1 -0
- data/.rubocop.yml +70 -0
- data/CHANGELOG.md +981 -0
- data/CONTRIBUTING.md +121 -0
- data/Dockerfile +249 -0
- data/Gemfile +2 -0
- data/LICENSE +22 -0
- data/README.md +555 -0
- data/Rakefile +77 -0
- data/TODO.md +12 -0
- data/VERSION +1 -0
- data/appveyor.yml +21 -0
- data/bin/license_finder +6 -0
- data/bin/license_finder_pip.py +43 -0
- data/ci/pipelines/pull-request.yml.erb +141 -0
- data/ci/pipelines/release.yml.erb +200 -0
- data/ci/scripts/containerize-tests.sh +14 -0
- data/ci/scripts/pushscript.sh +32 -0
- data/ci/scripts/run-rubocop.sh +15 -0
- data/ci/scripts/run-tests.sh +24 -0
- data/ci/scripts/test.ps1 +81 -0
- data/ci/scripts/updateChangelog.sh +84 -0
- data/ci/tasks/build-and-push-gem.yml +10 -0
- data/ci/tasks/build-windows.yml +6 -0
- data/ci/tasks/build.yml +16 -0
- data/ci/tasks/rubocop.yml +15 -0
- data/ci/tasks/run-tests.yml +10 -0
- data/ci/tasks/update-changelog.yml +18 -0
- data/dlf +12 -0
- data/examples/Gemfile +4 -0
- data/examples/custom_erb_template.rb +24 -0
- data/examples/extract_license_data.rb +63 -0
- data/examples/sample_template.erb +7 -0
- data/lib/license_finder/cli/approvals.rb +28 -0
- data/lib/license_finder/cli/base.rb +107 -0
- data/lib/license_finder/cli/dependencies.rb +44 -0
- data/lib/license_finder/cli/ignored_dependencies.rb +32 -0
- data/lib/license_finder/cli/ignored_groups.rb +32 -0
- data/lib/license_finder/cli/inherited_decisions.rb +50 -0
- data/lib/license_finder/cli/licenses.rb +26 -0
- data/lib/license_finder/cli/main.rb +221 -0
- data/lib/license_finder/cli/makes_decisions.rb +38 -0
- data/lib/license_finder/cli/patched_thor.rb +33 -0
- data/lib/license_finder/cli/permitted_licenses.rb +32 -0
- data/lib/license_finder/cli/project_name.rb +32 -0
- data/lib/license_finder/cli/restricted_licenses.rb +32 -0
- data/lib/license_finder/cli.rb +20 -0
- data/lib/license_finder/configuration.rb +186 -0
- data/lib/license_finder/core.rb +118 -0
- data/lib/license_finder/decision_applier.rb +70 -0
- data/lib/license_finder/decisions.rb +312 -0
- data/lib/license_finder/decisions_factory.rb +13 -0
- data/lib/license_finder/diff.rb +51 -0
- data/lib/license_finder/license/any_matcher.rb +15 -0
- data/lib/license_finder/license/definitions.rb +366 -0
- data/lib/license_finder/license/header_matcher.rb +17 -0
- data/lib/license_finder/license/matcher.rb +24 -0
- data/lib/license_finder/license/none_matcher.rb +11 -0
- data/lib/license_finder/license/template.rb +19 -0
- data/lib/license_finder/license/templates/0BSD.txt +10 -0
- data/lib/license_finder/license/templates/Apache1_1.txt +16 -0
- data/lib/license_finder/license/templates/Apache2.txt +172 -0
- data/lib/license_finder/license/templates/BSD.txt +24 -0
- data/lib/license_finder/license/templates/CC01.txt +30 -0
- data/lib/license_finder/license/templates/CDDL1.txt +131 -0
- data/lib/license_finder/license/templates/EPL1.txt +86 -0
- data/lib/license_finder/license/templates/GPLv2.txt +339 -0
- data/lib/license_finder/license/templates/GPLv3.txt +674 -0
- data/lib/license_finder/license/templates/ISC.txt +2 -0
- data/lib/license_finder/license/templates/LGPL.txt +165 -0
- data/lib/license_finder/license/templates/LGPL2_1.txt +169 -0
- data/lib/license_finder/license/templates/MIT.txt +9 -0
- data/lib/license_finder/license/templates/MPL1_1.txt +469 -0
- data/lib/license_finder/license/templates/MPL2.txt +373 -0
- data/lib/license_finder/license/templates/NewBSD.txt +21 -0
- data/lib/license_finder/license/templates/OFL.txt +91 -0
- data/lib/license_finder/license/templates/Python.txt +47 -0
- data/lib/license_finder/license/templates/Ruby.txt +52 -0
- data/lib/license_finder/license/templates/SimplifiedBSD.txt +19 -0
- data/lib/license_finder/license/templates/WTFPL.txt +14 -0
- data/lib/license_finder/license/templates/Zlib.txt +17 -0
- data/lib/license_finder/license/text.rb +45 -0
- data/lib/license_finder/license.rb +117 -0
- data/lib/license_finder/license_aggregator.rb +59 -0
- data/lib/license_finder/logger.rb +69 -0
- data/lib/license_finder/package.rb +202 -0
- data/lib/license_finder/package_delta.rb +61 -0
- data/lib/license_finder/package_manager.rb +181 -0
- data/lib/license_finder/package_managers/bower.rb +37 -0
- data/lib/license_finder/package_managers/bundler.rb +110 -0
- data/lib/license_finder/package_managers/cargo.rb +38 -0
- data/lib/license_finder/package_managers/carthage.rb +68 -0
- data/lib/license_finder/package_managers/cocoa_pods.rb +61 -0
- data/lib/license_finder/package_managers/composer.rb +63 -0
- data/lib/license_finder/package_managers/conan.rb +28 -0
- data/lib/license_finder/package_managers/conda.rb +131 -0
- data/lib/license_finder/package_managers/dep.rb +43 -0
- data/lib/license_finder/package_managers/dotnet.rb +83 -0
- data/lib/license_finder/package_managers/erlangmk.rb +50 -0
- data/lib/license_finder/package_managers/glide.rb +36 -0
- data/lib/license_finder/package_managers/go_15vendorexperiment.rb +87 -0
- data/lib/license_finder/package_managers/go_dep.rb +80 -0
- data/lib/license_finder/package_managers/go_modules.rb +93 -0
- data/lib/license_finder/package_managers/go_workspace.rb +116 -0
- data/lib/license_finder/package_managers/govendor.rb +73 -0
- data/lib/license_finder/package_managers/gradle.rb +99 -0
- data/lib/license_finder/package_managers/gvt.rb +69 -0
- data/lib/license_finder/package_managers/maven.rb +65 -0
- data/lib/license_finder/package_managers/mix.rb +131 -0
- data/lib/license_finder/package_managers/npm.rb +57 -0
- data/lib/license_finder/package_managers/nuget.rb +154 -0
- data/lib/license_finder/package_managers/pip.rb +70 -0
- data/lib/license_finder/package_managers/pipenv.rb +63 -0
- data/lib/license_finder/package_managers/rebar.rb +65 -0
- data/lib/license_finder/package_managers/sbt.rb +50 -0
- data/lib/license_finder/package_managers/spm.rb +93 -0
- data/lib/license_finder/package_managers/trash.rb +43 -0
- data/lib/license_finder/package_managers/yarn.rb +107 -0
- data/lib/license_finder/package_utils/activation.rb +40 -0
- data/lib/license_finder/package_utils/conan_info_parser.rb +77 -0
- data/lib/license_finder/package_utils/gradle_dependency_finder.rb +15 -0
- data/lib/license_finder/package_utils/license_files.rb +41 -0
- data/lib/license_finder/package_utils/licensing.rb +39 -0
- data/lib/license_finder/package_utils/maven_dependency_finder.rb +15 -0
- data/lib/license_finder/package_utils/notice_files.rb +40 -0
- data/lib/license_finder/package_utils/possible_license_file.rb +27 -0
- data/lib/license_finder/package_utils/pypi.rb +41 -0
- data/lib/license_finder/package_utils/sbt_dependency_finder.rb +15 -0
- data/lib/license_finder/packages/bower_package.rb +42 -0
- data/lib/license_finder/packages/bundler_package.rb +33 -0
- data/lib/license_finder/packages/cargo_package.rb +28 -0
- data/lib/license_finder/packages/carthage_package.rb +18 -0
- data/lib/license_finder/packages/cocoa_pods_package.rb +22 -0
- data/lib/license_finder/packages/composer_package.rb +13 -0
- data/lib/license_finder/packages/conan_package.rb +23 -0
- data/lib/license_finder/packages/conda_package.rb +74 -0
- data/lib/license_finder/packages/erlangmk_package.rb +114 -0
- data/lib/license_finder/packages/go_package.rb +32 -0
- data/lib/license_finder/packages/gradle_package.rb +30 -0
- data/lib/license_finder/packages/manual_package.rb +27 -0
- data/lib/license_finder/packages/maven_package.rb +27 -0
- data/lib/license_finder/packages/merged_package.rb +44 -0
- data/lib/license_finder/packages/mix_package.rb +13 -0
- data/lib/license_finder/packages/npm_package.rb +171 -0
- data/lib/license_finder/packages/nuget_package.rb +13 -0
- data/lib/license_finder/packages/pip_package.rb +50 -0
- data/lib/license_finder/packages/rebar_package.rb +13 -0
- data/lib/license_finder/packages/sbt_package.rb +22 -0
- data/lib/license_finder/packages/spm_package.rb +18 -0
- data/lib/license_finder/packages/yarn_package.rb +13 -0
- data/lib/license_finder/platform.rb +15 -0
- data/lib/license_finder/project_finder.rb +62 -0
- data/lib/license_finder/report.rb +33 -0
- data/lib/license_finder/reports/csv_report.rb +99 -0
- data/lib/license_finder/reports/diff_report.rb +29 -0
- data/lib/license_finder/reports/erb_report.rb +58 -0
- data/lib/license_finder/reports/html_report.rb +13 -0
- data/lib/license_finder/reports/json_report.rb +30 -0
- data/lib/license_finder/reports/junit_report.rb +19 -0
- data/lib/license_finder/reports/markdown_report.rb +9 -0
- data/lib/license_finder/reports/merged_report.rb +16 -0
- data/lib/license_finder/reports/templates/bootstrap.css +9 -0
- data/lib/license_finder/reports/templates/html_report.erb +113 -0
- data/lib/license_finder/reports/templates/junit_report.erb +41 -0
- data/lib/license_finder/reports/templates/markdown_report.erb +49 -0
- data/lib/license_finder/reports/templates/xml_report.erb +19 -0
- data/lib/license_finder/reports/text_report.rb +12 -0
- data/lib/license_finder/reports/xml_report.rb +19 -0
- data/lib/license_finder/scanner.rb +83 -0
- data/lib/license_finder/shared_helpers/cmd.rb +13 -0
- data/lib/license_finder/shared_helpers/common_path.rb +29 -0
- data/lib/license_finder/version.rb +6 -0
- data/lib/license_finder.rb +14 -0
- data/license_finder.gemspec +72 -0
- data/release/instructions.md +8 -0
- data/swift-all-keys.asc +240 -0
- 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
|