Merge pull request #17037 from Homebrew/more_forbidden
Add more `HOMEBREW_FORBIDDEN_*` configuration
This commit is contained in:
commit
3c910b94c1
@ -71,6 +71,9 @@ module Cask
|
|||||||
download(quiet:, timeout:)
|
download(quiet:, timeout:)
|
||||||
|
|
||||||
satisfy_cask_and_formula_dependencies
|
satisfy_cask_and_formula_dependencies
|
||||||
|
|
||||||
|
forbidden_tap_check
|
||||||
|
forbidden_cask_and_formula_check
|
||||||
end
|
end
|
||||||
|
|
||||||
def stage
|
def stage
|
||||||
@ -571,6 +574,107 @@ on_request: true)
|
|||||||
gain_permissions_remove(@cask.caskroom_path)
|
gain_permissions_remove(@cask.caskroom_path)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
sig { void }
|
||||||
|
def forbidden_tap_check
|
||||||
|
forbidden_taps = Homebrew::EnvConfig.forbidden_taps
|
||||||
|
return if forbidden_taps.blank?
|
||||||
|
|
||||||
|
forbidden_taps_set = Set.new(forbidden_taps.split.filter_map do |tap|
|
||||||
|
Tap.fetch(tap)
|
||||||
|
rescue Tap::InvalidNameError
|
||||||
|
opoo "Invalid tap name in `HOMEBREW_FORBIDDEN_TAPS`: #{tap}"
|
||||||
|
nil
|
||||||
|
end)
|
||||||
|
|
||||||
|
owner = Homebrew::EnvConfig.forbidden_owner
|
||||||
|
owner_contact = if (contact = Homebrew::EnvConfig.forbidden_owner_contact.presence)
|
||||||
|
"\n#{contact}"
|
||||||
|
end
|
||||||
|
|
||||||
|
unless skip_cask_deps?
|
||||||
|
cask_and_formula_dependencies.each do |cask_or_formula|
|
||||||
|
dep_tap = cask_or_formula.tap
|
||||||
|
next if dep_tap.blank?
|
||||||
|
next unless forbidden_taps_set.include?(dep_tap)
|
||||||
|
|
||||||
|
dep_full_name = cask_or_formula.full_name
|
||||||
|
raise CaskCannotBeInstalledError.new(@cask, <<~EOS
|
||||||
|
The installation of #{@cask} has a dependency #{dep_full_name}
|
||||||
|
but the #{dep_tap} tap was forbidden by #{owner} in `HOMEBREW_FORBIDDEN_TAPS`.#{owner_contact}
|
||||||
|
EOS
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
cask_tap = @cask.tap
|
||||||
|
return if cask_tap.blank?
|
||||||
|
return unless forbidden_taps_set.include?(cask_tap)
|
||||||
|
|
||||||
|
raise CaskCannotBeInstalledError.new(@cask, <<~EOS
|
||||||
|
The installation of #{@cask.full_name} has the tap #{cask_tap}
|
||||||
|
which was forbidden by #{owner} in `HOMEBREW_FORBIDDEN_TAPS`.#{owner_contact}
|
||||||
|
EOS
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
sig { void }
|
||||||
|
def forbidden_cask_and_formula_check
|
||||||
|
forbidden_formulae = Set.new(Homebrew::EnvConfig.forbidden_formulae.to_s.split)
|
||||||
|
forbidden_casks = Set.new(Homebrew::EnvConfig.forbidden_casks.to_s.split)
|
||||||
|
return if forbidden_formulae.blank? && forbidden_casks.blank?
|
||||||
|
|
||||||
|
owner = Homebrew::EnvConfig.forbidden_owner
|
||||||
|
owner_contact = if (contact = Homebrew::EnvConfig.forbidden_owner_contact.presence)
|
||||||
|
"\n#{contact}"
|
||||||
|
end
|
||||||
|
|
||||||
|
unless skip_cask_deps?
|
||||||
|
cask_and_formula_dependencies.each do |dep_cask_or_formula|
|
||||||
|
dep_name, dep_type, variable = if dep_cask_or_formula.is_a?(Cask) && forbidden_casks.present?
|
||||||
|
dep_cask = dep_cask_or_formula
|
||||||
|
dep_cask_name = if forbidden_casks.include?(dep_cask.token)
|
||||||
|
dep_cask.token
|
||||||
|
elsif dep_cask.tap.present? &&
|
||||||
|
forbidden_casks.include?(dep_cask.full_name)
|
||||||
|
dep_cask.full_name
|
||||||
|
end
|
||||||
|
[dep_cask_name, "cask", "HOMEBREW_FORBIDDEN_CASKS"]
|
||||||
|
elsif dep_cask_or_formula.is_a?(Formula) && forbidden_formulae.present?
|
||||||
|
dep_formula = dep_cask_or_formula
|
||||||
|
formula_name = if forbidden_formulae.include?(dep_formula.name)
|
||||||
|
dep_formula.name
|
||||||
|
elsif dep_formula.tap.present? &&
|
||||||
|
forbidden_formulae.include?(dep_formula.full_name)
|
||||||
|
dep_formula.full_name
|
||||||
|
end
|
||||||
|
[formula_name, "formula", "HOMEBREW_FORBIDDEN_FORMULAE"]
|
||||||
|
end
|
||||||
|
next if dep_name.blank?
|
||||||
|
|
||||||
|
raise CaskCannotBeInstalledError.new(@cask, <<~EOS
|
||||||
|
The installation of #{@cask} has a dependency #{dep_name}
|
||||||
|
but the #{dep_name} #{dep_type} was forbidden by #{owner} in `#{variable}`.#{owner_contact}
|
||||||
|
EOS
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return if forbidden_casks.blank?
|
||||||
|
|
||||||
|
cask_name = if forbidden_casks.include?(@cask.token)
|
||||||
|
@cask.token
|
||||||
|
elsif forbidden_casks.include?(@cask.full_name)
|
||||||
|
@cask.full_name
|
||||||
|
else
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
raise CaskCannotBeInstalledError.new(@cask, <<~EOS
|
||||||
|
The installation of #{cask_name} was forbidden by #{owner}
|
||||||
|
in `HOMEBREW_FORBIDDEN_CASKS`.#{owner_contact}
|
||||||
|
EOS
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
# load the same cask file that was used for installation, if possible
|
# load the same cask file that was used for installation, if possible
|
||||||
|
@ -185,10 +185,29 @@ module Homebrew
|
|||||||
description: "Output this many lines of output on formula `system` failures.",
|
description: "Output this many lines of output on formula `system` failures.",
|
||||||
default: 15,
|
default: 15,
|
||||||
},
|
},
|
||||||
|
HOMEBREW_FORBIDDEN_CASKS: {
|
||||||
|
description: "A space-separated list of casks. Homebrew will refuse to install a " \
|
||||||
|
"cask if it or any of its dependencies is on this list.",
|
||||||
|
},
|
||||||
|
HOMEBREW_FORBIDDEN_FORMULAE: {
|
||||||
|
description: "A space-separated list of formulae. Homebrew will refuse to install a " \
|
||||||
|
"formula or cask if it or any of its dependencies is on this list.",
|
||||||
|
},
|
||||||
HOMEBREW_FORBIDDEN_LICENSES: {
|
HOMEBREW_FORBIDDEN_LICENSES: {
|
||||||
description: "A space-separated list of licenses. Homebrew will refuse to install a " \
|
description: "A space-separated list of licenses. Homebrew will refuse to install a " \
|
||||||
"formula if it or any of its dependencies has a license on this list.",
|
"formula if it or any of its dependencies has a license on this list.",
|
||||||
},
|
},
|
||||||
|
HOMEBREW_FORBIDDEN_OWNER: {
|
||||||
|
description: "The person who has set any `HOMEBREW_FORBIDDEN_*` variables.",
|
||||||
|
default: "you",
|
||||||
|
},
|
||||||
|
HOMEBREW_FORBIDDEN_OWNER_CONTACT: {
|
||||||
|
description: "How to contact the `HOMEBREW_FORBIDDEN_OWNER`, if set and necessary.",
|
||||||
|
},
|
||||||
|
HOMEBREW_FORBIDDEN_TAPS: {
|
||||||
|
description: "A space-separated list of taps. Homebrew will refuse to install a " \
|
||||||
|
"formula if it or any of its dependencies is in a tap on this list.",
|
||||||
|
},
|
||||||
HOMEBREW_FORCE_BREWED_CA_CERTIFICATES: {
|
HOMEBREW_FORCE_BREWED_CA_CERTIFICATES: {
|
||||||
description: "If set, always use a Homebrew-installed `ca-certificates` rather than the system version. " \
|
description: "If set, always use a Homebrew-installed `ca-certificates` rather than the system version. " \
|
||||||
"Automatically set if the system version is too old.",
|
"Automatically set if the system version is too old.",
|
||||||
|
@ -217,7 +217,10 @@ class FormulaInstaller
|
|||||||
Tab.clear_cache
|
Tab.clear_cache
|
||||||
|
|
||||||
verify_deps_exist unless ignore_deps?
|
verify_deps_exist unless ignore_deps?
|
||||||
|
|
||||||
forbidden_license_check
|
forbidden_license_check
|
||||||
|
forbidden_tap_check
|
||||||
|
forbidden_formula_check
|
||||||
|
|
||||||
check_install_sanity
|
check_install_sanity
|
||||||
install_fetch_deps unless ignore_deps?
|
install_fetch_deps unless ignore_deps?
|
||||||
@ -1315,6 +1318,134 @@ on_request: installed_on_request?, options:)
|
|||||||
@locked ||= []
|
@locked ||= []
|
||||||
end
|
end
|
||||||
|
|
||||||
|
sig { void }
|
||||||
|
def forbidden_license_check
|
||||||
|
forbidden_licenses = Homebrew::EnvConfig.forbidden_licenses.to_s.dup
|
||||||
|
SPDX::ALLOWED_LICENSE_SYMBOLS.each do |s|
|
||||||
|
pattern = /#{s.to_s.tr("_", " ")}/i
|
||||||
|
forbidden_licenses.sub!(pattern, s.to_s)
|
||||||
|
end
|
||||||
|
forbidden_licenses = forbidden_licenses.split.to_h do |license|
|
||||||
|
[license, SPDX.license_version_info(license)]
|
||||||
|
end
|
||||||
|
|
||||||
|
return if forbidden_licenses.blank?
|
||||||
|
|
||||||
|
owner = Homebrew::EnvConfig.forbidden_owner
|
||||||
|
owner_contact = if (contact = Homebrew::EnvConfig.forbidden_owner_contact.presence)
|
||||||
|
"\n#{contact}"
|
||||||
|
end
|
||||||
|
|
||||||
|
unless ignore_deps?
|
||||||
|
compute_dependencies.each do |(dep, _options)|
|
||||||
|
dep_f = dep.to_formula
|
||||||
|
next unless SPDX.licenses_forbid_installation? dep_f.license, forbidden_licenses
|
||||||
|
|
||||||
|
raise CannotInstallFormulaError, <<~EOS
|
||||||
|
The installation of #{formula.name} has a dependency on #{dep.name} where all
|
||||||
|
its licenses were forbidden by #{owner} in `HOMEBREW_FORBIDDEN_LICENSES`:
|
||||||
|
#{SPDX.license_expression_to_string dep_f.license}.#{owner_contact}
|
||||||
|
EOS
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return if only_deps?
|
||||||
|
|
||||||
|
return unless SPDX.licenses_forbid_installation? formula.license, forbidden_licenses
|
||||||
|
|
||||||
|
raise CannotInstallFormulaError, <<~EOS
|
||||||
|
#{formula.name}'s licenses are all forbidden by #{owner} in `HOMEBREW_FORBIDDEN_LICENSES`:
|
||||||
|
#{SPDX.license_expression_to_string formula.license}.#{owner_contact}
|
||||||
|
EOS
|
||||||
|
end
|
||||||
|
|
||||||
|
sig { void }
|
||||||
|
def forbidden_tap_check
|
||||||
|
forbidden_taps = Homebrew::EnvConfig.forbidden_taps
|
||||||
|
return if forbidden_taps.blank?
|
||||||
|
|
||||||
|
forbidden_taps_set = Set.new(forbidden_taps.split.filter_map do |tap|
|
||||||
|
Tap.fetch(tap)
|
||||||
|
rescue Tap::InvalidNameError
|
||||||
|
opoo "Invalid tap name in `HOMEBREW_FORBIDDEN_TAPS`: #{tap}"
|
||||||
|
nil
|
||||||
|
end)
|
||||||
|
|
||||||
|
owner = Homebrew::EnvConfig.forbidden_owner
|
||||||
|
owner_contact = if (contact = Homebrew::EnvConfig.forbidden_owner_contact.presence)
|
||||||
|
"\n#{contact}"
|
||||||
|
end
|
||||||
|
|
||||||
|
unless ignore_deps?
|
||||||
|
compute_dependencies.each do |(dep, _options)|
|
||||||
|
dep_tap = dep.tap
|
||||||
|
next if dep_tap.blank?
|
||||||
|
next unless forbidden_taps_set.include?(dep_tap)
|
||||||
|
|
||||||
|
raise CannotInstallFormulaError, <<~EOS
|
||||||
|
The installation of #{formula.name} has a dependency #{dep.name}
|
||||||
|
but the #{dep_tap} tap was forbidden by #{owner} in `HOMEBREW_FORBIDDEN_TAPS`.#{owner_contact}
|
||||||
|
EOS
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return if only_deps?
|
||||||
|
|
||||||
|
formula_tap = formula.tap
|
||||||
|
return if formula_tap.blank?
|
||||||
|
return unless forbidden_taps_set.include?(formula_tap)
|
||||||
|
|
||||||
|
raise CannotInstallFormulaError, <<~EOS
|
||||||
|
The installation of #{formula.full_name} has the tap #{formula_tap}
|
||||||
|
which was forbidden by #{owner} in `HOMEBREW_FORBIDDEN_TAPS`.#{owner_contact}
|
||||||
|
EOS
|
||||||
|
end
|
||||||
|
|
||||||
|
sig { void }
|
||||||
|
def forbidden_formula_check
|
||||||
|
forbidden_formulae = Set.new(Homebrew::EnvConfig.forbidden_formulae.to_s.split)
|
||||||
|
return if forbidden_formulae.blank?
|
||||||
|
|
||||||
|
owner = Homebrew::EnvConfig.forbidden_owner
|
||||||
|
owner_contact = if (contact = Homebrew::EnvConfig.forbidden_owner_contact.presence)
|
||||||
|
"\n#{contact}"
|
||||||
|
end
|
||||||
|
|
||||||
|
unless ignore_deps?
|
||||||
|
compute_dependencies.each do |(dep, _options)|
|
||||||
|
dep_name = if forbidden_formulae.include?(dep.name)
|
||||||
|
dep.name
|
||||||
|
elsif dep.tap.present? &&
|
||||||
|
(dep_full_name = "#{dep.tap}/#{dep.name}") &&
|
||||||
|
forbidden_formulae.include?(dep_full_name)
|
||||||
|
dep_full_name
|
||||||
|
else
|
||||||
|
next
|
||||||
|
end
|
||||||
|
|
||||||
|
raise CannotInstallFormulaError, <<~EOS
|
||||||
|
The installation of #{formula.name} has a dependency #{dep_name}
|
||||||
|
but the #{dep_name} formula was forbidden by #{owner} in `HOMEBREW_FORBIDDEN_FORMULAE`.#{owner_contact}
|
||||||
|
EOS
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return if only_deps?
|
||||||
|
|
||||||
|
formula_name = if forbidden_formulae.include?(formula.name)
|
||||||
|
formula.name
|
||||||
|
elsif forbidden_formulae.include?(formula.full_name)
|
||||||
|
formula.full_name
|
||||||
|
else
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
raise CannotInstallFormulaError, <<~EOS
|
||||||
|
The installation of #{formula_name} was forbidden by #{owner}
|
||||||
|
in `HOMEBREW_FORBIDDEN_FORMULAE`.#{owner_contact}
|
||||||
|
EOS
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
attr_predicate :hold_locks?
|
attr_predicate :hold_locks?
|
||||||
@ -1349,39 +1480,4 @@ on_request: installed_on_request?, options:)
|
|||||||
|
|
||||||
$stderr.puts @requirement_messages
|
$stderr.puts @requirement_messages
|
||||||
end
|
end
|
||||||
|
|
||||||
sig { void }
|
|
||||||
def forbidden_license_check
|
|
||||||
forbidden_licenses = Homebrew::EnvConfig.forbidden_licenses.to_s.dup
|
|
||||||
SPDX::ALLOWED_LICENSE_SYMBOLS.each do |s|
|
|
||||||
pattern = /#{s.to_s.tr("_", " ")}/i
|
|
||||||
forbidden_licenses.sub!(pattern, s.to_s)
|
|
||||||
end
|
|
||||||
forbidden_licenses = forbidden_licenses.split.to_h do |license|
|
|
||||||
[license, SPDX.license_version_info(license)]
|
|
||||||
end
|
|
||||||
|
|
||||||
return if forbidden_licenses.blank?
|
|
||||||
return if ignore_deps?
|
|
||||||
|
|
||||||
compute_dependencies.each do |(dep, _options)|
|
|
||||||
dep_f = dep.to_formula
|
|
||||||
next unless SPDX.licenses_forbid_installation? dep_f.license, forbidden_licenses
|
|
||||||
|
|
||||||
raise CannotInstallFormulaError, <<~EOS
|
|
||||||
The installation of #{formula.name} has a dependency on #{dep.name} where all
|
|
||||||
its licenses are forbidden by HOMEBREW_FORBIDDEN_LICENSES:
|
|
||||||
#{SPDX.license_expression_to_string dep_f.license}.
|
|
||||||
EOS
|
|
||||||
end
|
|
||||||
|
|
||||||
return if only_deps?
|
|
||||||
|
|
||||||
return unless SPDX.licenses_forbid_installation? formula.license, forbidden_licenses
|
|
||||||
|
|
||||||
raise CannotInstallFormulaError, <<~EOS
|
|
||||||
#{formula.name}'s licenses are all forbidden by HOMEBREW_FORBIDDEN_LICENSES:
|
|
||||||
#{SPDX.license_expression_to_string formula.license}.
|
|
||||||
EOS
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
@ -105,9 +105,24 @@ module Homebrew::EnvConfig
|
|||||||
sig { returns(Integer) }
|
sig { returns(Integer) }
|
||||||
def fail_log_lines; end
|
def fail_log_lines; end
|
||||||
|
|
||||||
|
sig { returns(T.nilable(::String)) }
|
||||||
|
def forbidden_casks; end
|
||||||
|
|
||||||
|
sig { returns(T.nilable(::String)) }
|
||||||
|
def forbidden_formulae; end
|
||||||
|
|
||||||
sig { returns(T.nilable(::String)) }
|
sig { returns(T.nilable(::String)) }
|
||||||
def forbidden_licenses; end
|
def forbidden_licenses; end
|
||||||
|
|
||||||
|
sig { returns(String) }
|
||||||
|
def forbidden_owner; end
|
||||||
|
|
||||||
|
sig { returns(T.nilable(::String)) }
|
||||||
|
def forbidden_owner_contact; end
|
||||||
|
|
||||||
|
sig { returns(T.nilable(::String)) }
|
||||||
|
def forbidden_taps; end
|
||||||
|
|
||||||
sig { returns(T::Boolean) }
|
sig { returns(T::Boolean) }
|
||||||
def force_brewed_ca_certificates?; end
|
def force_brewed_ca_certificates?; end
|
||||||
|
|
||||||
|
@ -39,12 +39,14 @@ class Tap
|
|||||||
#{HOMEBREW_TAP_STYLE_EXCEPTIONS_DIR}/*.json
|
#{HOMEBREW_TAP_STYLE_EXCEPTIONS_DIR}/*.json
|
||||||
].freeze
|
].freeze
|
||||||
|
|
||||||
|
class InvalidNameError < ArgumentError; end
|
||||||
|
|
||||||
sig { params(user: String, repo: String).returns(Tap) }
|
sig { params(user: String, repo: String).returns(Tap) }
|
||||||
def self.fetch(user, repo = T.unsafe(nil))
|
def self.fetch(user, repo = T.unsafe(nil))
|
||||||
user, repo = user.split("/", 2) if repo.nil?
|
user, repo = user.split("/", 2) if repo.nil?
|
||||||
|
|
||||||
if [user, repo].any? { |part| part.nil? || part.include?("/") }
|
if [user, repo].any? { |part| part.nil? || part.include?("/") }
|
||||||
raise ArgumentError, "Invalid tap name: '#{[*user, *repo].join("/")}'"
|
raise InvalidNameError, "Invalid tap name: '#{[*user, *repo].join("/")}'"
|
||||||
end
|
end
|
||||||
|
|
||||||
user = T.must(user)
|
user = T.must(user)
|
||||||
|
@ -324,4 +324,77 @@ RSpec.describe Cask::Installer, :cask do
|
|||||||
expect(Cask::CaskLoader.load(cask_path("local-caffeine"))).not_to be_installed
|
expect(Cask::CaskLoader.load(cask_path("local-caffeine"))).not_to be_installed
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "#forbidden_tap_check" do
|
||||||
|
it "raises on forbidden tap on cask" do
|
||||||
|
ENV["HOMEBREW_FORBIDDEN_TAPS"] = tap = "homebrew/forbidden"
|
||||||
|
|
||||||
|
cask = Cask::Cask.new("homebrew-forbidden-tap", tap: Tap.fetch(tap)) do
|
||||||
|
url "file://#{TEST_FIXTURE_DIR}/cask/container.tar.gz"
|
||||||
|
end
|
||||||
|
|
||||||
|
expect do
|
||||||
|
described_class.new(cask).forbidden_tap_check
|
||||||
|
end.to raise_error(Cask::CaskCannotBeInstalledError, /has the tap #{tap}/)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "raises on forbidden tap on dependency" do
|
||||||
|
ENV["HOMEBREW_FORBIDDEN_TAPS"] = dep_tap = "homebrew/forbidden"
|
||||||
|
dep_name = "homebrew-forbidden-dependency-tap"
|
||||||
|
dep_path = Tap.fetch(dep_tap).new_formula_path(dep_name)
|
||||||
|
dep_path.parent.mkpath
|
||||||
|
dep_path.write <<~RUBY
|
||||||
|
class #{Formulary.class_s(dep_name)} < Formula
|
||||||
|
url "foo"
|
||||||
|
version "0.1"
|
||||||
|
end
|
||||||
|
RUBY
|
||||||
|
Formulary.cache.delete(dep_path)
|
||||||
|
|
||||||
|
cask = Cask::Cask.new("homebrew-forbidden-dependent-tap") do
|
||||||
|
url "file://#{TEST_FIXTURE_DIR}/cask/container.tar.gz"
|
||||||
|
depends_on formula: dep_name
|
||||||
|
end
|
||||||
|
|
||||||
|
expect do
|
||||||
|
described_class.new(cask).forbidden_tap_check
|
||||||
|
end.to raise_error(Cask::CaskCannotBeInstalledError, /but the #{dep_tap} tap was forbidden/)
|
||||||
|
ensure
|
||||||
|
dep_path.parent.parent.rmtree
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "#forbidden_cask_and_formula_check" do
|
||||||
|
it "raises on forbidden cask" do
|
||||||
|
ENV["HOMEBREW_FORBIDDEN_CASKS"] = cask_name = "homebrew-forbidden-cask"
|
||||||
|
cask = Cask::Cask.new(cask_name) do
|
||||||
|
url "file://#{TEST_FIXTURE_DIR}/cask/container.tar.gz"
|
||||||
|
end
|
||||||
|
|
||||||
|
expect do
|
||||||
|
described_class.new(cask).forbidden_cask_and_formula_check
|
||||||
|
end.to raise_error(Cask::CaskCannotBeInstalledError, /#{cask_name} was forbidden/)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "raises on forbidden dependency" do
|
||||||
|
ENV["HOMEBREW_FORBIDDEN_FORMULAE"] = dep_name = "homebrew-forbidden-dependency-formula"
|
||||||
|
dep_path = CoreTap.instance.new_formula_path(dep_name)
|
||||||
|
dep_path.write <<~RUBY
|
||||||
|
class #{Formulary.class_s(dep_name)} < Formula
|
||||||
|
url "foo"
|
||||||
|
version "0.1"
|
||||||
|
end
|
||||||
|
RUBY
|
||||||
|
Formulary.cache.delete(dep_path)
|
||||||
|
|
||||||
|
cask = Cask::Cask.new("homebrew-forbidden-dependent-cask") do
|
||||||
|
url "file://#{TEST_FIXTURE_DIR}/cask/container.tar.gz"
|
||||||
|
depends_on formula: dep_name
|
||||||
|
end
|
||||||
|
|
||||||
|
expect do
|
||||||
|
described_class.new(cask).forbidden_cask_and_formula_check
|
||||||
|
end.to raise_error(Cask::CaskCannotBeInstalledError, /#{dep_name} formula was forbidden/)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
@ -312,7 +312,7 @@ RSpec.describe Homebrew::CLI::NamedArgs do
|
|||||||
|
|
||||||
it "raises an error for invalid tap" do
|
it "raises an error for invalid tap" do
|
||||||
taps = described_class.new("homebrew/foo", "barbaz")
|
taps = described_class.new("homebrew/foo", "barbaz")
|
||||||
expect { taps.to_taps }.to raise_error(ArgumentError, /Invalid tap name/)
|
expect { taps.to_taps }.to raise_error(Tap::InvalidNameError, /Invalid tap name/)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -333,7 +333,7 @@ RSpec.describe Homebrew::CLI::NamedArgs do
|
|||||||
|
|
||||||
it "raises an error for invalid tap" do
|
it "raises an error for invalid tap" do
|
||||||
taps = described_class.new("homebrew/foo", "barbaz")
|
taps = described_class.new("homebrew/foo", "barbaz")
|
||||||
expect { taps.to_installed_taps }.to raise_error(ArgumentError, /Invalid tap name/)
|
expect { taps.to_installed_taps }.to raise_error(Tap::InvalidNameError, /Invalid tap name/)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -170,6 +170,197 @@ RSpec.describe FormulaInstaller do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "#forbidden_license_check" do
|
||||||
|
it "raises on forbidden license on formula" do
|
||||||
|
ENV["HOMEBREW_FORBIDDEN_LICENSES"] = "AGPL-3.0"
|
||||||
|
|
||||||
|
f_name = "homebrew-forbidden-license"
|
||||||
|
f_path = CoreTap.instance.new_formula_path(f_name)
|
||||||
|
f_path.write <<~RUBY
|
||||||
|
class #{Formulary.class_s(f_name)} < Formula
|
||||||
|
url "foo"
|
||||||
|
version "0.1"
|
||||||
|
license "AGPL-3.0"
|
||||||
|
end
|
||||||
|
RUBY
|
||||||
|
Formulary.cache.delete(f_path)
|
||||||
|
|
||||||
|
f = Formulary.factory(f_name)
|
||||||
|
fi = described_class.new(f)
|
||||||
|
|
||||||
|
expect do
|
||||||
|
fi.forbidden_license_check
|
||||||
|
end.to raise_error(CannotInstallFormulaError, /#{f_name}'s licenses are all forbidden/)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "raises on forbidden license on formula with contact instructions" do
|
||||||
|
ENV["HOMEBREW_FORBIDDEN_LICENSES"] = "AGPL-3.0"
|
||||||
|
ENV["HOMEBREW_FORBIDDEN_OWNER"] = owner = "your dog"
|
||||||
|
ENV["HOMEBREW_FORBIDDEN_OWNER_CONTACT"] = contact = "Woof loudly to get this unblocked."
|
||||||
|
|
||||||
|
f_name = "homebrew-forbidden-license"
|
||||||
|
f_path = CoreTap.instance.new_formula_path(f_name)
|
||||||
|
f_path.write <<~RUBY
|
||||||
|
class #{Formulary.class_s(f_name)} < Formula
|
||||||
|
url "foo"
|
||||||
|
version "0.1"
|
||||||
|
license "AGPL-3.0"
|
||||||
|
end
|
||||||
|
RUBY
|
||||||
|
Formulary.cache.delete(f_path)
|
||||||
|
|
||||||
|
f = Formulary.factory(f_name)
|
||||||
|
fi = described_class.new(f)
|
||||||
|
|
||||||
|
expect do
|
||||||
|
fi.forbidden_license_check
|
||||||
|
end.to raise_error(CannotInstallFormulaError, /#{owner}.+\n#{contact}/m)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "raises on forbidden license on dependency" do
|
||||||
|
ENV["HOMEBREW_FORBIDDEN_LICENSES"] = "GPL-3.0"
|
||||||
|
|
||||||
|
dep_name = "homebrew-forbidden-dependency-license"
|
||||||
|
dep_path = CoreTap.instance.new_formula_path(dep_name)
|
||||||
|
dep_path.write <<~RUBY
|
||||||
|
class #{Formulary.class_s(dep_name)} < Formula
|
||||||
|
url "foo"
|
||||||
|
version "0.1"
|
||||||
|
license "GPL-3.0"
|
||||||
|
end
|
||||||
|
RUBY
|
||||||
|
Formulary.cache.delete(dep_path)
|
||||||
|
|
||||||
|
f_name = "homebrew-forbidden-dependent-license"
|
||||||
|
f_path = CoreTap.instance.new_formula_path(f_name)
|
||||||
|
f_path.write <<~RUBY
|
||||||
|
class #{Formulary.class_s(f_name)} < Formula
|
||||||
|
url "foo"
|
||||||
|
version "0.1"
|
||||||
|
depends_on "#{dep_name}"
|
||||||
|
end
|
||||||
|
RUBY
|
||||||
|
Formulary.cache.delete(f_path)
|
||||||
|
|
||||||
|
f = Formulary.factory(f_name)
|
||||||
|
fi = described_class.new(f)
|
||||||
|
|
||||||
|
expect do
|
||||||
|
fi.forbidden_license_check
|
||||||
|
end.to raise_error(CannotInstallFormulaError, /dependency on #{dep_name} where all/)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "#forbidden_tap_check" do
|
||||||
|
it "raises on forbidden tap on formula" do
|
||||||
|
ENV["HOMEBREW_FORBIDDEN_TAPS"] = f_tap = "homebrew/forbidden"
|
||||||
|
f_name = "homebrew-forbidden-tap"
|
||||||
|
f_path = Tap.fetch(f_tap).new_formula_path(f_name)
|
||||||
|
f_path.parent.mkpath
|
||||||
|
f_path.write <<~RUBY
|
||||||
|
class #{Formulary.class_s(f_name)} < Formula
|
||||||
|
url "foo"
|
||||||
|
version "0.1"
|
||||||
|
end
|
||||||
|
RUBY
|
||||||
|
Formulary.cache.delete(f_path)
|
||||||
|
|
||||||
|
f = Formulary.factory("#{f_tap}/#{f_name}")
|
||||||
|
fi = described_class.new(f)
|
||||||
|
|
||||||
|
expect do
|
||||||
|
fi.forbidden_tap_check
|
||||||
|
end.to raise_error(CannotInstallFormulaError, /has the tap #{f_tap}/)
|
||||||
|
ensure
|
||||||
|
f_path.parent.parent.rmtree
|
||||||
|
end
|
||||||
|
|
||||||
|
it "raises on forbidden tap on dependency" do
|
||||||
|
ENV["HOMEBREW_FORBIDDEN_TAPS"] = dep_tap = "homebrew/forbidden"
|
||||||
|
dep_name = "homebrew-forbidden-dependency-tap"
|
||||||
|
dep_path = Tap.fetch(dep_tap).new_formula_path(dep_name)
|
||||||
|
dep_path.parent.mkpath
|
||||||
|
dep_path.write <<~RUBY
|
||||||
|
class #{Formulary.class_s(dep_name)} < Formula
|
||||||
|
url "foo"
|
||||||
|
version "0.1"
|
||||||
|
end
|
||||||
|
RUBY
|
||||||
|
Formulary.cache.delete(dep_path)
|
||||||
|
|
||||||
|
f_name = "homebrew-forbidden-dependent-tap"
|
||||||
|
f_path = CoreTap.instance.new_formula_path(f_name)
|
||||||
|
f_path.write <<~RUBY
|
||||||
|
class #{Formulary.class_s(f_name)} < Formula
|
||||||
|
url "foo"
|
||||||
|
version "0.1"
|
||||||
|
depends_on "#{dep_name}"
|
||||||
|
end
|
||||||
|
RUBY
|
||||||
|
Formulary.cache.delete(f_path)
|
||||||
|
|
||||||
|
f = Formulary.factory(f_name)
|
||||||
|
fi = described_class.new(f)
|
||||||
|
|
||||||
|
expect do
|
||||||
|
fi.forbidden_tap_check
|
||||||
|
end.to raise_error(CannotInstallFormulaError, /but the #{dep_tap} tap was forbidden/)
|
||||||
|
ensure
|
||||||
|
dep_path.parent.parent.rmtree
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "#forbidden_formula_check" do
|
||||||
|
it "raises on forbidden formula" do
|
||||||
|
ENV["HOMEBREW_FORBIDDEN_FORMULAE"] = f_name = "homebrew-forbidden-formula"
|
||||||
|
f_path = CoreTap.instance.new_formula_path(f_name)
|
||||||
|
f_path.write <<~RUBY
|
||||||
|
class #{Formulary.class_s(f_name)} < Formula
|
||||||
|
url "foo"
|
||||||
|
version "0.1"
|
||||||
|
end
|
||||||
|
RUBY
|
||||||
|
Formulary.cache.delete(f_path)
|
||||||
|
|
||||||
|
f = Formulary.factory(f_name)
|
||||||
|
fi = described_class.new(f)
|
||||||
|
|
||||||
|
expect do
|
||||||
|
fi.forbidden_formula_check
|
||||||
|
end.to raise_error(CannotInstallFormulaError, /#{f_name} was forbidden/)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "raises on forbidden dependency" do
|
||||||
|
ENV["HOMEBREW_FORBIDDEN_FORMULAE"] = dep_name = "homebrew-forbidden-dependency-formula"
|
||||||
|
dep_path = CoreTap.instance.new_formula_path(dep_name)
|
||||||
|
dep_path.write <<~RUBY
|
||||||
|
class #{Formulary.class_s(dep_name)} < Formula
|
||||||
|
url "foo"
|
||||||
|
version "0.1"
|
||||||
|
end
|
||||||
|
RUBY
|
||||||
|
Formulary.cache.delete(dep_path)
|
||||||
|
|
||||||
|
f_name = "homebrew-forbidden-dependent-formula"
|
||||||
|
f_path = CoreTap.instance.new_formula_path(f_name)
|
||||||
|
f_path.write <<~RUBY
|
||||||
|
class #{Formulary.class_s(f_name)} < Formula
|
||||||
|
url "foo"
|
||||||
|
version "0.1"
|
||||||
|
depends_on "#{dep_name}"
|
||||||
|
end
|
||||||
|
RUBY
|
||||||
|
Formulary.cache.delete(f_path)
|
||||||
|
|
||||||
|
f = Formulary.factory(f_name)
|
||||||
|
fi = described_class.new(f)
|
||||||
|
|
||||||
|
expect do
|
||||||
|
fi.forbidden_formula_check
|
||||||
|
end.to raise_error(CannotInstallFormulaError, /#{dep_name} formula was forbidden/)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
specify "install fails with BuildError when a system() call fails" do
|
specify "install fails with BuildError when a system() call fails" do
|
||||||
ENV["HOMEBREW_TEST_NO_EXIT_CLEANUP"] = "1"
|
ENV["HOMEBREW_TEST_NO_EXIT_CLEANUP"] = "1"
|
||||||
ENV["FAILBALL_BUILD_ERROR"] = "1"
|
ENV["FAILBALL_BUILD_ERROR"] = "1"
|
||||||
|
@ -105,15 +105,15 @@ RSpec.describe Tap do
|
|||||||
|
|
||||||
expect do
|
expect do
|
||||||
described_class.fetch("foo")
|
described_class.fetch("foo")
|
||||||
end.to raise_error(ArgumentError, /Invalid tap name/)
|
end.to raise_error(Tap::InvalidNameError, /Invalid tap name/)
|
||||||
|
|
||||||
expect do
|
expect do
|
||||||
described_class.fetch("homebrew/homebrew/bar")
|
described_class.fetch("homebrew/homebrew/bar")
|
||||||
end.to raise_error(ArgumentError, /Invalid tap name/)
|
end.to raise_error(Tap::InvalidNameError, /Invalid tap name/)
|
||||||
|
|
||||||
expect do
|
expect do
|
||||||
described_class.fetch("homebrew", "homebrew/baz")
|
described_class.fetch("homebrew", "homebrew/baz")
|
||||||
end.to raise_error(ArgumentError, /Invalid tap name/)
|
end.to raise_error(Tap::InvalidNameError, /Invalid tap name/)
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "::from_path" do
|
describe "::from_path" do
|
||||||
|
@ -3647,11 +3647,36 @@ command execution e.g. `$(cat file)`.
|
|||||||
|
|
||||||
*Default:* `15`.
|
*Default:* `15`.
|
||||||
|
|
||||||
|
`HOMEBREW_FORBIDDEN_CASKS`
|
||||||
|
|
||||||
|
: A space-separated list of casks. Homebrew will refuse to install a cask if it
|
||||||
|
or any of its dependencies is on this list.
|
||||||
|
|
||||||
|
`HOMEBREW_FORBIDDEN_FORMULAE`
|
||||||
|
|
||||||
|
: A space-separated list of formulae. Homebrew will refuse to install a formula
|
||||||
|
or cask if it or any of its dependencies is on this list.
|
||||||
|
|
||||||
`HOMEBREW_FORBIDDEN_LICENSES`
|
`HOMEBREW_FORBIDDEN_LICENSES`
|
||||||
|
|
||||||
: A space-separated list of licenses. Homebrew will refuse to install a formula
|
: A space-separated list of licenses. Homebrew will refuse to install a formula
|
||||||
if it or any of its dependencies has a license on this list.
|
if it or any of its dependencies has a license on this list.
|
||||||
|
|
||||||
|
`HOMEBREW_FORBIDDEN_OWNER`
|
||||||
|
|
||||||
|
: The person who has set any `HOMEBREW_FORBIDDEN_*` variables.
|
||||||
|
|
||||||
|
*Default:* `you`.
|
||||||
|
|
||||||
|
`HOMEBREW_FORBIDDEN_OWNER_CONTACT`
|
||||||
|
|
||||||
|
: How to contact the `HOMEBREW_FORBIDDEN_OWNER`, if set and necessary.
|
||||||
|
|
||||||
|
`HOMEBREW_FORBIDDEN_TAPS`
|
||||||
|
|
||||||
|
: A space-separated list of taps. Homebrew will refuse to install a formula if
|
||||||
|
it or any of its dependencies is in a tap on this list.
|
||||||
|
|
||||||
`HOMEBREW_FORCE_BREWED_CA_CERTIFICATES`
|
`HOMEBREW_FORCE_BREWED_CA_CERTIFICATES`
|
||||||
|
|
||||||
: If set, always use a Homebrew-installed `ca-certificates` rather than the
|
: If set, always use a Homebrew-installed `ca-certificates` rather than the
|
||||||
|
@ -2368,9 +2368,28 @@ Output this many lines of output on formula \fBsystem\fP failures\.
|
|||||||
\fIDefault:\fP \fB15\fP\&\.
|
\fIDefault:\fP \fB15\fP\&\.
|
||||||
.RE
|
.RE
|
||||||
.TP
|
.TP
|
||||||
|
\fBHOMEBREW_FORBIDDEN_CASKS\fP
|
||||||
|
A space\-separated list of casks\. Homebrew will refuse to install a cask if it or any of its dependencies is on this list\.
|
||||||
|
.TP
|
||||||
|
\fBHOMEBREW_FORBIDDEN_FORMULAE\fP
|
||||||
|
A space\-separated list of formulae\. Homebrew will refuse to install a formula or cask if it or any of its dependencies is on this list\.
|
||||||
|
.TP
|
||||||
\fBHOMEBREW_FORBIDDEN_LICENSES\fP
|
\fBHOMEBREW_FORBIDDEN_LICENSES\fP
|
||||||
A space\-separated list of licenses\. Homebrew will refuse to install a formula if it or any of its dependencies has a license on this list\.
|
A space\-separated list of licenses\. Homebrew will refuse to install a formula if it or any of its dependencies has a license on this list\.
|
||||||
.TP
|
.TP
|
||||||
|
\fBHOMEBREW_FORBIDDEN_OWNER\fP
|
||||||
|
The person who has set any \fBHOMEBREW_FORBIDDEN_*\fP variables\.
|
||||||
|
.RS
|
||||||
|
.P
|
||||||
|
\fIDefault:\fP \fByou\fP\&\.
|
||||||
|
.RE
|
||||||
|
.TP
|
||||||
|
\fBHOMEBREW_FORBIDDEN_OWNER_CONTACT\fP
|
||||||
|
How to contact the \fBHOMEBREW_FORBIDDEN_OWNER\fP, if set and necessary\.
|
||||||
|
.TP
|
||||||
|
\fBHOMEBREW_FORBIDDEN_TAPS\fP
|
||||||
|
A space\-separated list of taps\. Homebrew will refuse to install a formula if it or any of its dependencies is in a tap on this list\.
|
||||||
|
.TP
|
||||||
\fBHOMEBREW_FORCE_BREWED_CA_CERTIFICATES\fP
|
\fBHOMEBREW_FORCE_BREWED_CA_CERTIFICATES\fP
|
||||||
If set, always use a Homebrew\-installed \fBca\-certificates\fP rather than the system version\. Automatically set if the system version is too old\.
|
If set, always use a Homebrew\-installed \fBca\-certificates\fP rather than the system version\. Automatically set if the system version is too old\.
|
||||||
.TP
|
.TP
|
||||||
|
Loading…
x
Reference in New Issue
Block a user