Merge pull request #17213 from Homebrew/allowed-taps
env_config: add `HOMEBREW_ALLOWED_TAPS`
This commit is contained in:
commit
fc13eb83c8
@ -574,15 +574,7 @@ on_request: true)
|
|||||||
|
|
||||||
sig { void }
|
sig { void }
|
||||||
def forbidden_tap_check
|
def forbidden_tap_check
|
||||||
forbidden_taps = Homebrew::EnvConfig.forbidden_taps
|
return if Tap.allowed_taps.blank? && Tap.forbidden_taps.blank?
|
||||||
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 = Homebrew::EnvConfig.forbidden_owner
|
||||||
owner_contact = if (contact = Homebrew::EnvConfig.forbidden_owner_contact.presence)
|
owner_contact = if (contact = Homebrew::EnvConfig.forbidden_owner_contact.presence)
|
||||||
@ -592,27 +584,31 @@ on_request: true)
|
|||||||
unless skip_cask_deps?
|
unless skip_cask_deps?
|
||||||
cask_and_formula_dependencies.each do |cask_or_formula|
|
cask_and_formula_dependencies.each do |cask_or_formula|
|
||||||
dep_tap = cask_or_formula.tap
|
dep_tap = cask_or_formula.tap
|
||||||
next if dep_tap.blank?
|
next if dep_tap.blank? || (dep_tap.allowed_by_env? && !dep_tap.forbidden_by_env?)
|
||||||
next unless forbidden_taps_set.include?(dep_tap)
|
|
||||||
|
|
||||||
dep_full_name = cask_or_formula.full_name
|
dep_full_name = cask_or_formula.full_name
|
||||||
raise CaskCannotBeInstalledError.new(@cask, <<~EOS
|
error_message = +"The installation of #{@cask} has a dependency #{dep_full_name}\n" \
|
||||||
The installation of #{@cask} has a dependency #{dep_full_name}
|
"from the #{dep_tap} tap but #{owner} "
|
||||||
but the #{dep_tap} tap was forbidden by #{owner} in `HOMEBREW_FORBIDDEN_TAPS`.#{owner_contact}
|
error_message << "has not allowed this tap in `HOMEBREW_ALLOWED_TAPS`" unless dep_tap.allowed_by_env?
|
||||||
EOS
|
error_message << " and\n" if !dep_tap.allowed_by_env? && dep_tap.forbidden_by_env?
|
||||||
)
|
error_message << "has forbidden this tap in `HOMEBREW_FORBIDDEN_TAPS`" if dep_tap.forbidden_by_env?
|
||||||
|
error_message << ".#{owner_contact}"
|
||||||
|
|
||||||
|
raise CaskCannotBeInstalledError.new(@cask, error_message)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
cask_tap = @cask.tap
|
cask_tap = @cask.tap
|
||||||
return if cask_tap.blank?
|
return if cask_tap.blank? || (cask_tap.allowed_by_env? && !cask_tap.forbidden_by_env?)
|
||||||
return unless forbidden_taps_set.include?(cask_tap)
|
|
||||||
|
|
||||||
raise CaskCannotBeInstalledError.new(@cask, <<~EOS
|
error_message = +"The installation of #{@cask.full_name} has the tap #{cask_tap}\n" \
|
||||||
The installation of #{@cask.full_name} has the tap #{cask_tap}
|
"but #{owner} "
|
||||||
which was forbidden by #{owner} in `HOMEBREW_FORBIDDEN_TAPS`.#{owner_contact}
|
error_message << "has not allowed this tap in `HOMEBREW_ALLOWED_TAPS`" unless cask_tap.allowed_by_env?
|
||||||
EOS
|
error_message << " and\n" if !cask_tap.allowed_by_env? && cask_tap.forbidden_by_env?
|
||||||
)
|
error_message << "has forbidden this tap in `HOMEBREW_FORBIDDEN_TAPS`" if cask_tap.forbidden_by_env?
|
||||||
|
error_message << ".#{owner_contact}"
|
||||||
|
|
||||||
|
raise CaskCannotBeInstalledError.new(@cask, error_message)
|
||||||
end
|
end
|
||||||
|
|
||||||
sig { void }
|
sig { void }
|
||||||
|
|||||||
@ -11,6 +11,11 @@ module Homebrew
|
|||||||
module_function
|
module_function
|
||||||
|
|
||||||
ENVS = {
|
ENVS = {
|
||||||
|
HOMEBREW_ALLOWED_TAPS: {
|
||||||
|
description: "A space-separated list of taps. Homebrew will refuse to install a " \
|
||||||
|
"formula unless it and all of its dependencies are in an official tap " \
|
||||||
|
"or in a tap on this list.",
|
||||||
|
},
|
||||||
HOMEBREW_API_AUTO_UPDATE_SECS: {
|
HOMEBREW_API_AUTO_UPDATE_SECS: {
|
||||||
description: "Check Homebrew's API for new formulae or cask data every " \
|
description: "Check Homebrew's API for new formulae or cask data every " \
|
||||||
"`HOMEBREW_API_AUTO_UPDATE_SECS` seconds. Alternatively, disable API auto-update " \
|
"`HOMEBREW_API_AUTO_UPDATE_SECS` seconds. Alternatively, disable API auto-update " \
|
||||||
|
|||||||
@ -1391,15 +1391,7 @@ on_request: installed_on_request?, options:)
|
|||||||
|
|
||||||
sig { void }
|
sig { void }
|
||||||
def forbidden_tap_check
|
def forbidden_tap_check
|
||||||
forbidden_taps = Homebrew::EnvConfig.forbidden_taps
|
return if Tap.allowed_taps.blank? && Tap.forbidden_taps.blank?
|
||||||
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 = Homebrew::EnvConfig.forbidden_owner
|
||||||
owner_contact = if (contact = Homebrew::EnvConfig.forbidden_owner_contact.presence)
|
owner_contact = if (contact = Homebrew::EnvConfig.forbidden_owner_contact.presence)
|
||||||
@ -1409,26 +1401,32 @@ on_request: installed_on_request?, options:)
|
|||||||
unless ignore_deps?
|
unless ignore_deps?
|
||||||
compute_dependencies.each do |(dep, _options)|
|
compute_dependencies.each do |(dep, _options)|
|
||||||
dep_tap = dep.tap
|
dep_tap = dep.tap
|
||||||
next if dep_tap.blank?
|
next if dep_tap.blank? || (dep_tap.allowed_by_env? && !dep_tap.forbidden_by_env?)
|
||||||
next unless forbidden_taps_set.include?(dep_tap)
|
|
||||||
|
|
||||||
raise CannotInstallFormulaError, <<~EOS
|
error_message = +"The installation of #{formula.name} has a dependency #{dep.name}\n" \
|
||||||
The installation of #{formula.name} has a dependency #{dep.name}
|
"from the #{dep_tap} tap but #{owner} "
|
||||||
but the #{dep_tap} tap was forbidden by #{owner} in `HOMEBREW_FORBIDDEN_TAPS`.#{owner_contact}
|
error_message << "has not allowed this tap in `HOMEBREW_ALLOWED_TAPS`" unless dep_tap.allowed_by_env?
|
||||||
EOS
|
error_message << " and\n" if !dep_tap.allowed_by_env? && dep_tap.forbidden_by_env?
|
||||||
|
error_message << "has forbidden this tap in `HOMEBREW_FORBIDDEN_TAPS`" if dep_tap.forbidden_by_env?
|
||||||
|
error_message << ".#{owner_contact}"
|
||||||
|
|
||||||
|
raise CannotInstallFormulaError, error_message
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return if only_deps?
|
return if only_deps?
|
||||||
|
|
||||||
formula_tap = formula.tap
|
formula_tap = formula.tap
|
||||||
return if formula_tap.blank?
|
return if formula_tap.blank? || (formula_tap.allowed_by_env? && !formula_tap.forbidden_by_env?)
|
||||||
return unless forbidden_taps_set.include?(formula_tap)
|
|
||||||
|
|
||||||
raise CannotInstallFormulaError, <<~EOS
|
error_message = +"The installation of #{formula.full_name} has the tap #{formula_tap}\n" \
|
||||||
The installation of #{formula.full_name} has the tap #{formula_tap}
|
"but #{owner} "
|
||||||
which was forbidden by #{owner} in `HOMEBREW_FORBIDDEN_TAPS`.#{owner_contact}
|
error_message << "has not allowed this tap in `HOMEBREW_ALLOWED_TAPS`" unless formula_tap.allowed_by_env?
|
||||||
EOS
|
error_message << " and\n" if !formula_tap.allowed_by_env? && formula_tap.forbidden_by_env?
|
||||||
|
error_message << "has forbidden this tap in `HOMEBREW_FORBIDDEN_TAPS`" if formula_tap.forbidden_by_env?
|
||||||
|
error_message << ".#{owner_contact}"
|
||||||
|
|
||||||
|
raise CannotInstallFormulaError, error_message
|
||||||
end
|
end
|
||||||
|
|
||||||
sig { void }
|
sig { void }
|
||||||
|
|||||||
@ -9,6 +9,9 @@ module Homebrew::EnvConfig
|
|||||||
sig { returns(T.nilable(::String)) }
|
sig { returns(T.nilable(::String)) }
|
||||||
def all_proxy; end
|
def all_proxy; end
|
||||||
|
|
||||||
|
sig { returns(T.nilable(::String)) }
|
||||||
|
def allowed_taps; end
|
||||||
|
|
||||||
sig { returns(Integer) }
|
sig { returns(Integer) }
|
||||||
def api_auto_update_secs; end
|
def api_auto_update_secs; end
|
||||||
|
|
||||||
|
|||||||
@ -132,6 +132,36 @@ class Tap
|
|||||||
false
|
false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
sig { returns(T::Set[Tap]) }
|
||||||
|
def self.allowed_taps
|
||||||
|
cache_key = :"allowed_taps_#{Homebrew::EnvConfig.allowed_taps.to_s.tr(" ", "_")}"
|
||||||
|
cache[cache_key] ||= begin
|
||||||
|
allowed_tap_list = Homebrew::EnvConfig.allowed_taps.to_s.split
|
||||||
|
|
||||||
|
Set.new(allowed_tap_list.filter_map do |tap|
|
||||||
|
Tap.fetch(tap)
|
||||||
|
rescue Tap::InvalidNameError
|
||||||
|
opoo "Invalid tap name in `HOMEBREW_ALLOWED_TAPS`: #{tap}"
|
||||||
|
nil
|
||||||
|
end).freeze
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
sig { returns(T::Set[Tap]) }
|
||||||
|
def self.forbidden_taps
|
||||||
|
cache_key = :"forbidden_taps_#{Homebrew::EnvConfig.forbidden_taps.to_s.tr(" ", "_")}"
|
||||||
|
cache[cache_key] ||= begin
|
||||||
|
forbidden_tap_list = Homebrew::EnvConfig.forbidden_taps.to_s.split
|
||||||
|
|
||||||
|
Set.new(forbidden_tap_list.filter_map do |tap|
|
||||||
|
Tap.fetch(tap)
|
||||||
|
rescue Tap::InvalidNameError
|
||||||
|
opoo "Invalid tap name in `HOMEBREW_FORBIDDEN_TAPS`: #{tap}"
|
||||||
|
nil
|
||||||
|
end).freeze
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
# @api public
|
# @api public
|
||||||
extend Enumerable
|
extend Enumerable
|
||||||
|
|
||||||
@ -1056,6 +1086,20 @@ class Tap
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
sig { returns(T::Boolean) }
|
||||||
|
def allowed_by_env?
|
||||||
|
@allowed_by_env ||= begin
|
||||||
|
allowed_taps = self.class.allowed_taps
|
||||||
|
|
||||||
|
official? || allowed_taps.blank? || allowed_taps.include?(self)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
sig { returns(T::Boolean) }
|
||||||
|
def forbidden_by_env?
|
||||||
|
@forbidden_by_env ||= self.class.forbidden_taps.include?(self)
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
sig { params(file: Pathname).returns(T.any(T::Array[String], Hash)) }
|
sig { params(file: Pathname).returns(T.any(T::Array[String], Hash)) }
|
||||||
|
|||||||
@ -326,22 +326,48 @@ RSpec.describe Cask::Installer, :cask do
|
|||||||
end
|
end
|
||||||
|
|
||||||
describe "#forbidden_tap_check" do
|
describe "#forbidden_tap_check" do
|
||||||
it "raises on forbidden tap on cask" do
|
before do
|
||||||
ENV["HOMEBREW_FORBIDDEN_TAPS"] = tap = "homebrew/forbidden"
|
allow(Tap).to receive_messages(allowed_taps: allowed_taps_set, forbidden_taps: forbidden_taps_set)
|
||||||
|
end
|
||||||
|
|
||||||
cask = Cask::Cask.new("homebrew-forbidden-tap", tap: Tap.fetch(tap)) do
|
let(:homebrew_forbidden) { Tap.fetch("homebrew/forbidden") }
|
||||||
|
let(:allowed_third_party) { Tap.fetch("nothomebrew/allowed") }
|
||||||
|
let(:disallowed_third_party) { Tap.fetch("nothomebrew/notallowed") }
|
||||||
|
let(:allowed_taps_set) { Set.new([allowed_third_party]) }
|
||||||
|
let(:forbidden_taps_set) { Set.new([homebrew_forbidden]) }
|
||||||
|
|
||||||
|
it "raises on forbidden tap on cask" do
|
||||||
|
cask = Cask::Cask.new("homebrew-forbidden-tap", tap: homebrew_forbidden) do
|
||||||
url "file://#{TEST_FIXTURE_DIR}/cask/container.tar.gz"
|
url "file://#{TEST_FIXTURE_DIR}/cask/container.tar.gz"
|
||||||
end
|
end
|
||||||
|
|
||||||
expect do
|
expect do
|
||||||
described_class.new(cask).forbidden_tap_check
|
described_class.new(cask).forbidden_tap_check
|
||||||
end.to raise_error(Cask::CaskCannotBeInstalledError, /has the tap #{tap}/)
|
end.to raise_error(Cask::CaskCannotBeInstalledError, /has the tap #{homebrew_forbidden}/)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "raises on not allowed third-party tap on cask" do
|
||||||
|
cask = Cask::Cask.new("homebrew-not-allowed-tap", tap: disallowed_third_party) 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 #{disallowed_third_party}/)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "does not raise on allowed tap on cask" do
|
||||||
|
cask = Cask::Cask.new("third-party-allowed-tap", tap: allowed_third_party) do
|
||||||
|
url "file://#{TEST_FIXTURE_DIR}/cask/container.tar.gz"
|
||||||
|
end
|
||||||
|
|
||||||
|
expect { described_class.new(cask).forbidden_tap_check }.not_to raise_error
|
||||||
end
|
end
|
||||||
|
|
||||||
it "raises on forbidden tap on dependency" do
|
it "raises on forbidden tap on dependency" do
|
||||||
ENV["HOMEBREW_FORBIDDEN_TAPS"] = dep_tap = "homebrew/forbidden"
|
dep_tap = homebrew_forbidden
|
||||||
dep_name = "homebrew-forbidden-dependency-tap"
|
dep_name = "homebrew-forbidden-dependency-tap"
|
||||||
dep_path = Tap.fetch(dep_tap).new_formula_path(dep_name)
|
dep_path = dep_tap.new_formula_path(dep_name)
|
||||||
dep_path.parent.mkpath
|
dep_path.parent.mkpath
|
||||||
dep_path.write <<~RUBY
|
dep_path.write <<~RUBY
|
||||||
class #{Formulary.class_s(dep_name)} < Formula
|
class #{Formulary.class_s(dep_name)} < Formula
|
||||||
@ -358,7 +384,7 @@ RSpec.describe Cask::Installer, :cask do
|
|||||||
|
|
||||||
expect do
|
expect do
|
||||||
described_class.new(cask).forbidden_tap_check
|
described_class.new(cask).forbidden_tap_check
|
||||||
end.to raise_error(Cask::CaskCannotBeInstalledError, /but the #{dep_tap} tap was forbidden/)
|
end.to raise_error(Cask::CaskCannotBeInstalledError, /from the #{dep_tap} tap but/)
|
||||||
ensure
|
ensure
|
||||||
dep_path.parent.parent.rmtree
|
dep_path.parent.parent.rmtree
|
||||||
end
|
end
|
||||||
|
|||||||
@ -258,10 +258,20 @@ RSpec.describe FormulaInstaller do
|
|||||||
end
|
end
|
||||||
|
|
||||||
describe "#forbidden_tap_check" do
|
describe "#forbidden_tap_check" do
|
||||||
|
before do
|
||||||
|
allow(Tap).to receive_messages(allowed_taps: allowed_taps_set, forbidden_taps: forbidden_taps_set)
|
||||||
|
end
|
||||||
|
|
||||||
|
let(:homebrew_forbidden) { Tap.fetch("homebrew/forbidden") }
|
||||||
|
let(:allowed_third_party) { Tap.fetch("nothomebrew/allowed") }
|
||||||
|
let(:disallowed_third_party) { Tap.fetch("nothomebrew/notallowed") }
|
||||||
|
let(:allowed_taps_set) { Set.new([allowed_third_party]) }
|
||||||
|
let(:forbidden_taps_set) { Set.new([homebrew_forbidden]) }
|
||||||
|
|
||||||
it "raises on forbidden tap on formula" do
|
it "raises on forbidden tap on formula" do
|
||||||
ENV["HOMEBREW_FORBIDDEN_TAPS"] = f_tap = "homebrew/forbidden"
|
f_tap = homebrew_forbidden
|
||||||
f_name = "homebrew-forbidden-tap"
|
f_name = "homebrew-forbidden-tap"
|
||||||
f_path = Tap.fetch(f_tap).new_formula_path(f_name)
|
f_path = homebrew_forbidden.new_formula_path(f_name)
|
||||||
f_path.parent.mkpath
|
f_path.parent.mkpath
|
||||||
f_path.write <<~RUBY
|
f_path.write <<~RUBY
|
||||||
class #{Formulary.class_s(f_name)} < Formula
|
class #{Formulary.class_s(f_name)} < Formula
|
||||||
@ -281,10 +291,54 @@ RSpec.describe FormulaInstaller do
|
|||||||
f_path.parent.parent.rmtree
|
f_path.parent.parent.rmtree
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it "raises on not allowed third-party tap on formula" do
|
||||||
|
f_tap = disallowed_third_party
|
||||||
|
f_name = "homebrew-not-allowed-tap"
|
||||||
|
f_path = disallowed_third_party.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.parent.rmtree
|
||||||
|
end
|
||||||
|
|
||||||
|
it "does not raise on allowed tap on formula" do
|
||||||
|
f_tap = allowed_third_party
|
||||||
|
f_name = "homebrew-allowed-tap"
|
||||||
|
f_path = allowed_third_party.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 { fi.forbidden_tap_check }.not_to raise_error
|
||||||
|
ensure
|
||||||
|
f_path.parent.parent.parent.rmtree
|
||||||
|
end
|
||||||
|
|
||||||
it "raises on forbidden tap on dependency" do
|
it "raises on forbidden tap on dependency" do
|
||||||
ENV["HOMEBREW_FORBIDDEN_TAPS"] = dep_tap = "homebrew/forbidden"
|
dep_tap = homebrew_forbidden
|
||||||
dep_name = "homebrew-forbidden-dependency-tap"
|
dep_name = "homebrew-forbidden-dependency-tap"
|
||||||
dep_path = Tap.fetch(dep_tap).new_formula_path(dep_name)
|
dep_path = homebrew_forbidden.new_formula_path(dep_name)
|
||||||
dep_path.parent.mkpath
|
dep_path.parent.mkpath
|
||||||
dep_path.write <<~RUBY
|
dep_path.write <<~RUBY
|
||||||
class #{Formulary.class_s(dep_name)} < Formula
|
class #{Formulary.class_s(dep_name)} < Formula
|
||||||
@ -310,7 +364,7 @@ RSpec.describe FormulaInstaller do
|
|||||||
|
|
||||||
expect do
|
expect do
|
||||||
fi.forbidden_tap_check
|
fi.forbidden_tap_check
|
||||||
end.to raise_error(CannotInstallFormulaError, /but the #{dep_tap} tap was forbidden/)
|
end.to raise_error(CannotInstallFormulaError, /from the #{dep_tap} tap but/)
|
||||||
ensure
|
ensure
|
||||||
dep_path.parent.parent.rmtree
|
dep_path.parent.parent.rmtree
|
||||||
end
|
end
|
||||||
|
|||||||
@ -142,6 +142,24 @@ RSpec.describe Tap do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "::allowed_taps" do
|
||||||
|
before { allow(Homebrew::EnvConfig).to receive(:allowed_taps).and_return("homebrew/allowed") }
|
||||||
|
|
||||||
|
it "returns a set of allowed taps according to the environment" do
|
||||||
|
expect(described_class.allowed_taps)
|
||||||
|
.to contain_exactly(described_class.fetch("homebrew/allowed"))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "::forbidden_taps" do
|
||||||
|
before { allow(Homebrew::EnvConfig).to receive(:forbidden_taps).and_return("homebrew/forbidden") }
|
||||||
|
|
||||||
|
it "returns a set of forbidden taps according to the environment" do
|
||||||
|
expect(described_class.forbidden_taps)
|
||||||
|
.to contain_exactly(described_class.fetch("homebrew/forbidden"))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
specify "::names" do
|
specify "::names" do
|
||||||
expect(described_class.names.sort).to eq(["homebrew/core", "homebrew/foo"])
|
expect(described_class.names.sort).to eq(["homebrew/core", "homebrew/foo"])
|
||||||
end
|
end
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user