license_finder-rubyzip3 7.2.1.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/.github/dependabot.yml +16 -0
- data/.gitignore +13 -0
- data/.pre-commit-hooks.yaml +10 -0
- data/.rspec +1 -0
- data/.rubocop.yml +84 -0
- data/CHANGELOG.md +1066 -0
- data/CONTRIBUTING.md +122 -0
- data/Dockerfile +275 -0
- data/Gemfile +2 -0
- data/LICENSE +22 -0
- data/README.md +597 -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 +138 -0
- data/ci/pipelines/release.yml.erb +176 -0
- data/ci/scripts/containerize-tests.sh +14 -0
- data/ci/scripts/pushscript.sh +31 -0
- data/ci/scripts/run-rubocop.sh +15 -0
- data/ci/scripts/run-tests.sh +41 -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 +21 -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 +113 -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 +31 -0
- data/lib/license_finder/cli/main.rb +229 -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 +197 -0
- data/lib/license_finder/core.rb +121 -0
- data/lib/license_finder/decision_applier.rb +70 -0
- data/lib/license_finder/decisions.rb +334 -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 +498 -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/AGPL3.txt +661 -0
- data/lib/license_finder/license/templates/Apache1_1.txt +16 -0
- data/lib/license_finder/license/templates/Apache2.txt +170 -0
- data/lib/license_finder/license/templates/Artistic.txt +128 -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/CC01_alt.txt +31 -0
- data/lib/license_finder/license/templates/CDDL1.txt +131 -0
- data/lib/license_finder/license/templates/CDDL1_1.txt +123 -0
- data/lib/license_finder/license/templates/CPL1.txt +217 -0
- data/lib/license_finder/license/templates/EPL1.txt +86 -0
- data/lib/license_finder/license/templates/EPL2.txt +80 -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/Unlicense.txt +24 -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 +49 -0
- data/lib/license_finder/license.rb +123 -0
- data/lib/license_finder/license_aggregator.rb +59 -0
- data/lib/license_finder/logger.rb +69 -0
- data/lib/license_finder/manual_licenses.rb +79 -0
- data/lib/license_finder/package.rb +195 -0
- data/lib/license_finder/package_delta.rb +61 -0
- data/lib/license_finder/package_manager.rb +183 -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 +66 -0
- data/lib/license_finder/package_managers/composer.rb +63 -0
- data/lib/license_finder/package_managers/conan.rb +70 -0
- data/lib/license_finder/package_managers/conda.rb +131 -0
- data/lib/license_finder/package_managers/dep.rb +45 -0
- data/lib/license_finder/package_managers/dotnet.rb +86 -0
- data/lib/license_finder/package_managers/erlangmk.rb +50 -0
- data/lib/license_finder/package_managers/glide.rb +42 -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 +117 -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 +69 -0
- data/lib/license_finder/package_managers/mix.rb +131 -0
- data/lib/license_finder/package_managers/npm.rb +70 -0
- data/lib/license_finder/package_managers/nuget.rb +159 -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/pnpm.rb +126 -0
- data/lib/license_finder/package_managers/pub.rb +86 -0
- data/lib/license_finder/package_managers/rebar.rb +65 -0
- data/lib/license_finder/package_managers/sbt.rb +46 -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 +195 -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/conan_info_parser_v2.rb +82 -0
- data/lib/license_finder/package_utils/gradle_dependency_finder.rb +15 -0
- data/lib/license_finder/package_utils/license_files.rb +51 -0
- data/lib/license_finder/package_utils/licensing.rb +40 -0
- data/lib/license_finder/package_utils/maven_dependency_finder.rb +57 -0
- data/lib/license_finder/package_utils/notice_files.rb +51 -0
- data/lib/license_finder/package_utils/possible_license_file.rb +33 -0
- data/lib/license_finder/package_utils/pypi.rb +43 -0
- data/lib/license_finder/package_utils/sbt_dependency_finder.rb +15 -0
- data/lib/license_finder/packages/bower_package.rb +45 -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 +112 -0
- data/lib/license_finder/packages/go_package.rb +30 -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 +39 -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 +219 -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/pnpm_package.rb +13 -0
- data/lib/license_finder/packages/pubspec_package.rb +18 -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/printer.rb +39 -0
- data/lib/license_finder/project_finder.rb +62 -0
- data/lib/license_finder/report.rb +34 -0
- data/lib/license_finder/reports/csv_report.rb +108 -0
- data/lib/license_finder/reports/diff_report.rb +29 -0
- data/lib/license_finder/reports/erb_report.rb +62 -0
- data/lib/license_finder/reports/html_report.rb +13 -0
- data/lib/license_finder/reports/json_report.rb +31 -0
- data/lib/license_finder/reports/junit_report.rb +23 -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 +23 -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 +79 -0
- data/release/instructions.md +8 -0
- data/swift-all-keys.asc +240 -0
- metadata +604 -0
|
@@ -0,0 +1,159 @@
|
|
|
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
|
+
licenses&.map! do |license|
|
|
55
|
+
license.gsub('https://licenses.nuget.org/', '')
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
path = Dir.glob("#{Dir.home}/.nuget/packages/#{dep.name.downcase}/#{dep.version}").first
|
|
59
|
+
|
|
60
|
+
memo[dep.name] ||= NugetPackage.new(dep.name, dep.version, spec_licenses: licenses, install_path: path)
|
|
61
|
+
memo[dep.name].groups << dep.assembly unless memo[dep.name].groups.include? dep.assembly
|
|
62
|
+
end.values
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def license_urls(dep)
|
|
66
|
+
files = Dir["**/#{dep.name}.#{dep.version}.nupkg"]
|
|
67
|
+
|
|
68
|
+
return nil if files.empty?
|
|
69
|
+
|
|
70
|
+
file = files.first
|
|
71
|
+
Zip::File.open file do |zipfile|
|
|
72
|
+
content = zipfile.read("#{dep.name}.nuspec")
|
|
73
|
+
Nuget.nuspec_license_urls(content)
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def dependencies
|
|
78
|
+
assemblies.flat_map(&:dependencies)
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def nuget_binary
|
|
82
|
+
legacy_vcproj = Dir['**/*.vcproj'].any?
|
|
83
|
+
|
|
84
|
+
if legacy_vcproj
|
|
85
|
+
'/usr/local/bin/nugetv3.5.0.exe'
|
|
86
|
+
else
|
|
87
|
+
'/usr/local/bin/nuget.exe'
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def package_management_command
|
|
92
|
+
return 'nuget' if LicenseFinder::Platform.windows?
|
|
93
|
+
|
|
94
|
+
"mono #{nuget_binary}"
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def prepare
|
|
98
|
+
Dir.chdir(project_path) do
|
|
99
|
+
cmd = prepare_command
|
|
100
|
+
stdout, stderr, status = Cmd.run(cmd)
|
|
101
|
+
return if status.success?
|
|
102
|
+
|
|
103
|
+
log_errors stderr
|
|
104
|
+
|
|
105
|
+
if stderr.include?('-PackagesDirectory')
|
|
106
|
+
logger.info cmd, 'trying fallback prepare command', color: :magenta
|
|
107
|
+
|
|
108
|
+
cmd = "#{cmd} -PackagesDirectory /#{Dir.home}/.nuget/packages"
|
|
109
|
+
stdout, stderr, status = Cmd.run(cmd)
|
|
110
|
+
return if status.success?
|
|
111
|
+
|
|
112
|
+
log_errors_with_cmd(cmd, stderr)
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
error_message = "Prepare command '#{cmd}' failed\n#{stderr}"
|
|
116
|
+
error_message += "\n#{stdout}\n" if !stdout.nil? && !stdout.empty?
|
|
117
|
+
raise error_message unless @prepare_no_fail
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def prepare_command
|
|
122
|
+
cmd = package_management_command
|
|
123
|
+
sln_files = Dir['*.sln']
|
|
124
|
+
cmds = []
|
|
125
|
+
if sln_files.count > 1
|
|
126
|
+
sln_files.each do |sln|
|
|
127
|
+
cmds << "#{cmd} restore #{sln}"
|
|
128
|
+
end
|
|
129
|
+
else
|
|
130
|
+
cmds << "#{cmd} restore"
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
cmds.join(' && ')
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
def installed?(logger = Core.default_logger)
|
|
137
|
+
_stdout, _stderr, status = Cmd.run(nuget_check)
|
|
138
|
+
if status.success?
|
|
139
|
+
logger.debug self.class, 'is installed', color: :green
|
|
140
|
+
else
|
|
141
|
+
logger.info self.class, 'is not installed', color: :red
|
|
142
|
+
end
|
|
143
|
+
status.success?
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
def nuget_check
|
|
147
|
+
return 'where nuget' if LicenseFinder::Platform.windows?
|
|
148
|
+
|
|
149
|
+
"which mono && ls #{nuget_binary}"
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
def self.nuspec_license_urls(specfile_content)
|
|
153
|
+
xml = REXML::Document.new(specfile_content)
|
|
154
|
+
REXML::XPath.match(xml, '//metadata//licenseUrl')
|
|
155
|
+
.map(&:get_text)
|
|
156
|
+
.map(&:to_s)
|
|
157
|
+
end
|
|
158
|
+
end
|
|
159
|
+
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 = '3'
|
|
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,126 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'json'
|
|
4
|
+
require 'tempfile'
|
|
5
|
+
|
|
6
|
+
module LicenseFinder
|
|
7
|
+
class PNPM < PackageManager
|
|
8
|
+
def initialize(options = {})
|
|
9
|
+
super
|
|
10
|
+
@pnpm_options = options[:pnpm_options]
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
SHELL_COMMAND = 'pnpm licenses list --json --long'
|
|
14
|
+
|
|
15
|
+
def possible_package_paths
|
|
16
|
+
[project_path.join('pnpm-lock.yaml')]
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def self.takes_priority_over
|
|
20
|
+
NPM
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def current_packages
|
|
24
|
+
# check if the minimum version of PNPM is met
|
|
25
|
+
raise 'The minimum PNPM version is not met, requires 7.17.0 or later' unless supported_pnpm?
|
|
26
|
+
|
|
27
|
+
# check if the project directory has workspace file
|
|
28
|
+
cmd = PNPM::SHELL_COMMAND.to_s
|
|
29
|
+
cmd += ' --no-color'
|
|
30
|
+
cmd += ' --recursive' unless project_has_workspaces == false
|
|
31
|
+
cmd += " --dir #{project_path}" unless project_path.nil?
|
|
32
|
+
cmd += " #{@pnpm_options}" unless @pnpm_options.nil?
|
|
33
|
+
|
|
34
|
+
stdout, stderr, status = Cmd.run(cmd)
|
|
35
|
+
raise "Command '#{cmd}' failed to execute: #{stderr}" unless status.success?
|
|
36
|
+
|
|
37
|
+
json_objects = JSON.parse(stdout)
|
|
38
|
+
get_pnpm_packages(json_objects)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def get_pnpm_packages(json_objects)
|
|
42
|
+
packages = []
|
|
43
|
+
incompatible_packages = []
|
|
44
|
+
|
|
45
|
+
json_objects.map do |_, value|
|
|
46
|
+
value.each do |pkg|
|
|
47
|
+
name = pkg['name']
|
|
48
|
+
|
|
49
|
+
if pkg['version']
|
|
50
|
+
version = pkg['version']
|
|
51
|
+
elsif pkg['versions']
|
|
52
|
+
version = pkg['versions'][0]
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
license = pkg['license']
|
|
56
|
+
homepage = pkg['vendorUrl']
|
|
57
|
+
author = pkg['vendorName']
|
|
58
|
+
module_path = pkg['path']
|
|
59
|
+
|
|
60
|
+
package = PNPMPackage.new(
|
|
61
|
+
name,
|
|
62
|
+
version,
|
|
63
|
+
spec_licenses: [license],
|
|
64
|
+
homepage: homepage,
|
|
65
|
+
authors: author,
|
|
66
|
+
install_path: module_path
|
|
67
|
+
)
|
|
68
|
+
packages << package
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
packages + incompatible_packages.uniq
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def package_management_command
|
|
76
|
+
'pnpm'
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def prepare_command
|
|
80
|
+
'pnpm install --no-lockfile --ignore-scripts'
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def prepare
|
|
84
|
+
prep_cmd = "#{prepare_command}#{production_flag}"
|
|
85
|
+
_stdout, stderr, status = Dir.chdir(project_path) { Cmd.run(prep_cmd) }
|
|
86
|
+
|
|
87
|
+
return if status.success?
|
|
88
|
+
|
|
89
|
+
log_errors stderr
|
|
90
|
+
raise "Prepare command '#{prep_cmd}' failed" unless @prepare_no_fail
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
private
|
|
94
|
+
|
|
95
|
+
def project_has_workspaces
|
|
96
|
+
Dir.chdir(project_path) do
|
|
97
|
+
return File.file?('pnpm-workspace.yaml')
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
# PNPM introduced the licenses command in 7.17.0
|
|
102
|
+
def supported_pnpm?
|
|
103
|
+
Dir.chdir(project_path) do
|
|
104
|
+
version_string, stderr_str, status = Cmd.run('pnpm --version')
|
|
105
|
+
raise "Command 'pnpm -v' failed to execute: #{stderr_str}" unless status.success?
|
|
106
|
+
|
|
107
|
+
version = version_string.split('.').map(&:to_i)
|
|
108
|
+
major = version[0]
|
|
109
|
+
minor = version[1]
|
|
110
|
+
patch = version[1]
|
|
111
|
+
|
|
112
|
+
return true if major > 7
|
|
113
|
+
return true if major == 7 && minor > 17
|
|
114
|
+
return true if major == 7 && minor == 17 && patch >= 0
|
|
115
|
+
|
|
116
|
+
return false
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
def production_flag
|
|
121
|
+
return '' if @ignored_groups.nil?
|
|
122
|
+
|
|
123
|
+
@ignored_groups.include?('devDependencies') ? ' --prod' : ''
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
end
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'json'
|
|
4
|
+
require 'yaml'
|
|
5
|
+
|
|
6
|
+
module LicenseFinder
|
|
7
|
+
class Pub < PackageManager
|
|
8
|
+
class PubError < RuntimeError; end
|
|
9
|
+
|
|
10
|
+
def current_packages
|
|
11
|
+
unless File.exist?('pubspec.lock')
|
|
12
|
+
raise PubError, "No checked-out Pub packages found.
|
|
13
|
+
Please install your dependencies first."
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
if ENV['PUB_CACHE'].nil? || ENV['PUB_CACHE'].eql?('')
|
|
17
|
+
raise PubError, 'While PUB_CACHE environment variable is empty, retrieving package licenses is impossible. Please set the PUB_CACHE env variable (default: ~/.pub)'
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
stdout, _stderr, _status = Cmd.run('flutter pub deps --json')
|
|
21
|
+
yaml_deps = JSON.parse(stdout)
|
|
22
|
+
yaml_deps['packages'].map do |dependency|
|
|
23
|
+
package_name = dependency['name']
|
|
24
|
+
subpath = "#{dependency['name']}-#{dependency['version']}"
|
|
25
|
+
package_version = dependency['version']
|
|
26
|
+
|
|
27
|
+
project_repo = dependency['source'] == 'git' ? Pathname("#{ENV['PUB_CACHE']}/git/#{dependency['name']}-*/") : Pathname("#{ENV['PUB_CACHE']}/hosted/pub.dartlang.org/#{subpath}")
|
|
28
|
+
|
|
29
|
+
homepage = read_repository_home(project_repo)
|
|
30
|
+
homepage = "https://pub.dev/packages/#{package_name}" if homepage.nil? || homepage.empty?
|
|
31
|
+
PubPackage.new(
|
|
32
|
+
package_name,
|
|
33
|
+
package_version,
|
|
34
|
+
license_text(project_repo),
|
|
35
|
+
logger: logger,
|
|
36
|
+
install_path: project_repo,
|
|
37
|
+
homepage: homepage
|
|
38
|
+
)
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def possible_package_paths
|
|
43
|
+
[project_path.join('pubspec.lock')]
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def package_management_command
|
|
47
|
+
'flutter'
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def prepare_command
|
|
51
|
+
'flutter pub get'
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def prepare
|
|
55
|
+
prep_cmd = "#{prepare_command} #{production_flag}"
|
|
56
|
+
_stdout, stderr, status = Dir.chdir(project_path) { Cmd.run(prep_cmd) }
|
|
57
|
+
|
|
58
|
+
return if status.success?
|
|
59
|
+
|
|
60
|
+
log_errors stderr
|
|
61
|
+
raise "Prepare command '#{prep_cmd}' failed" unless @prepare_no_fail
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
private
|
|
65
|
+
|
|
66
|
+
def license_text(subpath)
|
|
67
|
+
license_path = license_pattern(subpath).find { |f| File.exist?(f) }
|
|
68
|
+
license_path.nil? ? nil : IO.read(license_path)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def license_pattern(subpath)
|
|
72
|
+
Dir.glob(subpath.join('LICENSE*'), File::FNM_CASEFOLD)
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def production_flag
|
|
76
|
+
return '' if @ignored_groups.nil?
|
|
77
|
+
|
|
78
|
+
@ignored_groups.include?('devDependencies') ? '' : 'no-'
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def read_repository_home(project_repo)
|
|
82
|
+
package_yaml = project_repo.join('pubspec.yaml')
|
|
83
|
+
YAML.load(IO.read(package_yaml))['repository'] if Dir.exist?(project_repo) && File.exist?(package_yaml)
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
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,46 @@
|
|
|
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
|
+
contents = CSV.parse(text, headers: true)
|
|
21
|
+
contents.map do |row|
|
|
22
|
+
group_id, name, version = row['Dependency'].split('#').map(&:strip)
|
|
23
|
+
spec = {
|
|
24
|
+
'artifactId' => name,
|
|
25
|
+
'groupId' => group_id,
|
|
26
|
+
'version' => version,
|
|
27
|
+
'licenses' => [{ 'name' => row['License'] }]
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
path = File.join("#{Dir.home}/.ivy2/cache", "#{spec['groupId']}/#{spec['artifactId']}")
|
|
31
|
+
SbtPackage.new(spec, logger: logger, include_groups: @include_groups, install_path: path)
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
packages.uniq
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def package_management_command
|
|
39
|
+
'sbt'
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def possible_package_paths
|
|
43
|
+
[project_path.join('build.sbt')]
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|