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