class Bootsnap::LoadPathCache::Path

Constants

RUBY_LIBDIR

Built-in ruby lib stuff doesn’t change, but things can occasionally be installed into sitedir, which generally lives under rubylibdir.

RUBY_SITEDIR
STABLE

a Path can be either stable of volatile, depending on how frequently we expect its contents may change. Stable paths aren’t rescanned nearly as often.

VOLATILE

Attributes

path[R]

Public Class Methods

new(path, real: false) click to toggle source
# File lib/bootsnap/load_path_cache/path.rb, line 24
def initialize(path, real: false)
  @path = path.to_s.freeze
  @real = real
end

Public Instance Methods

entries(store) click to toggle source

Return a list of all the requirable files of this Path.

# File lib/bootsnap/load_path_cache/path.rb, line 58
def entries(store)
  if stable?
    # the cached_mtime field is unused for 'stable' paths, but is
    # set to zero anyway, just in case we change the stability heuristics.
    _, entries, = store.get(expanded_path)
    return entries if entries # cache hit

    entries = PathScanner.call(expanded_path)
    store.set(expanded_path, [0, entries])
    return entries
  end

  cached_mtime, entries = store.get(expanded_path)

  current_mtime = latest_mtime(expanded_path, entries || [])
  return [] if current_mtime == -1 # path does not exist
  return entries if cached_mtime == current_mtime

  entries = PathScanner.call(expanded_path)
  store.set(expanded_path, [current_mtime, entries])
  entries
end
expanded_path() click to toggle source
# File lib/bootsnap/load_path_cache/path.rb, line 81
def expanded_path
  if @real
    path
  else
    @expanded_path ||= File.expand_path(path).freeze
  end
end
non_directory?() click to toggle source

True if the path exists, but represents a non-directory object

# File lib/bootsnap/load_path_cache/path.rb, line 47
def non_directory?
  !File.stat(path).directory?
rescue Errno::ENOENT, Errno::ENOTDIR, Errno::EINVAL
  false
end
relative?() click to toggle source
# File lib/bootsnap/load_path_cache/path.rb, line 53
def relative?
  !path.start_with?(SLASH)
end
stable?() click to toggle source

A path is considered ‘stable’ if it is part of a Gem.path or the ruby distribution. When adding or removing files in these paths, the cache must be cleared before the change will be noticed.

# File lib/bootsnap/load_path_cache/path.rb, line 11
def stable?
  stability == STABLE
end
to_realpath() click to toggle source
# File lib/bootsnap/load_path_cache/path.rb, line 29
def to_realpath
  return self if @real

  realpath = begin
    File.realpath(path)
  rescue Errno::ENOENT
    return self
  end

  if realpath == path
    @real = true
    self
  else
    Path.new(realpath, real: true)
  end
end
volatile?() click to toggle source

A path is considered volatile if it doesn’t live under a Gem.path or the ruby distribution root. These paths are scanned for new additions more frequently.

# File lib/bootsnap/load_path_cache/path.rb, line 18
def volatile?
  stability == VOLATILE
end

Private Instance Methods

latest_mtime(root_path, entries) click to toggle source

last time a directory was modified in this subtree. dirs should be a list of relative paths to directories under path. e.g. for /a/b and /a/b/c, pass (‘/a/b’, [‘c’])

# File lib/bootsnap/load_path_cache/path.rb, line 94
def latest_mtime(root_path, entries)
  max = begin
    File.mtime(root_path).to_i
  rescue Errno::ENOENT, Errno::ENOTDIR, Errno::EINVAL
    -1
  end

  visited = {"." => true}

  entries.each do |relpath|
    dirname = File.dirname(relpath)
    visited[dirname] ||= begin
      begin
        current = File.mtime(File.join(root_path, dirname)).to_i
        max = current if current > max
      rescue Errno::ENOENT, Errno::ENOTDIR, Errno::EINVAL
        # ignore
      end
      true
    end
  end

  max
end
stability() click to toggle source
# File lib/bootsnap/load_path_cache/path.rb, line 130
def stability
  @stability ||= if Gem.path.detect { |p| expanded_path.start_with?(p.to_s) }
    STABLE
  elsif Bootsnap.bundler? && expanded_path.start_with?(Bundler.bundle_path.to_s)
    STABLE
  elsif expanded_path.start_with?(RUBY_LIBDIR) && !expanded_path.start_with?(RUBY_SITEDIR)
    STABLE
  else
    VOLATILE
  end
end