mirror of
https://github.com/Homebrew/brew.git
synced 2025-07-14 16:09:03 +08:00
formula: add methods for allowing/denying network access
This commit is contained in:
parent
c938f89c28
commit
7c11699d73
@ -70,6 +70,11 @@ class Formula
|
|||||||
extend Attrable
|
extend Attrable
|
||||||
extend APIHashable
|
extend APIHashable
|
||||||
|
|
||||||
|
SUPPORTED_NETWORK_ACCESS_PHASES = [:build, :test, :postinstall].freeze
|
||||||
|
DEFAULT_NETWORK_ACCESS_ALLOWED = true
|
||||||
|
private_constant :SUPPORTED_NETWORK_ACCESS_PHASES
|
||||||
|
private_constant :DEFAULT_NETWORK_ACCESS_ALLOWED
|
||||||
|
|
||||||
# The name of this {Formula}.
|
# The name of this {Formula}.
|
||||||
# e.g. `this-formula`
|
# e.g. `this-formula`
|
||||||
sig { returns(String) }
|
sig { returns(String) }
|
||||||
@ -400,6 +405,7 @@ class Formula
|
|||||||
!!head && !stable
|
!!head && !stable
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Stop RuboCop from erroneously indenting hash target
|
||||||
delegate [ # rubocop:disable Layout/HashAlignment
|
delegate [ # rubocop:disable Layout/HashAlignment
|
||||||
:bottle_defined?,
|
:bottle_defined?,
|
||||||
:bottle_tag?,
|
:bottle_tag?,
|
||||||
@ -459,6 +465,13 @@ class Formula
|
|||||||
# @see .version
|
# @see .version
|
||||||
delegate version: :active_spec
|
delegate version: :active_spec
|
||||||
|
|
||||||
|
# Stop RuboCop from erroneously indenting hash target
|
||||||
|
delegate [ # rubocop:disable Layout/HashAlignment
|
||||||
|
:allow_network_access!,
|
||||||
|
:deny_network_access!,
|
||||||
|
:network_access_allowed?,
|
||||||
|
] => :"self.class"
|
||||||
|
|
||||||
# Whether this formula was loaded using the formulae.brew.sh API
|
# Whether this formula was loaded using the formulae.brew.sh API
|
||||||
# @!method loaded_from_api?
|
# @!method loaded_from_api?
|
||||||
# @private
|
# @private
|
||||||
@ -3028,6 +3041,9 @@ class Formula
|
|||||||
@skip_clean_paths = Set.new
|
@skip_clean_paths = Set.new
|
||||||
@link_overwrite_paths = Set.new
|
@link_overwrite_paths = Set.new
|
||||||
@loaded_from_api = false
|
@loaded_from_api = false
|
||||||
|
@network_access_allowed = SUPPORTED_NETWORK_ACCESS_PHASES.to_h do |phase|
|
||||||
|
[phase, DEFAULT_NETWORK_ACCESS_ALLOWED]
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -3104,6 +3120,59 @@ class Formula
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# @!attribute [w] allow_network_access!
|
||||||
|
# The phases for which network access is allowed. By default, network
|
||||||
|
# access is allowed for all phases. Valid phases are `:build`, `:test`,
|
||||||
|
# and `:postinstall`. When no argument is passed, network access will be
|
||||||
|
# allowed for all phases.
|
||||||
|
# <pre>allow_network_access!</pre>
|
||||||
|
# <pre>allow_network_access! :build</pre>
|
||||||
|
# <pre>allow_network_access! [:build, :test]</pre>
|
||||||
|
sig { params(phases: T.any(Symbol, T::Array[Symbol])).void }
|
||||||
|
def allow_network_access!(phases = [])
|
||||||
|
phases_array = Array(phases)
|
||||||
|
if phases_array.empty?
|
||||||
|
@network_access_allowed.each_key { |phase| @network_access_allowed[phase] = true }
|
||||||
|
else
|
||||||
|
phases_array.each do |phase|
|
||||||
|
raise ArgumentError, "Unknown phase: #{phase}" unless SUPPORTED_NETWORK_ACCESS_PHASES.include?(phase)
|
||||||
|
|
||||||
|
@network_access_allowed[phase] = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# @!attribute [w] deny_network_access!
|
||||||
|
# The phases for which network access is denied. By default, network
|
||||||
|
# access is allowed for all phases. Valid phases are `:build`, `:test`,
|
||||||
|
# and `:postinstall`. When no argument is passed, network access will be
|
||||||
|
# denied for all phases.
|
||||||
|
# <pre>deny_network_access!</pre>
|
||||||
|
# <pre>deny_network_access! :build</pre>
|
||||||
|
# <pre>deny_network_access! [:build, :test]</pre>
|
||||||
|
sig { params(phases: T.any(Symbol, T::Array[Symbol])).void }
|
||||||
|
def deny_network_access!(phases = [])
|
||||||
|
phases_array = Array(phases)
|
||||||
|
if phases_array.empty?
|
||||||
|
@network_access_allowed.each_key { |phase| @network_access_allowed[phase] = false }
|
||||||
|
else
|
||||||
|
phases_array.each do |phase|
|
||||||
|
raise ArgumentError, "Unknown phase: #{phase}" unless SUPPORTED_NETWORK_ACCESS_PHASES.include?(phase)
|
||||||
|
|
||||||
|
@network_access_allowed[phase] = false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Whether the specified phase should be forced offline.
|
||||||
|
sig { params(phase: Symbol).returns(T::Boolean) }
|
||||||
|
def network_access_allowed?(phase)
|
||||||
|
raise ArgumentError, "Unknown phase: #{phase}" unless SUPPORTED_NETWORK_ACCESS_PHASES.include?(phase)
|
||||||
|
|
||||||
|
env_var = Homebrew::EnvConfig.send(:"formula_#{phase}_network")
|
||||||
|
env_var.nil? ? @network_access_allowed[phase] : env_var == "allow"
|
||||||
|
end
|
||||||
|
|
||||||
# @!attribute [w] homepage
|
# @!attribute [w] homepage
|
||||||
# The homepage for the software. Used by users to get more information
|
# The homepage for the software. Used by users to get more information
|
||||||
# about the software and Homebrew maintainers as a point of contact for
|
# about the software and Homebrew maintainers as a point of contact for
|
||||||
|
@ -42,6 +42,7 @@ RSpec.describe Formula do
|
|||||||
expect(f.alias_name).to be_nil
|
expect(f.alias_name).to be_nil
|
||||||
expect(f.full_alias_name).to be_nil
|
expect(f.full_alias_name).to be_nil
|
||||||
expect(f.specified_path).to eq(path)
|
expect(f.specified_path).to eq(path)
|
||||||
|
[:build, :test, :postinstall].each { |phase| expect(f.network_access_allowed?(phase)).to be(true) }
|
||||||
expect { klass.new }.to raise_error(ArgumentError)
|
expect { klass.new }.to raise_error(ArgumentError)
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -55,6 +56,7 @@ RSpec.describe Formula do
|
|||||||
expect(f_alias.specified_path).to eq(Pathname(alias_path))
|
expect(f_alias.specified_path).to eq(Pathname(alias_path))
|
||||||
expect(f_alias.full_alias_name).to eq(alias_name)
|
expect(f_alias.full_alias_name).to eq(alias_name)
|
||||||
expect(f_alias.full_specified_name).to eq(alias_name)
|
expect(f_alias.full_specified_name).to eq(alias_name)
|
||||||
|
[:build, :test, :postinstall].each { |phase| expect(f_alias.network_access_allowed?(phase)).to be(true) }
|
||||||
expect { klass.new }.to raise_error(ArgumentError)
|
expect { klass.new }.to raise_error(ArgumentError)
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -1895,4 +1897,39 @@ RSpec.describe Formula do
|
|||||||
expect(f.fish_completion/"testball.fish").to be_a_file
|
expect(f.fish_completion/"testball.fish").to be_a_file
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "{allow,deny}_network_access" do
|
||||||
|
phases = [:build, :postinstall, :test].freeze
|
||||||
|
actions = %w[allow deny].freeze
|
||||||
|
phases.each do |phase|
|
||||||
|
actions.each do |action|
|
||||||
|
it "can #{action} network access for #{phase}" do
|
||||||
|
f = Class.new(Testball) do
|
||||||
|
send(:"#{action}_network_access!", phase)
|
||||||
|
end
|
||||||
|
|
||||||
|
expect(f.network_access_allowed?(phase)).to be(action == "allow")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
actions.each do |action|
|
||||||
|
it "can #{action} network access for all phases" do
|
||||||
|
f = Class.new(Testball) do
|
||||||
|
send(:"#{action}_network_access!")
|
||||||
|
end
|
||||||
|
|
||||||
|
phases.each do |phase|
|
||||||
|
expect(f.network_access_allowed?(phase)).to be(action == "allow")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "#network_access_allowed?" do
|
||||||
|
it "throws an error when passed an invalid symbol" do
|
||||||
|
f = Testball.new
|
||||||
|
expect { f.network_access_allowed?(:foo) }.to raise_error(ArgumentError)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
Loading…
x
Reference in New Issue
Block a user