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