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.
- 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
|