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,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,195 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module LicenseFinder
|
|
4
|
+
class Yarn < PackageManager
|
|
5
|
+
def initialize(options = {})
|
|
6
|
+
super
|
|
7
|
+
@yarn_options = options[:yarn_options]
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
SHELL_COMMAND = 'yarn licenses list --recursive --json'
|
|
11
|
+
|
|
12
|
+
def possible_package_paths
|
|
13
|
+
[project_path.join('yarn.lock')]
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def current_packages
|
|
17
|
+
# the licenses plugin supports the classic production flag
|
|
18
|
+
cmd = "#{Yarn::SHELL_COMMAND}#{classic_yarn_production_flag}"
|
|
19
|
+
if yarn_version == 1
|
|
20
|
+
cmd += ' --no-progress'
|
|
21
|
+
cmd += " --cwd #{project_path}" unless project_path.nil?
|
|
22
|
+
cmd += " #{@yarn_options}" unless @yarn_options.nil?
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
stdout, stderr, status = Dir.chdir(project_path) { Cmd.run(cmd) }
|
|
26
|
+
raise "Command '#{cmd}' failed to execute: #{stderr}" unless status.success?
|
|
27
|
+
|
|
28
|
+
json_strings = stdout.encode('ASCII', invalid: :replace, undef: :replace, replace: '?').split("\n")
|
|
29
|
+
json_objects = json_strings.map { |json_object| JSON.parse(json_object) }
|
|
30
|
+
|
|
31
|
+
if yarn_version == 1
|
|
32
|
+
get_yarn1_packages(json_objects)
|
|
33
|
+
else
|
|
34
|
+
get_yarn_packages(json_objects)
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def prepare
|
|
39
|
+
prep_cmd = prepare_command.to_s
|
|
40
|
+
_stdout, stderr, status = Dir.chdir(project_path) { Cmd.run(prep_cmd) }
|
|
41
|
+
return if status.success?
|
|
42
|
+
|
|
43
|
+
log_errors stderr
|
|
44
|
+
raise "Prepare command '#{prep_cmd}' failed" unless @prepare_no_fail
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def self.takes_priority_over
|
|
48
|
+
NPM
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def package_management_command
|
|
52
|
+
'yarn'
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def prepare_command
|
|
56
|
+
if yarn_version == 1
|
|
57
|
+
classic_yarn_prepare_command
|
|
58
|
+
else
|
|
59
|
+
yarn_prepare_command
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
private
|
|
64
|
+
|
|
65
|
+
def yarn_prepare_command
|
|
66
|
+
"#{yarn_plugin_production_command}yarn install && yarn plugin import https://raw.githubusercontent.com/mhassan1/yarn-plugin-licenses/#{yarn_licenses_plugin_version}/bundles/@yarnpkg/plugin-licenses.js"
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def classic_yarn_prepare_command
|
|
70
|
+
"yarn install --ignore-engines --ignore-scripts#{classic_yarn_production_flag}"
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def yarn_licenses_plugin_version
|
|
74
|
+
if yarn_version == 2
|
|
75
|
+
'v0.6.0'
|
|
76
|
+
else
|
|
77
|
+
'v0.7.2'
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def yarn_version
|
|
82
|
+
Dir.chdir(project_path) do
|
|
83
|
+
version_string, stderr_str, status = Dir.chdir(project_path) { Cmd.run('yarn -v') }
|
|
84
|
+
raise "Command 'yarn -v' failed to execute: #{stderr_str}" unless status.success?
|
|
85
|
+
|
|
86
|
+
version = version_string.split('.').map(&:to_i)
|
|
87
|
+
return version[0]
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def get_yarn_packages(json_objects)
|
|
92
|
+
packages = []
|
|
93
|
+
incompatible_packages = []
|
|
94
|
+
json_objects.each do |json_object|
|
|
95
|
+
license = json_object['value']
|
|
96
|
+
body = json_object['children']
|
|
97
|
+
|
|
98
|
+
body.each do |package_name, vendor_info|
|
|
99
|
+
valid_match = %r{(?<name>@?[\w/.-]+)@(?<manager>\D*):\D*(?<version>(\d+\.?)+)} =~ package_name.to_s
|
|
100
|
+
valid_match = %r{(?<name>@?[\w/.-]+)@virtual:.+#(\D*):\D*(?<version>(\d+\.?)+)} =~ package_name.to_s if manager.eql?('virtual')
|
|
101
|
+
|
|
102
|
+
if valid_match
|
|
103
|
+
homepage = vendor_info['children']['vendorUrl']
|
|
104
|
+
author = vendor_info['children']['vendorName']
|
|
105
|
+
package = YarnPackage.new(
|
|
106
|
+
name,
|
|
107
|
+
version,
|
|
108
|
+
spec_licenses: [license],
|
|
109
|
+
homepage: homepage,
|
|
110
|
+
authors: author,
|
|
111
|
+
install_path: project_path.join(modules_folder, name)
|
|
112
|
+
)
|
|
113
|
+
packages << package
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
incompatible_match = %r{(?<name>@?[\w/.-]+)@[a-z]*:(?<version>(\.))} =~ package_name.to_s
|
|
117
|
+
if incompatible_match
|
|
118
|
+
package = YarnPackage.new(name, version, spec_licenses: [license])
|
|
119
|
+
incompatible_packages.push(package)
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
packages + incompatible_packages.uniq
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def get_yarn1_packages(json_objects)
|
|
128
|
+
packages = []
|
|
129
|
+
if json_objects.last['type'] == 'table'
|
|
130
|
+
license_json = json_objects.pop['data']
|
|
131
|
+
packages = packages_from_json(license_json)
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
incompatible_packages = []
|
|
135
|
+
json_objects.each do |json_object|
|
|
136
|
+
match = %r{(?<name>@?[\w/.-]+)@(?<version>(\d+\.?)+)} =~ json_object['data'].to_s
|
|
137
|
+
if match
|
|
138
|
+
package = YarnPackage.new(name, version, spec_licenses: ['unknown'])
|
|
139
|
+
incompatible_packages.push(package)
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
packages + incompatible_packages.uniq
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
def packages_from_json(json_data)
|
|
147
|
+
body = json_data['body']
|
|
148
|
+
head = json_data['head']
|
|
149
|
+
|
|
150
|
+
packages = body.map do |json_package|
|
|
151
|
+
Hash[head.zip(json_package)]
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
valid_packages = filter_yarn_internal_package(packages)
|
|
155
|
+
|
|
156
|
+
valid_packages.map do |package_hash|
|
|
157
|
+
YarnPackage.new(
|
|
158
|
+
package_hash['Name'],
|
|
159
|
+
package_hash['Version'],
|
|
160
|
+
spec_licenses: [package_hash['License']],
|
|
161
|
+
homepage: package_hash['VendorUrl'],
|
|
162
|
+
authors: package_hash['VendorName'],
|
|
163
|
+
install_path: project_path.join(modules_folder, package_hash['Name'])
|
|
164
|
+
)
|
|
165
|
+
end
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
def modules_folder
|
|
169
|
+
return @modules_folder if @modules_folder
|
|
170
|
+
|
|
171
|
+
stdout, _stderr, status = Dir.chdir(project_path) { Cmd.run('yarn config get modules-folder') }
|
|
172
|
+
@modules_folder = 'node_modules' if !status.success? || stdout.strip == 'undefined'
|
|
173
|
+
@modules_folder ||= stdout.strip
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
# remove fake package created by yarn [Yarn Bug]
|
|
177
|
+
def filter_yarn_internal_package(all_packages)
|
|
178
|
+
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}/
|
|
179
|
+
yarn_internal_package = all_packages.find { |package| internal_package_pattern.match(package['Name']) }
|
|
180
|
+
all_packages - [yarn_internal_package]
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
def classic_yarn_production_flag
|
|
184
|
+
return '' if @ignored_groups.nil?
|
|
185
|
+
|
|
186
|
+
@ignored_groups.include?('devDependencies') ? ' --production' : ''
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
def yarn_plugin_production_command
|
|
190
|
+
return '' if @ignored_groups.nil?
|
|
191
|
+
|
|
192
|
+
@ignored_groups.include?('devDependencies') ? 'yarn plugin import workspace-tools && yarn workspaces focus --all --production && ' : ''
|
|
193
|
+
end
|
|
194
|
+
end
|
|
195
|
+
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
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module LicenseFinder
|
|
4
|
+
class ConanInfoParser
|
|
5
|
+
def parse(info)
|
|
6
|
+
@lines = info.lines.map(&:chomp)
|
|
7
|
+
@state = :project_level # state of the state machine
|
|
8
|
+
@projects = [] # list of projects
|
|
9
|
+
@current_project = nil # current project being populated in the SM
|
|
10
|
+
@current_vals = [] # current val list being populate in the SM
|
|
11
|
+
@current_key = nil # current key to be associated with the current val
|
|
12
|
+
while (line = @lines.shift)
|
|
13
|
+
next if line == ''
|
|
14
|
+
|
|
15
|
+
case @state
|
|
16
|
+
when :project_level
|
|
17
|
+
@current_project = {}
|
|
18
|
+
@current_project['name'] = line.strip
|
|
19
|
+
@state = :key_val
|
|
20
|
+
when :key_val
|
|
21
|
+
parse_key_val(line)
|
|
22
|
+
when :val_list
|
|
23
|
+
parse_val_list(line)
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
wrap_up
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
private
|
|
30
|
+
|
|
31
|
+
def parse_key_val(line)
|
|
32
|
+
key, val = key_val(line)
|
|
33
|
+
if val
|
|
34
|
+
@current_project[key.downcase] = val
|
|
35
|
+
elsif line.start_with?(' ')
|
|
36
|
+
@current_key = key.downcase
|
|
37
|
+
@current_vals = []
|
|
38
|
+
@state = :val_list
|
|
39
|
+
else
|
|
40
|
+
change_to_new_project_state line
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def parse_val_list(line)
|
|
45
|
+
if val_list_level(line)
|
|
46
|
+
@current_vals << line.strip
|
|
47
|
+
else
|
|
48
|
+
@current_project[@current_key] = @current_vals
|
|
49
|
+
if line.start_with?(' ')
|
|
50
|
+
@state = :key_val
|
|
51
|
+
@lines.unshift(line)
|
|
52
|
+
else
|
|
53
|
+
change_to_new_project_state line
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def wrap_up
|
|
59
|
+
@current_project[@current_key] = @current_vals if @current_vals.count && @current_key
|
|
60
|
+
@projects << @current_project
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def val_list_level(line)
|
|
64
|
+
line.start_with?(' ')
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def change_to_new_project_state(line)
|
|
68
|
+
@state = :project_level
|
|
69
|
+
@projects << @current_project
|
|
70
|
+
@lines.unshift(line)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def key_val(info)
|
|
74
|
+
info.split(':', 2).map(&:strip!)
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module LicenseFinder
|
|
4
|
+
class ConanInfoParserV2
|
|
5
|
+
def parse(info)
|
|
6
|
+
@lines = info.lines.map(&:chomp)
|
|
7
|
+
@state = :project_level # state of the state machine
|
|
8
|
+
@projects = [] # list of projects
|
|
9
|
+
@current_project = nil # current project being populated in the SM
|
|
10
|
+
@current_vals = [] # current val list being populate in the SM
|
|
11
|
+
@current_key = nil # current key to be associated with the current val
|
|
12
|
+
|
|
13
|
+
line = @lines.shift
|
|
14
|
+
line = @lines.shift while line != '======== Basic graph information ========'
|
|
15
|
+
|
|
16
|
+
while (line = @lines.shift)
|
|
17
|
+
next if line == ''
|
|
18
|
+
|
|
19
|
+
case @state
|
|
20
|
+
when :project_level
|
|
21
|
+
@current_project = {}
|
|
22
|
+
name, _id = line.strip.split('#')
|
|
23
|
+
@current_project['name'] = name
|
|
24
|
+
@state = :key_val
|
|
25
|
+
when :key_val
|
|
26
|
+
parse_key_val(line)
|
|
27
|
+
when :val_list
|
|
28
|
+
parse_val_list(line)
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
wrap_up
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
private
|
|
35
|
+
|
|
36
|
+
def parse_key_val(line)
|
|
37
|
+
key, val = key_val(line)
|
|
38
|
+
if val
|
|
39
|
+
@current_project[key.downcase] = val
|
|
40
|
+
elsif line.start_with?(' ')
|
|
41
|
+
@current_key = key.downcase
|
|
42
|
+
@current_vals = []
|
|
43
|
+
@state = :val_list
|
|
44
|
+
else
|
|
45
|
+
change_to_new_project_state line
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def parse_val_list(line)
|
|
50
|
+
if val_list_level(line)
|
|
51
|
+
@current_vals << line.strip
|
|
52
|
+
else
|
|
53
|
+
@current_project[@current_key] = @current_vals
|
|
54
|
+
if line.start_with?(' ')
|
|
55
|
+
@state = :key_val
|
|
56
|
+
@lines.unshift(line)
|
|
57
|
+
else
|
|
58
|
+
change_to_new_project_state line
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def wrap_up
|
|
64
|
+
@current_project[@current_key] = @current_vals if @current_vals.count && @current_key
|
|
65
|
+
@projects << @current_project
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def val_list_level(line)
|
|
69
|
+
line.start_with?(' ')
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def change_to_new_project_state(line)
|
|
73
|
+
@state = :project_level
|
|
74
|
+
@projects << @current_project
|
|
75
|
+
@lines.unshift(line)
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def key_val(info)
|
|
79
|
+
info.split(':', 2).map(&:strip!)
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module LicenseFinder
|
|
4
|
+
class GradleDependencyFinder
|
|
5
|
+
def initialize(project_path)
|
|
6
|
+
@project_path = project_path
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def dependencies
|
|
10
|
+
Pathname
|
|
11
|
+
.glob(@project_path.join('**', 'dependency-license.xml'))
|
|
12
|
+
.map(&:read)
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'license_finder/package_utils/possible_license_file'
|
|
4
|
+
|
|
5
|
+
module LicenseFinder
|
|
6
|
+
class LicenseFiles
|
|
7
|
+
CANDIDATE_FILE_NAMES = %w[LICENSE License license LICENCE Licence licence COPYING copying README readme].freeze
|
|
8
|
+
CANDIDATE_PATH_WILDCARD = "*{#{CANDIDATE_FILE_NAMES.join(',')}}*"
|
|
9
|
+
|
|
10
|
+
def self.find(install_path, options = {})
|
|
11
|
+
new(install_path).find(options)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def initialize(install_path)
|
|
15
|
+
@install_path = install_path ? Pathname(install_path) : nil
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def find(options = {})
|
|
19
|
+
paths_of_candidate_files
|
|
20
|
+
.map { |path| PossibleLicenseFile.new(path, options) }
|
|
21
|
+
.reject { |file| file.license.nil? }
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
private
|
|
25
|
+
|
|
26
|
+
attr_reader :install_path
|
|
27
|
+
|
|
28
|
+
def paths_of_candidate_files
|
|
29
|
+
candidate_files_and_dirs
|
|
30
|
+
.flat_map { |path| !path.is_a?(Zip::Entry) && path.directory? ? path.children : path }
|
|
31
|
+
.reject(&:directory?)
|
|
32
|
+
.uniq
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def candidate_files_and_dirs
|
|
36
|
+
return [] if install_path.nil?
|
|
37
|
+
|
|
38
|
+
if !install_path.extname.casecmp('.jar').zero?
|
|
39
|
+
Pathname.glob(install_path.join('**', CANDIDATE_PATH_WILDCARD))
|
|
40
|
+
else
|
|
41
|
+
candidates_from_zip
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def candidates_from_zip
|
|
46
|
+
Zip::File.open(install_path.to_s) do |zip_file|
|
|
47
|
+
zip_file.glob(CANDIDATE_PATH_WILDCARD, File::FNM_EXTGLOB)
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'license_finder/package_utils/activation'
|
|
4
|
+
|
|
5
|
+
module LicenseFinder
|
|
6
|
+
Licensing = Struct.new(:package, :decided_licenses, :licenses_from_spec, :license_files) do
|
|
7
|
+
# Implements the algorithm for choosing the right set of licenses from
|
|
8
|
+
# among the various sources of licenses we know about. In order of
|
|
9
|
+
# priority, licenses come from decisions, package specs, or package files.
|
|
10
|
+
def activations
|
|
11
|
+
if activations_from_decisions.any? then activations_from_decisions
|
|
12
|
+
elsif activations_from_spec.any? then activations_from_spec
|
|
13
|
+
elsif activations_from_files.any? then activations_from_files
|
|
14
|
+
else
|
|
15
|
+
[default_activation]
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def activations_from_decisions
|
|
20
|
+
@activations_from_decisions ||= decided_licenses
|
|
21
|
+
.map { |license| Activation::FromDecision.new(package, license) }
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def activations_from_spec
|
|
25
|
+
@activations_from_spec ||= licenses_from_spec
|
|
26
|
+
.map { |license| Activation::FromSpec.new(package, license) }
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def activations_from_files
|
|
30
|
+
@activations_from_files ||= license_files
|
|
31
|
+
.group_by(&:license)
|
|
32
|
+
.map { |license, files| Activation::FromFiles.new(package, license, files) }
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def default_activation
|
|
36
|
+
default_license = License.find_by_name nil
|
|
37
|
+
Activation::None.new(package, default_license)
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module LicenseFinder
|
|
4
|
+
class MavenDependencyFinder
|
|
5
|
+
def initialize(project_path, m2_path)
|
|
6
|
+
@project_path = project_path
|
|
7
|
+
@m2_path = m2_path
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def dependencies
|
|
11
|
+
options = {
|
|
12
|
+
'GroupTags' => { 'licenses' => 'license', 'dependencies' => 'dependency' },
|
|
13
|
+
'ForceArray' => %w[license dependency]
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
Pathname
|
|
17
|
+
.glob(@project_path.join('**', 'target', 'generated-resources', 'licenses.xml'))
|
|
18
|
+
.map(&:read)
|
|
19
|
+
.flat_map { |xml| XmlSimple.xml_in(xml, options)['dependencies'] }
|
|
20
|
+
.reject(&:empty?)
|
|
21
|
+
.each { |dep| add_info_from_m2(dep) }
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# Add the name of the JAR file to allow later retrieval of license and notice files,
|
|
25
|
+
# and add the name, description and URL from the POM XML file.
|
|
26
|
+
def add_info_from_m2(dep)
|
|
27
|
+
m2_artifact_dir = @m2_path
|
|
28
|
+
.join(dep['groupId'].tr('.', '/'))
|
|
29
|
+
.join(dep['artifactId'])
|
|
30
|
+
.join(dep['version'])
|
|
31
|
+
artifact_basename = "#{dep['artifactId']}-#{dep['version']}"
|
|
32
|
+
|
|
33
|
+
# Basic support for Maven classifiers. So far, only "jakarta" is supported. Unfortunately,
|
|
34
|
+
# we do not have access to the "classifier" field here (licenses.xml does not have it).
|
|
35
|
+
jar_file = m2_artifact_dir.join("#{artifact_basename}.jar")
|
|
36
|
+
jar_file = m2_artifact_dir.join("#{artifact_basename}-jakarta.jar") unless File.exist?(jar_file) || !File.exist?(m2_artifact_dir.join("#{artifact_basename}-jakarta.jar"))
|
|
37
|
+
|
|
38
|
+
dep.store('jarFile', jar_file)
|
|
39
|
+
|
|
40
|
+
add_info_from_pom(m2_artifact_dir.join("#{artifact_basename}.pom"), dep)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# Extract name, description and URL from pom.xml
|
|
44
|
+
def add_info_from_pom(pom_file, dep)
|
|
45
|
+
pom = XmlSimple.xml_in(pom_file.read, { 'ForceArray' => false })
|
|
46
|
+
|
|
47
|
+
name = pom['name']
|
|
48
|
+
dep.store('summary', name) unless name.nil?
|
|
49
|
+
|
|
50
|
+
description = pom['description']
|
|
51
|
+
dep.store('description', description) unless description.nil?
|
|
52
|
+
|
|
53
|
+
url = pom['url']
|
|
54
|
+
dep.store('homepage', url) unless url.nil?
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|