Merge pull request #10695 from Bo98/gem_path

Prevent loading all non-Bundler gems
This commit is contained in:
Bo Anderson 2021-02-26 21:35:52 +00:00 committed by GitHub
commit a65c5d685c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
30 changed files with 123 additions and 74 deletions

View File

@ -6,6 +6,7 @@ source "https://rubygems.org"
gem "bootsnap", require: false gem "bootsnap", require: false
gem "byebug", require: false gem "byebug", require: false
gem "codecov", require: false gem "codecov", require: false
gem "minitest", require: false
gem "nokogiri", require: false gem "nokogiri", require: false
gem "parallel_tests", require: false gem "parallel_tests", require: false
gem "ronn", require: false gem "ronn", require: false

View File

@ -179,6 +179,7 @@ DEPENDENCIES
codecov codecov
concurrent-ruby concurrent-ruby
mechanize mechanize
minitest
nokogiri nokogiri
parallel_tests parallel_tests
patchelf patchelf

View File

@ -568,11 +568,11 @@ then
# Don't allow non-developers to customise Ruby warnings. # Don't allow non-developers to customise Ruby warnings.
unset HOMEBREW_RUBY_WARNINGS unset HOMEBREW_RUBY_WARNINGS
# Disable Ruby options we don't need. RubyGems provides a decent speedup. # Disable Ruby options we don't need.
RUBY_DISABLE_OPTIONS="--disable=gems,did_you_mean,rubyopt" RUBY_DISABLE_OPTIONS="--disable=did_you_mean,rubyopt"
else else
# Don't disable did_you_mean for developers as it's useful. # Don't disable did_you_mean for developers as it's useful.
RUBY_DISABLE_OPTIONS="--disable=gems,rubyopt" RUBY_DISABLE_OPTIONS="--disable=rubyopt"
fi fi
if [[ -z "$HOMEBREW_RUBY_WARNINGS" ]] if [[ -z "$HOMEBREW_RUBY_WARNINGS" ]]

View File

@ -6,7 +6,7 @@
old_trap = trap("INT") { exit! 130 } old_trap = trap("INT") { exit! 130 }
require "global" require_relative "global"
require "build_options" require "build_options"
require "cxxstdlib" require "cxxstdlib"
require "keg" require "keg"

View File

@ -3,7 +3,6 @@
require "utils/bottles" require "utils/bottles"
require "utils/gems"
require "formula" require "formula"
require "cask/cask_loader" require "cask/cask_loader"
require "set" require "set"

View File

@ -67,3 +67,9 @@ HOMEBREW_TEMP = Pathname(EnvVar["HOMEBREW_TEMP"]).yield_self do |tmp|
tmp.mkpath unless tmp.exist? tmp.mkpath unless tmp.exist?
tmp.realpath tmp.realpath
end.freeze end.freeze
# The Ruby path and args to use for forked Ruby calls
HOMEBREW_RUBY_EXEC_ARGS = [
RUBY_PATH,
ENV["HOMEBREW_RUBY_WARNINGS"],
].freeze

View File

@ -35,6 +35,8 @@ module Homebrew
def test def test
args = test_args.parse args = test_args.parse
Homebrew.install_bundler_gems!
require "formula_assertions" require "formula_assertions"
require "formula_free_port" require "formula_free_port"
@ -75,10 +77,7 @@ module Homebrew
env = ENV.to_hash env = ENV.to_hash
begin begin
exec_args = %W[ exec_args = HOMEBREW_RUBY_EXEC_ARGS + %W[
#{RUBY_PATH}
#{ENV["HOMEBREW_RUBY_WARNINGS"]}
-I #{$LOAD_PATH.join(File::PATH_SEPARATOR)}
-- --
#{HOMEBREW_LIBRARY_PATH}/test.rb #{HOMEBREW_LIBRARY_PATH}/test.rb
#{f.path} #{f.path}
@ -106,7 +105,7 @@ module Homebrew
rescue Exception => e # rubocop:disable Lint/RescueException rescue Exception => e # rubocop:disable Lint/RescueException
retry if retry_test?(f, args: args) retry if retry_test?(f, args: args)
ofail "#{f.full_name}: failed" ofail "#{f.full_name}: failed"
puts e, e.backtrace $stderr.puts e, e.backtrace
ensure ensure
ENV.replace(env) ENV.replace(env)
end end

View File

@ -35,7 +35,7 @@ module EnvActivation
params( params(
env: T.nilable(String), env: T.nilable(String),
cc: T.nilable(String), cc: T.nilable(String),
build_bottle: T.nilable(T::Boolean), build_bottle: T::Boolean,
bottle_arch: T.nilable(String), bottle_arch: T.nilable(String),
_block: T.proc.returns(T.untyped), _block: T.proc.returns(T.untyped),
).returns(T.untyped) ).returns(T.untyped)

View File

@ -35,13 +35,14 @@ module SharedEnvExtension
sig { sig {
params( params(
formula: T.nilable(Formula), formula: T.nilable(Formula),
cc: T.nilable(String), cc: T.nilable(String),
build_bottle: T.nilable(T::Boolean), build_bottle: T.nilable(T::Boolean),
bottle_arch: T.nilable(T::Boolean), bottle_arch: T.nilable(String),
testing_formula: T::Boolean,
).void ).void
} }
def setup_build_environment(formula: nil, cc: nil, build_bottle: false, bottle_arch: nil) def setup_build_environment(formula: nil, cc: nil, build_bottle: false, bottle_arch: nil, testing_formula: false)
@formula = formula @formula = formula
@cc = cc @cc = cc
@build_bottle = build_bottle @build_bottle = build_bottle

View File

@ -16,13 +16,14 @@ module Stdenv
# @private # @private
sig { sig {
params( params(
formula: T.nilable(Formula), formula: T.nilable(Formula),
cc: T.nilable(String), cc: T.nilable(String),
build_bottle: T.nilable(T::Boolean), build_bottle: T.nilable(T::Boolean),
bottle_arch: T.nilable(T::Boolean), bottle_arch: T.nilable(String),
testing_formula: T::Boolean,
).void ).void
} }
def setup_build_environment(formula: nil, cc: nil, build_bottle: false, bottle_arch: nil) def setup_build_environment(formula: nil, cc: nil, build_bottle: false, bottle_arch: nil, testing_formula: false)
super super
self["HOMEBREW_ENV"] = "std" self["HOMEBREW_ENV"] = "std"

View File

@ -44,13 +44,14 @@ module Superenv
# @private # @private
sig { sig {
params( params(
formula: T.nilable(Formula), formula: T.nilable(Formula),
cc: T.nilable(String), cc: T.nilable(String),
build_bottle: T.nilable(T::Boolean), build_bottle: T.nilable(T::Boolean),
bottle_arch: T.nilable(T::Boolean), bottle_arch: T.nilable(String),
testing_formula: T::Boolean,
).void ).void
} }
def setup_build_environment(formula: nil, cc: nil, build_bottle: false, bottle_arch: nil) def setup_build_environment(formula: nil, cc: nil, build_bottle: false, bottle_arch: nil, testing_formula: false)
super super
send(compiler) send(compiler)

View File

@ -3,7 +3,10 @@
module Stdenv module Stdenv
def setup_build_environment(formula: nil, cc: nil, build_bottle: false, bottle_arch: nil, testing_formula: false) def setup_build_environment(formula: nil, cc: nil, build_bottle: false, bottle_arch: nil, testing_formula: false)
generic_setup_build_environment(formula: formula, cc: cc, build_bottle: build_bottle, bottle_arch: bottle_arch) generic_setup_build_environment(
formula: formula, cc: cc, build_bottle: build_bottle,
bottle_arch: bottle_arch, testing_formula: testing_formula
)
prepend_path "CPATH", HOMEBREW_PREFIX/"include" prepend_path "CPATH", HOMEBREW_PREFIX/"include"
prepend_path "LIBRARY_PATH", HOMEBREW_PREFIX/"lib" prepend_path "LIBRARY_PATH", HOMEBREW_PREFIX/"lib"

View File

@ -11,7 +11,10 @@ module Superenv
# @private # @private
def setup_build_environment(formula: nil, cc: nil, build_bottle: false, bottle_arch: nil, testing_formula: false) def setup_build_environment(formula: nil, cc: nil, build_bottle: false, bottle_arch: nil, testing_formula: false)
generic_setup_build_environment(formula: formula, cc: cc, build_bottle: build_bottle, bottle_arch: bottle_arch) generic_setup_build_environment(
formula: formula, cc: cc, build_bottle: build_bottle,
bottle_arch: bottle_arch, testing_formula: testing_formula
)
self["HOMEBREW_OPTIMIZATION_LEVEL"] = "O2" self["HOMEBREW_OPTIMIZATION_LEVEL"] = "O2"
self["HOMEBREW_DYNAMIC_LINKER"] = determine_dynamic_linker_path self["HOMEBREW_DYNAMIC_LINKER"] = determine_dynamic_linker_path
self["HOMEBREW_RPATH_PATHS"] = determine_rpath_paths(@formula) self["HOMEBREW_RPATH_PATHS"] = determine_rpath_paths(@formula)

View File

@ -11,7 +11,10 @@ module Stdenv
end end
def setup_build_environment(formula: nil, cc: nil, build_bottle: false, bottle_arch: nil, testing_formula: false) def setup_build_environment(formula: nil, cc: nil, build_bottle: false, bottle_arch: nil, testing_formula: false)
generic_setup_build_environment(formula: formula, cc: cc, build_bottle: build_bottle, bottle_arch: bottle_arch) generic_setup_build_environment(
formula: formula, cc: cc, build_bottle: build_bottle,
bottle_arch: bottle_arch, testing_formula: testing_formula
)
# sed is strict, and errors out when it encounters files with # sed is strict, and errors out when it encounters files with
# mixed character sets # mixed character sets

View File

@ -121,7 +121,10 @@ module Superenv
self["HOMEBREW_SDKROOT"] = nil self["HOMEBREW_SDKROOT"] = nil
self["HOMEBREW_DEVELOPER_DIR"] = nil self["HOMEBREW_DEVELOPER_DIR"] = nil
end end
generic_setup_build_environment(formula: formula, cc: cc, build_bottle: build_bottle, bottle_arch: bottle_arch) generic_setup_build_environment(
formula: formula, cc: cc, build_bottle: build_bottle,
bottle_arch: bottle_arch, testing_formula: testing_formula
)
# Filter out symbols known not to be defined since GNU Autotools can't # Filter out symbols known not to be defined since GNU Autotools can't
# reliably figure this out with Xcode 8 and above. # reliably figure this out with Xcode 8 and above.

View File

@ -8,8 +8,38 @@ module Homebrew
module Assertions module Assertions
include Context include Context
require "test/unit/assertions" require "minitest"
include ::Test::Unit::Assertions require "minitest/assertions"
include ::Minitest::Assertions
attr_writer :assertions
def assertions
@assertions ||= 0
end
# Test::Unit backwards compatibility methods
{
assert_raise: :assert_raises,
assert_not_empty: :refute_empty,
assert_not_equal: :refute_equal,
assert_not_in_delta: :refute_in_delta,
assert_not_in_epsilon: :refute_in_epsilon,
assert_not_includes: :refute_includes,
assert_not_instance_of: :refute_instance_of,
assert_not_kind_of: :refute_kind_of,
assert_no_match: :refute_match,
assert_not_nil: :refute_nil,
assert_not_operator: :refute_operator,
assert_not_predicate: :refute_predicate,
assert_not_respond_to: :refute_respond_to,
assert_not_same: :refute_same,
}.each do |old_method, new_method|
define_method(old_method) do |*args|
# odeprecated old_method, new_method
send(new_method, *args)
end
end
# Returns the output of running cmd, and asserts the exit status. # Returns the output of running cmd, and asserts the exit status.
# @api public # @api public
@ -18,7 +48,7 @@ module Homebrew
output = `#{cmd}` output = `#{cmd}`
assert_equal result, $CHILD_STATUS.exitstatus assert_equal result, $CHILD_STATUS.exitstatus
output output
rescue Test::Unit::AssertionFailedError rescue Minitest::Assertion
puts output if verbose? puts output if verbose?
raise raise
end end
@ -35,7 +65,7 @@ module Homebrew
end end
assert_equal result, $CHILD_STATUS.exitstatus unless result.nil? assert_equal result, $CHILD_STATUS.exitstatus unless result.nil?
output output
rescue Test::Unit::AssertionFailedError rescue Minitest::Assertion
puts output if verbose? puts output if verbose?
raise raise
end end

View File

@ -16,13 +16,11 @@ class FormulaInfo
# Returns nil if formula is absent or if there was an error reading it. # Returns nil if formula is absent or if there was an error reading it.
def self.lookup(name) def self.lookup(name)
json = Utils.popen_read( json = Utils.popen_read(
RUBY_PATH, *HOMEBREW_RUBY_EXEC_ARGS,
ENV["HOMEBREW_RUBY_WARNINGS"],
"-I", $LOAD_PATH.join(File::PATH_SEPARATOR),
HOMEBREW_LIBRARY_PATH/"brew.rb", HOMEBREW_LIBRARY_PATH/"brew.rb",
"info", "info",
"--json=v1", "--json=v1",
name name,
) )
return unless $CHILD_STATUS.success? return unless $CHILD_STATUS.success?

View File

@ -896,13 +896,12 @@ class FormulaInstaller
# 1. formulae can modify ENV, so we must ensure that each # 1. formulae can modify ENV, so we must ensure that each
# installation has a pristine ENV when it starts, forking now is # installation has a pristine ENV when it starts, forking now is
# the easiest way to do this # the easiest way to do this
args = %W[ args = [
nice #{RUBY_PATH} "nice",
#{ENV["HOMEBREW_RUBY_WARNINGS"]} *HOMEBREW_RUBY_EXEC_ARGS,
-I #{$LOAD_PATH.join(File::PATH_SEPARATOR)} "--",
-- HOMEBREW_LIBRARY_PATH/"build.rb",
#{HOMEBREW_LIBRARY_PATH}/build.rb formula.specified_path,
#{formula.specified_path}
].concat(build_argv) ].concat(build_argv)
Utils.safe_fork do Utils.safe_fork do

View File

@ -16,7 +16,6 @@ require "rbconfig"
RUBY_PATH = Pathname.new(RbConfig.ruby).freeze RUBY_PATH = Pathname.new(RbConfig.ruby).freeze
RUBY_BIN = RUBY_PATH.dirname.freeze RUBY_BIN = RUBY_PATH.dirname.freeze
require "rubygems"
# Only require "core_ext" here to ensure we're only requiring the minimum of # Only require "core_ext" here to ensure we're only requiring the minimum of
# what we need. # what we need.
require "active_support/core_ext/object/blank" require "active_support/core_ext/object/blank"

View File

@ -17,13 +17,10 @@ else
end end
if homebrew_bootsnap_enabled if homebrew_bootsnap_enabled
require "rubygems"
begin begin
require "bootsnap" require "bootsnap"
rescue LoadError rescue LoadError
unless ENV["HOMEBREW_BOOTSNAP_RETRY"] unless ENV["HOMEBREW_BOOTSNAP_RETRY"]
require "utils/gems"
Homebrew.install_bundler_gems!(only_warn_on_failure: true) Homebrew.install_bundler_gems!(only_warn_on_failure: true)
ENV["HOMEBREW_BOOTSNAP_RETRY"] = "1" ENV["HOMEBREW_BOOTSNAP_RETRY"] = "1"

View File

@ -5,12 +5,21 @@ require "pathname"
HOMEBREW_LIBRARY_PATH = Pathname(__dir__).realpath.freeze HOMEBREW_LIBRARY_PATH = Pathname(__dir__).realpath.freeze
$LOAD_PATH.push HOMEBREW_LIBRARY_PATH.to_s require_relative "utils/gems"
Homebrew.setup_gem_environment!(setup_path: false)
require "vendor/bundle/bundler/setup" $LOAD_PATH.push HOMEBREW_LIBRARY_PATH.to_s unless $LOAD_PATH.include?(HOMEBREW_LIBRARY_PATH.to_s)
require "homebrew_bootsnap" require_relative "vendor/bundle/bundler/setup"
$LOAD_PATH.uniq!
unless defined?(Bootsnap) # Block any gem loading by bypassing rubygem's `require`.
$LOAD_PATH.select! { |d| Pathname(d).directory? } # Helps make sure we don't accidentally use things not in bundler's load path.
$LOAD_PATH.uniq! # Bundler 2.2.7+ and non-standalone mode both do this automatically.
# https://github.com/rubygems/rubygems/blob/5841761974bef324a33ef1cb650bbf8a2457805b/bundler/lib/bundler/installer/standalone.rb#L55-L63
if Kernel.private_method_defined?(:gem_original_require)
Kernel.send(:remove_method, :require)
Kernel.send(:define_method, :require, Kernel.instance_method(:gem_original_require))
Kernel.send(:private, :require)
end end
require_relative "homebrew_bootsnap"

View File

@ -3,7 +3,7 @@
old_trap = trap("INT") { exit! 130 } old_trap = trap("INT") { exit! 130 }
require "global" require_relative "global"
require "debrew" require "debrew"
require "fcntl" require "fcntl"
require "socket" require "socket"

View File

@ -11,7 +11,6 @@ require "dependency_collector"
require "utils/bottles" require "utils/bottles"
require "patch" require "patch"
require "compilers" require "compilers"
require "global"
require "os/mac/version" require "os/mac/version"
require "extend/on_os" require "extend/on_os"

View File

@ -3,7 +3,7 @@
old_trap = trap("INT") { exit! 130 } old_trap = trap("INT") { exit! 130 }
require "global" require_relative "global"
require "extend/ENV" require "extend/ENV"
require "timeout" require "timeout"
require "debrew" require "debrew"

View File

@ -6,8 +6,7 @@ require "cmd/shared_examples/args_parse"
describe "brew test" do describe "brew test" do
it_behaves_like "parseable arguments" it_behaves_like "parseable arguments"
# randomly segfaults on Linux with portable-ruby. it "tests a given Formula", :integration_test do
it "tests a given Formula", :integration_test, :needs_macos do
install_test_formula "testball", <<~'RUBY' install_test_formula "testball", <<~'RUBY'
test do test do
assert_equal "test", shell_output("#{bin}/test") assert_equal "test", shell_output("#{bin}/test")

View File

@ -2,7 +2,6 @@
# frozen_string_literal: true # frozen_string_literal: true
require "formula_info" require "formula_info"
require "global"
describe FormulaInfo, :integration_test do describe FormulaInfo, :integration_test do
it "tests the FormulaInfo class" do it "tests the FormulaInfo class" do

View File

@ -87,10 +87,7 @@ RSpec.shared_context "integration test" do # rubocop:disable RSpec/ContextWordin
) )
@ruby_args ||= begin @ruby_args ||= begin
ruby_args = [ ruby_args = HOMEBREW_RUBY_EXEC_ARGS.dup
ENV["HOMEBREW_RUBY_WARNINGS"],
"-I", $LOAD_PATH.join(File::PATH_SEPARATOR)
]
if ENV["HOMEBREW_TESTS_COVERAGE"] if ENV["HOMEBREW_TESTS_COVERAGE"]
simplecov_spec = Gem.loaded_specs["simplecov"] simplecov_spec = Gem.loaded_specs["simplecov"]
specs = [simplecov_spec] specs = [simplecov_spec]
@ -111,12 +108,12 @@ RSpec.shared_context "integration test" do # rubocop:disable RSpec/ContextWordin
libs.each { |lib| ruby_args << "-I" << lib } libs.each { |lib| ruby_args << "-I" << lib }
ruby_args << "-rsimplecov" ruby_args << "-rsimplecov"
end end
ruby_args << "-rtest/support/helper/integration_mocks" ruby_args << "-r#{HOMEBREW_LIBRARY_PATH}/test/support/helper/integration_mocks"
ruby_args << (HOMEBREW_LIBRARY_PATH/"brew.rb").resolved_path.to_s ruby_args << (HOMEBREW_LIBRARY_PATH/"brew.rb").resolved_path.to_s
end end
Bundler.with_clean_env do Bundler.with_clean_env do
stdout, stderr, status = Open3.capture3(env, RUBY_PATH, *@ruby_args, *args) stdout, stderr, status = Open3.capture3(env, *@ruby_args, *args)
$stdout.print stdout $stdout.print stdout
$stderr.print stderr $stderr.print stderr
status status

View File

@ -37,6 +37,11 @@ HOMEBREW_LOCKS = (HOMEBREW_PREFIX.parent/"locks").freeze
HOMEBREW_CELLAR = (HOMEBREW_PREFIX.parent/"cellar").freeze HOMEBREW_CELLAR = (HOMEBREW_PREFIX.parent/"cellar").freeze
HOMEBREW_LOGS = (HOMEBREW_PREFIX.parent/"logs").freeze HOMEBREW_LOGS = (HOMEBREW_PREFIX.parent/"logs").freeze
HOMEBREW_TEMP = (HOMEBREW_PREFIX.parent/"temp").freeze HOMEBREW_TEMP = (HOMEBREW_PREFIX.parent/"temp").freeze
HOMEBREW_RUBY_EXEC_ARGS = [
RUBY_PATH,
ENV["HOMEBREW_RUBY_WARNINGS"],
"-I", HOMEBREW_LIBRARY_PATH/"test/support/lib"
].freeze
TEST_FIXTURE_DIR = (HOMEBREW_LIBRARY_PATH/"test/support/fixtures").freeze TEST_FIXTURE_DIR = (HOMEBREW_LIBRARY_PATH/"test/support/fixtures").freeze

View File

@ -22,7 +22,6 @@ module Homebrew
end end
def gem_user_bindir def gem_user_bindir
require "rubygems"
"#{gem_user_dir}/bin" "#{gem_user_dir}/bin"
end end
@ -51,13 +50,11 @@ module Homebrew
end end
end end
def setup_gem_environment!(gem_home: nil, gem_bindir: nil) def setup_gem_environment!(gem_home: nil, gem_bindir: nil, setup_path: true)
require "rubygems"
# Match where our bundler gems are. # Match where our bundler gems are.
gem_home ||= "#{ENV["HOMEBREW_LIBRARY"]}/Homebrew/vendor/bundle/ruby/#{RbConfig::CONFIG["ruby_version"]}" gem_home ||= "#{ENV["HOMEBREW_LIBRARY"]}/Homebrew/vendor/bundle/ruby/#{RbConfig::CONFIG["ruby_version"]}"
ENV["GEM_HOME"] = gem_home ENV["GEM_HOME"] = gem_home
ENV["GEM_PATH"] = "#{ENV["GEM_HOME"]}:#{Gem.default_dir}" ENV["GEM_PATH"] = gem_home
# Set TMPDIR so Xcode's `make` doesn't fall back to `/var/tmp/`, # Set TMPDIR so Xcode's `make` doesn't fall back to `/var/tmp/`,
# which may be not user-writable. # which may be not user-writable.
@ -67,6 +64,8 @@ module Homebrew
Gem.clear_paths Gem.clear_paths
Gem::Specification.reset Gem::Specification.reset
return unless setup_path
# Add necessary Ruby and Gem binary directories to `PATH`. # Add necessary Ruby and Gem binary directories to `PATH`.
gem_bindir ||= Gem.bindir gem_bindir ||= Gem.bindir
paths = ENV.fetch("PATH").split(":") paths = ENV.fetch("PATH").split(":")
@ -103,7 +102,6 @@ module Homebrew
end end
def install_bundler! def install_bundler!
require "rubygems"
setup_gem_environment!(gem_home: gem_user_dir, gem_bindir: gem_user_bindir) setup_gem_environment!(gem_home: gem_user_dir, gem_bindir: gem_user_bindir)
install_gem_setup_path!( install_gem_setup_path!(
"bundler", "bundler",

View File

@ -2,7 +2,6 @@
# frozen_string_literal: true # frozen_string_literal: true
if ENV["HOMEBREW_SORBET_RUNTIME"] if ENV["HOMEBREW_SORBET_RUNTIME"]
require "utils/gems"
Homebrew.install_bundler_gems! Homebrew.install_bundler_gems!
require "sorbet-runtime" require "sorbet-runtime"
else else