module Bootsnap
def _instrument(event, path)
def _instrument(event, path) @instrumentation.call(event, path) end
def absolute_path?(path)
def absolute_path?(path) path[1] == ":" end
def absolute_path?(path)
def absolute_path?(path) path.start_with?("/") end
def bundler?
def bundler? return false unless defined?(::Bundler) # Bundler environment variable %w(BUNDLE_BIN_PATH BUNDLE_GEMFILE).each do |current| return true if ENV.key?(current) end false end
def default_setup
def default_setup env = ENV["RAILS_ENV"] || ENV["RACK_ENV"] || ENV["ENV"] development_mode = ["", nil, "development"].include?(env) unless ENV["DISABLE_BOOTSNAP"] cache_dir = ENV["BOOTSNAP_CACHE_DIR"] unless cache_dir config_dir_frame = caller.detect do |line| line.include?("/config/") end unless config_dir_frame $stderr.puts("[bootsnap/setup] couldn't infer cache directory! Either:") $stderr.puts("[bootsnap/setup] 1. require bootsnap/setup from your application's config directory; or") $stderr.puts("[bootsnap/setup] 2. Define the environment variable BOOTSNAP_CACHE_DIR") raise("couldn't infer bootsnap cache directory") end path = config_dir_frame.split(/:\d+:/).first path = File.dirname(path) until File.basename(path) == "config" app_root = File.dirname(path) cache_dir = File.join(app_root, "tmp", "cache") end ignore_directories = if ENV.key?("BOOTSNAP_IGNORE_DIRECTORIES") ENV["BOOTSNAP_IGNORE_DIRECTORIES"].split(",") end setup( cache_dir: cache_dir, development_mode: development_mode, load_path_cache: !ENV["DISABLE_BOOTSNAP_LOAD_PATH_CACHE"], compile_cache_iseq: !ENV["DISABLE_BOOTSNAP_COMPILE_CACHE"], compile_cache_yaml: !ENV["DISABLE_BOOTSNAP_COMPILE_CACHE"], compile_cache_json: !ENV["DISABLE_BOOTSNAP_COMPILE_CACHE"], readonly: !!ENV["BOOTSNAP_READONLY"], ignore_directories: ignore_directories, ) if ENV["BOOTSNAP_LOG"] log! elsif ENV["BOOTSNAP_STATS"] log_stats! end end end
def instrumentation=(callback)
def instrumentation=(callback) @instrumentation = callback if respond_to?(:instrumentation_enabled=, true) self.instrumentation_enabled = !!callback end end
def log!
def log! self.logger = $stderr.method(:puts) end
def log_stats!
def log_stats! stats = {hit: 0, revalidated: 0, miss: 0, stale: 0} self.instrumentation = ->(event, _path) { stats[event] += 1 } Kernel.at_exit do stats.each do |event, count| $stderr.puts "bootsnap #{event}: #{count}" end end end
def logger=(logger)
def logger=(logger) @logger = logger self.instrumentation = if logger.respond_to?(:debug) ->(event, path) { @logger.debug("[Bootsnap] #{event} #{path}") unless event == :hit } else ->(event, path) { @logger.call("[Bootsnap] #{event} #{path}") unless event == :hit } end end
def rb_get_path(fname)
The native version is very intricate and may behave differently on windows etc.
This is a semi-accurate ruby implementation of the native `rb_get_path(VALUE)` function.
def rb_get_path(fname) path_path = fname.respond_to?(:to_path) ? fname.to_path : fname String.try_convert(path_path) || raise(TypeError, "no implicit conversion of #{path_path.class} into String") end
def setup(
def setup( cache_dir:, development_mode: true, load_path_cache: true, ignore_directories: nil, readonly: false, revalidation: false, compile_cache_iseq: true, compile_cache_yaml: true, compile_cache_json: true ) if load_path_cache Bootsnap::LoadPathCache.setup( cache_path: "#{cache_dir}/bootsnap/load-path-cache", development_mode: development_mode, ignore_directories: ignore_directories, readonly: readonly, ) end Bootsnap::CompileCache.setup( cache_dir: "#{cache_dir}/bootsnap/compile-cache", iseq: compile_cache_iseq, yaml: compile_cache_yaml, json: compile_cache_json, readonly: readonly, revalidation: revalidation, ) end
def unload_cache!
def unload_cache! LoadPathCache.unload! end