Reset Bootsnap after installing gems

This commit is contained in:
Bo Anderson 2025-03-27 03:05:51 +00:00
parent 76e154fe82
commit 1168ec1feb
No known key found for this signature in database
5 changed files with 86 additions and 40 deletions

View File

@ -558,7 +558,7 @@ module Homebrew
return unless bootsnap.directory? return unless bootsnap.directory?
bootsnap.each_child do |subdir| bootsnap.each_child do |subdir|
cleanup_path(subdir) { FileUtils.rm_r(subdir) } if subdir.basename.to_s != Homebrew.bootsnap_key cleanup_path(subdir) { FileUtils.rm_r(subdir) } if subdir.basename.to_s != Homebrew::Bootsnap.key
end end
end end

View File

@ -0,0 +1,3 @@
# typed: strict
HOMEBREW_USING_PORTABLE_RUBY = T.let(false, T::Boolean)

View File

@ -1,13 +1,10 @@
# typed: true # typed: true
# frozen_string_literal: true # frozen_string_literal: true
homebrew_bootsnap_enabled = HOMEBREW_USING_PORTABLE_RUBY &&
ENV["HOMEBREW_NO_BOOTSNAP"].nil? &&
!ENV["HOMEBREW_BOOTSNAP"].nil?
module Homebrew module Homebrew
def self.bootsnap_key module Bootsnap
@bootsnap_key ||= begin def self.key
@key ||= begin
require "digest/sha2" require "digest/sha2"
checksum = Digest::SHA256.new checksum = Digest::SHA256.new
@ -18,29 +15,53 @@ module Homebrew
checksum.hexdigest checksum.hexdigest
end end
end end
end
if homebrew_bootsnap_enabled
require "bootsnap"
private_class_method def self.cache_dir
cache = ENV.fetch("HOMEBREW_CACHE", nil) || ENV.fetch("HOMEBREW_DEFAULT_CACHE", nil) cache = ENV.fetch("HOMEBREW_CACHE", nil) || ENV.fetch("HOMEBREW_DEFAULT_CACHE", nil)
raise "Needs HOMEBREW_CACHE or HOMEBREW_DEFAULT_CACHE!" if cache.nil? || cache.empty? raise "Needs HOMEBREW_CACHE or HOMEBREW_DEFAULT_CACHE!" if cache.nil? || cache.empty?
cache = File.join(cache, "bootsnap", Homebrew.bootsnap_key) File.join(cache, "bootsnap", key)
end
private_class_method def self.ignore_directories
# We never do `require "vendor/bundle/ruby/..."` or `require "vendor/portable-ruby/..."`, # We never do `require "vendor/bundle/ruby/..."` or `require "vendor/portable-ruby/..."`,
# so let's slim the cache a bit by excluding them. # so let's slim the cache a bit by excluding them.
# Note that gems within `bundle/ruby` will still be cached - these are when directory walking down from above. # Note that gems within `bundle/ruby` will still be cached - these are when directory walking down from above.
ignore_directories = [ [
(HOMEBREW_LIBRARY_PATH/"vendor/bundle/ruby").to_s, (HOMEBREW_LIBRARY_PATH/"vendor/bundle/ruby").to_s,
(HOMEBREW_LIBRARY_PATH/"vendor/portable-ruby").to_s, (HOMEBREW_LIBRARY_PATH/"vendor/portable-ruby").to_s,
] ]
end
Bootsnap.setup( private_class_method def self.enabled?
cache_dir: cache, HOMEBREW_USING_PORTABLE_RUBY && ENV["HOMEBREW_NO_BOOTSNAP"].nil? && !ENV["HOMEBREW_BOOTSNAP"].nil?
end
def self.load!(compile_cache: true)
return unless enabled?
require "bootsnap"
::Bootsnap.setup(
cache_dir:,
ignore_directories:, ignore_directories:,
load_path_cache: true, load_path_cache: true,
compile_cache_iseq: true, compile_cache_iseq: compile_cache,
compile_cache_yaml: true, compile_cache_yaml: compile_cache,
compile_cache_json: compile_cache,
) )
end
def self.reset!
return unless enabled?
::Bootsnap.unload_cache!
@key = nil
# The compile cache doesn't get unloaded so we don't need to load it again!
load!(compile_cache: false)
end
end
end end
Homebrew::Bootsnap.load!

View File

@ -1,8 +1,25 @@
# typed: strict # typed: strict
module Homebrew module Homebrew
module Bootsnap
sig { returns(String) } sig { returns(String) }
def self.bootsnap_key; end def self.key; end
sig { returns(String) }
private_class_method def self.cache_dir; end
sig { returns(T::Array[String]) }
private_class_method def self.ignore_directories; end
sig { returns(T::Boolean) }
private_class_method def self.enabled?; end
sig { params(compile_cache: T::Boolean).void }
def self.load!(compile_cache: true); end
sig { void }
def self.reset!; end
end
end end
module Bootsnap module Bootsnap
@ -29,5 +46,9 @@ module Bootsnap
compile_cache_iseq: true, compile_cache_iseq: true,
compile_cache_yaml: true, compile_cache_yaml: true,
compile_cache_json: true compile_cache_json: true
); end )
end
sig { void }
def self.unload_cache!; end
end end

View File

@ -303,6 +303,7 @@ module Homebrew
exec bundle, "install", out: :err exec bundle, "install", out: :err
end) end)
if $CHILD_STATUS.success? if $CHILD_STATUS.success?
Homebrew::Bootsnap.reset! if defined?(Homebrew::Bootsnap) # Gem install can run before Bootsnap loads
true true
else else
message = <<~EOS message = <<~EOS