module Bootsnap

Ruby C extensions are initialized by calling Init_<extname>.

This sets up the module hierarchy and attaches functions as methods.

We also populate some semi-static information about the current OS and so on.

Constants

InvalidConfiguration
VERSION

Attributes

cache_dir[R]
logger[R]

Public Class Methods

_instrument(event, path) click to toggle source
# File lib/bootsnap.rb, line 42
def _instrument(event, path)
  @instrumentation.call(event, path)
end
absolute_path?(path) click to toggle source
# File lib/bootsnap.rb, line 168
def absolute_path?(path)
  path[1] == ":"
end
default_setup() click to toggle source
# File lib/bootsnap.rb, line 117
def default_setup
  env = ENV["RAILS_ENV"] || ENV["RACK_ENV"] || ENV["ENV"]
  development_mode = ["", nil, "development"].include?(env)

  if enabled?("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: enabled?("BOOTSNAP_LOAD_PATH_CACHE"),
      compile_cache_iseq: enabled?("BOOTSNAP_COMPILE_CACHE"),
      compile_cache_yaml: enabled?("BOOTSNAP_COMPILE_CACHE"),
      readonly: bool_env("BOOTSNAP_READONLY"),
      revalidation: bool_env("BOOTSNAP_REVALIDATE"),
      ignore_directories: ignore_directories,
      config_path: ENV["BOOTSNAP_CONFIG"] || "config/bootsnap.rb",
    )

    if ENV["BOOTSNAP_LOG"]
      log!
    elsif ENV["BOOTSNAP_STATS"]
      log_stats!
    end
  end
end
enable_frozen_string_literal(app_only: false) click to toggle source
# File lib/bootsnap.rb, line 93
def enable_frozen_string_literal(app_only: false)
  if app_only
    gems_root = File.join(Bundler.bundle_path.cleanpath, "")
    app_root =  File.join(Dir.pwd, "")
    Bootsnap::CompileCache::ISeq.default_compiler = Bootsnap::CompileCache::ISeq::DEFAULT
    Bootsnap::CompileCache::ISeq.compiler_selector = lambda { |path|
      # Enable `frozen_string_literal: true` for app code, but not gems.

      if path.start_with?(app_root) && !path.start_with?(gems_root)
        Bootsnap::CompileCache::ISeq::FROZEN_STRING_LITERAL
      else
        Bootsnap::CompileCache::ISeq::DEFAULT
      end
    }
  else
    options = RubyVM::InstructionSequence.compile_option.merge(frozen_string_literal: true)
    RubyVM::InstructionSequence.compile_option = options
  end
end
instrumentation=(callback) click to toggle source
# File lib/bootsnap.rb, line 35
def instrumentation=(callback)
  @instrumentation = callback
  if respond_to?(:instrumentation_enabled=, true)
    self.instrumentation_enabled = !!callback
  end
end
instrumentation_enabled=(p1) click to toggle source
static VALUE
bs_instrumentation_enabled_set(VALUE self, VALUE enabled)
{
  instrumentation_enabled = RTEST(enabled);
  return enabled;
}
load_config(config_path) click to toggle source
# File lib/bootsnap.rb, line 84
def load_config(config_path)
  if config_path
    config_path = File.expand_path(config_path)
    if File.exist?(config_path)
      require(config_path)
    end
  end
end
log!() click to toggle source
# File lib/bootsnap.rb, line 22
def log!
  self.logger = $stderr.method(:puts)
end
log_stats!() click to toggle source
# File lib/bootsnap.rb, line 12
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
logger=(logger) click to toggle source
# File lib/bootsnap.rb, line 26
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
rb_get_path(p1) click to toggle source

Allow the C extension to redefine ‘rb_get_path` without warning.

static VALUE
bs_rb_get_path(VALUE self, VALUE fname)
{
    return rb_get_path(fname);
}
Also aliased as: rb_get_path
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: (compile_cache_json_unset = true), config_path: nil ) click to toggle source
# File lib/bootsnap.rb, line 46
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: (compile_cache_json_unset = true),
  config_path: nil
)
  unless compile_cache_json_unset
    warn("Bootsnap.setup `compile_cache_json` argument is deprecated and has no effect")
  end

  @cache_dir = "#{cache_dir}/bootsnap"

  if load_path_cache
    Bootsnap::LoadPathCache.setup(
      cache_path: "#{@cache_dir}/load-path-cache",
      development_mode: development_mode,
      ignore_directories: ignore_directories,
      readonly: readonly,
    )
  end

  Bootsnap::CompileCache.setup(
    cache_dir: "#{@cache_dir}/compile-cache",
    iseq: compile_cache_iseq,
    yaml: compile_cache_yaml,
    readonly: readonly,
    revalidation: revalidation,
  )

  load_config(config_path)
end
unload_cache!() click to toggle source
# File lib/bootsnap.rb, line 113
def unload_cache!
  LoadPathCache.unload!
end

Private Class Methods

bool_env(key, default: false) click to toggle source
# File lib/bootsnap.rb, line 194
def bool_env(key, default: false)
  value = ENV.fetch(key) { default }
  !["0", "false", false].include?(value)
end
enabled?(key) click to toggle source
# File lib/bootsnap.rb, line 190
def enabled?(key)
  !ENV["DISABLE_#{key}"]
end

Public Instance Methods

bundler?() click to toggle source
# File lib/bootsnap/bundler.rb, line 6
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