Merge pull request #7953 from MLH-Fellowship/license-multiple

Allow multiple licenses to be specified as an array with a consistent internal API
This commit is contained in:
Mike McQuaid 2020-07-28 14:31:02 +01:00 committed by GitHub
commit b0c5991426
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 92 additions and 23 deletions

View File

@ -330,20 +330,28 @@ module Homebrew
def audit_license
if formula.license.present?
if @spdx_data["licenses"].any? { |lic| lic["licenseId"] == formula.license }
return unless @online
non_standard_licenses = []
formula.license.each do |license|
next if @spdx_data["licenses"].any? { |spdx| spdx["licenseId"] == license }
user, repo = get_repo_data(%r{https?://github\.com/([^/]+)/([^/]+)/?.*}) if @new_formula
return if user.blank?
github_license = GitHub.get_repo_license(user, repo)
return if github_license && [formula.license, "NOASSERTION"].include?(github_license)
problem "License mismatch - GitHub license is: #{github_license}, "\
"but Formulae license states: #{formula.license}."
else
problem "#{formula.license} is not a standard SPDX license."
non_standard_licenses << license
end
if non_standard_licenses.present?
problem "Formula #{formula.name} contains non-standard SPDX licenses: #{non_standard_licenses}."
end
return unless @online
user, repo = get_repo_data(%r{https?://github\.com/([^/]+)/([^/]+)/?.*}) if @new_formula
return if user.blank?
github_license = GitHub.get_repo_license(user, repo)
return if github_license && (formula.license + ["NOASSERTION"]).include?(github_license)
problem "License mismatch - GitHub license is: #{Array(github_license)}, "\
"but Formulae license states: #{formula.license}."
elsif @new_formula
problem "No license specified for package."
end

View File

@ -2208,9 +2208,16 @@ class Formula
# @!attribute [w]
# The SPDX ID of the open-source license that the formula uses.
# Shows when running `brew info`.
#
# Multiple licenses means that the software is licensed under multiple licenses.
# Do not use multiple licenses if e.g. different parts are under different licenses.
# <pre>license "BSD-2-Clause"</pre>
attr_rw :license
def license(args = nil)
if args.nil?
@licenses
else
@licenses = Array(args)
end
end
# @!attribute [w] homepage
# The homepage for the software. Used by users to get more information

View File

@ -1123,18 +1123,18 @@ class FormulaInstaller
next if @ignore_deps
dep_f = dep.to_formula
next unless forbidden_licenses.include? dep_f.license
next unless dep_f.license.all? { |license| forbidden_licenses.include? license }
raise CannotInstallFormulaError, <<~EOS
The installation of #{formula.name} has a dependency on #{dep.name} with a forbidden license #{dep_f.license}.
The installation of #{formula.name} has a dependency on #{dep.name} where all its licenses are forbidden: #{dep_f.license}.
EOS
end
return if @only_deps
return unless forbidden_licenses.include? formula.license
return unless formula.license.all? { |license| forbidden_licenses.include? license }
raise CannotInstallFormulaError, <<~EOS
#{formula.name} has a forbidden license #{formula.license}.
#{formula.name}'s licenses are all forbidden: #{formula.license}.
EOS
end
end

View File

@ -86,12 +86,14 @@ module Homebrew
let(:custom_spdx_id) { "zzz" }
let(:standard_mismatch_spdx_id) { "0BSD" }
let(:license_array) { ["0BSD", "GPL-3.0"] }
let(:license_array_mismatch) { ["0BSD", "MIT"] }
let(:license_array_nonstandard) { ["0BSD", "zzz", "MIT"] }
it "does not check if the formula is not a new formula" do
fa = formula_auditor "foo", <<~RUBY, spdx_data: spdx_data, new_formula: false
class Foo < Formula
url "https://brew.sh/foo-1.0.tgz"
license ""
end
RUBY
@ -103,7 +105,6 @@ module Homebrew
fa = formula_auditor "foo", <<~RUBY, spdx_data: spdx_data, new_formula: true
class Foo < Formula
url "https://brew.sh/foo-1.0.tgz"
license ""
end
RUBY
@ -120,7 +121,19 @@ module Homebrew
RUBY
fa.audit_license
expect(fa.problems.first).to match "#{custom_spdx_id} is not a standard SPDX license."
expect(fa.problems.first).to match "Formula foo contains non-standard SPDX licenses: [\"zzz\"]."
end
it "detects if license array contains a non-standard spdx-id" do
fa = formula_auditor "foo", <<~RUBY, spdx_data: spdx_data, new_formula: true
class Foo < Formula
url "https://brew.sh/foo-1.0.tgz"
license #{license_array_nonstandard}
end
RUBY
fa.audit_license
expect(fa.problems.first).to match "Formula foo contains non-standard SPDX licenses: [\"zzz\"]."
end
it "verifies that a license info is a standard spdx id" do
@ -135,6 +148,18 @@ module Homebrew
expect(fa.problems).to be_empty
end
it "verifies that a license array contains only standard spdx id" do
fa = formula_auditor "foo", <<~RUBY, spdx_data: spdx_data, new_formula: true
class Foo < Formula
url "https://brew.sh/foo-1.0.tgz"
license #{license_array}
end
RUBY
fa.audit_license
expect(fa.problems).to be_empty
end
it "checks online and verifies that a standard license id is the same "\
"as what is indicated on its Github repo" do
fa = formula_auditor "cask", <<~RUBY, spdx_data: spdx_data, online: true, core_tap: true, new_formula: true
@ -160,8 +185,37 @@ module Homebrew
RUBY
fa.audit_license
expect(fa.problems.first).to match "License mismatch - GitHub license is: GPL-3.0, "\
"but Formulae license states: #{standard_mismatch_spdx_id}."
expect(fa.problems.first).to match "License mismatch - GitHub license is: [\"GPL-3.0\"], "\
"but Formulae license states: #{Array(standard_mismatch_spdx_id)}."
end
it "checks online and detects that an array of license does not contain "\
"what is indicated on its Github repository" do
fa = formula_auditor "cask", <<~RUBY, online: true, spdx_data: spdx_data, core_tap: true, new_formula: true
class Cask < Formula
url "https://github.com/cask/cask/archive/v0.8.4.tar.gz"
head "https://github.com/cask/cask.git"
license #{license_array_mismatch}
end
RUBY
fa.audit_license
expect(fa.problems.first).to match "License mismatch - GitHub license is: [\"GPL-3.0\"], "\
"but Formulae license states: #{Array(license_array_mismatch)}."
end
it "checks online and verifies that an array of license contains "\
"what is indicated on its Github repository" do
fa = formula_auditor "cask", <<~RUBY, online: true, spdx_data: spdx_data, core_tap: true, new_formula: true
class Cask < Formula
url "https://github.com/cask/cask/archive/v0.8.4.tar.gz"
head "https://github.com/cask/cask.git"
license #{license_array}
end
RUBY
fa.audit_license
expect(fa.problems).to be_empty
end
end