bootsnap 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
 - data/.gitignore +17 -0
 - data/.rubocop.yml +7 -0
 - data/CONTRIBUTING.md +21 -0
 - data/Gemfile +4 -0
 - data/README.md +49 -0
 - data/Rakefile +11 -0
 - data/bin/console +14 -0
 - data/bin/setup +8 -0
 - data/bin/testunit +8 -0
 - data/bootsnap.gemspec +34 -0
 - data/dev.yml +5 -0
 - data/ext/bootsnap/bootsnap.c +542 -0
 - data/ext/bootsnap/bootsnap.h +10 -0
 - data/ext/bootsnap/crc32.c +16 -0
 - data/ext/bootsnap/extconf.rb +7 -0
 - data/lib/bootsnap.rb +38 -0
 - data/lib/bootsnap/compile_cache.rb +16 -0
 - data/lib/bootsnap/compile_cache/iseq.rb +74 -0
 - data/lib/bootsnap/compile_cache/yaml.rb +54 -0
 - data/lib/bootsnap/explicit_require.rb +44 -0
 - data/lib/bootsnap/load_path_cache.rb +52 -0
 - data/lib/bootsnap/load_path_cache/cache.rb +150 -0
 - data/lib/bootsnap/load_path_cache/change_observer.rb +56 -0
 - data/lib/bootsnap/load_path_cache/core_ext/active_support.rb +68 -0
 - data/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb +88 -0
 - data/lib/bootsnap/load_path_cache/path.rb +93 -0
 - data/lib/bootsnap/load_path_cache/path_scanner.rb +44 -0
 - data/lib/bootsnap/load_path_cache/store.rb +77 -0
 - data/lib/bootsnap/version.rb +3 -0
 - metadata +172 -0
 
| 
         @@ -0,0 +1,56 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Bootsnap
         
     | 
| 
      
 2 
     | 
    
         
            +
              module LoadPathCache
         
     | 
| 
      
 3 
     | 
    
         
            +
                module ChangeObserver
         
     | 
| 
      
 4 
     | 
    
         
            +
                  def self.register(observer, arr)
         
     | 
| 
      
 5 
     | 
    
         
            +
                    # Re-overriding these methods on an array that already has them would
         
     | 
| 
      
 6 
     | 
    
         
            +
                    # cause StackOverflowErrors
         
     | 
| 
      
 7 
     | 
    
         
            +
                    return if arr.respond_to?(:push_without_lpc)
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                    # For each method that adds items to one end or another of the array
         
     | 
| 
      
 10 
     | 
    
         
            +
                    # (<<, push, unshift, concat), override that method to also notify the
         
     | 
| 
      
 11 
     | 
    
         
            +
                    # observer of the change.
         
     | 
| 
      
 12 
     | 
    
         
            +
                    sc = arr.singleton_class
         
     | 
| 
      
 13 
     | 
    
         
            +
                    sc.send(:alias_method, :shovel_without_lpc, :<<)
         
     | 
| 
      
 14 
     | 
    
         
            +
                    arr.define_singleton_method(:<<) do |entry|
         
     | 
| 
      
 15 
     | 
    
         
            +
                      observer.push_paths(self, entry)
         
     | 
| 
      
 16 
     | 
    
         
            +
                      shovel_without_lpc(entry)
         
     | 
| 
      
 17 
     | 
    
         
            +
                    end
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                    sc.send(:alias_method, :push_without_lpc, :push)
         
     | 
| 
      
 20 
     | 
    
         
            +
                    arr.define_singleton_method(:push) do |*entries|
         
     | 
| 
      
 21 
     | 
    
         
            +
                      observer.push_paths(self, *entries)
         
     | 
| 
      
 22 
     | 
    
         
            +
                      push_without_lpc(*entries)
         
     | 
| 
      
 23 
     | 
    
         
            +
                    end
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                    sc.send(:alias_method, :unshift_without_lpc, :unshift)
         
     | 
| 
      
 26 
     | 
    
         
            +
                    arr.define_singleton_method(:unshift) do |*entries|
         
     | 
| 
      
 27 
     | 
    
         
            +
                      observer.unshift_paths(self, *entries)
         
     | 
| 
      
 28 
     | 
    
         
            +
                      unshift_without_lpc(*entries)
         
     | 
| 
      
 29 
     | 
    
         
            +
                    end
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
                    sc.send(:alias_method, :concat_without_lpc, :concat)
         
     | 
| 
      
 32 
     | 
    
         
            +
                    arr.define_singleton_method(:concat) do |entries|
         
     | 
| 
      
 33 
     | 
    
         
            +
                      observer.push_paths(self, *entries)
         
     | 
| 
      
 34 
     | 
    
         
            +
                      concat_without_lpc(entries)
         
     | 
| 
      
 35 
     | 
    
         
            +
                    end
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
                    # For each method that modifies the array more aggressively, override
         
     | 
| 
      
 38 
     | 
    
         
            +
                    # the method to also have the observer completely reconstruct its state
         
     | 
| 
      
 39 
     | 
    
         
            +
                    # after the modification. Many of these could be made to modify the
         
     | 
| 
      
 40 
     | 
    
         
            +
                    # internal state of the LoadPathCache::Cache more efficiently, but the
         
     | 
| 
      
 41 
     | 
    
         
            +
                    # accounting cost would be greater than the hit from these, since we
         
     | 
| 
      
 42 
     | 
    
         
            +
                    # actively discourage calling them.
         
     | 
| 
      
 43 
     | 
    
         
            +
                    %i(
         
     | 
| 
      
 44 
     | 
    
         
            +
                      collect! compact! delete delete_at delete_if fill flatten! insert map!
         
     | 
| 
      
 45 
     | 
    
         
            +
                      reject! reverse! select! shuffle! shift slice! sort! sort_by!
         
     | 
| 
      
 46 
     | 
    
         
            +
                    ).each do |meth|
         
     | 
| 
      
 47 
     | 
    
         
            +
                      sc.send(:alias_method, :"#{meth}_without_lpc", meth)
         
     | 
| 
      
 48 
     | 
    
         
            +
                      arr.define_singleton_method(meth) do |*a|
         
     | 
| 
      
 49 
     | 
    
         
            +
                        send(:"#{meth}_without_lpc", *a)
         
     | 
| 
      
 50 
     | 
    
         
            +
                        observer.reinitialize
         
     | 
| 
      
 51 
     | 
    
         
            +
                      end
         
     | 
| 
      
 52 
     | 
    
         
            +
                    end
         
     | 
| 
      
 53 
     | 
    
         
            +
                  end
         
     | 
| 
      
 54 
     | 
    
         
            +
                end
         
     | 
| 
      
 55 
     | 
    
         
            +
              end
         
     | 
| 
      
 56 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,68 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Bootsnap
         
     | 
| 
      
 2 
     | 
    
         
            +
              module LoadPathCache
         
     | 
| 
      
 3 
     | 
    
         
            +
                module CoreExt
         
     | 
| 
      
 4 
     | 
    
         
            +
                  module ActiveSupport
         
     | 
| 
      
 5 
     | 
    
         
            +
                    def self.with_bootsnap_fallback(error)
         
     | 
| 
      
 6 
     | 
    
         
            +
                      yield
         
     | 
| 
      
 7 
     | 
    
         
            +
                    rescue error
         
     | 
| 
      
 8 
     | 
    
         
            +
                      without_bootsnap_cache { yield }
         
     | 
| 
      
 9 
     | 
    
         
            +
                    end
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                    def self.without_bootsnap_cache
         
     | 
| 
      
 12 
     | 
    
         
            +
                      prev = Thread.current[:without_bootsnap_cache] || false
         
     | 
| 
      
 13 
     | 
    
         
            +
                      Thread.current[:without_bootsnap_cache] = true
         
     | 
| 
      
 14 
     | 
    
         
            +
                      yield
         
     | 
| 
      
 15 
     | 
    
         
            +
                    ensure
         
     | 
| 
      
 16 
     | 
    
         
            +
                      Thread.current[:without_bootsnap_cache] = prev
         
     | 
| 
      
 17 
     | 
    
         
            +
                    end
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                    module ClassMethods
         
     | 
| 
      
 20 
     | 
    
         
            +
                      def autoload_paths=(o)
         
     | 
| 
      
 21 
     | 
    
         
            +
                        r = super
         
     | 
| 
      
 22 
     | 
    
         
            +
                        Bootsnap::LoadPathCache.autoload_paths_cache.reinitialize(o)
         
     | 
| 
      
 23 
     | 
    
         
            +
                        r
         
     | 
| 
      
 24 
     | 
    
         
            +
                      end
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
                      def search_for_file(path)
         
     | 
| 
      
 27 
     | 
    
         
            +
                        return super if Thread.current[:without_bootsnap_cache]
         
     | 
| 
      
 28 
     | 
    
         
            +
                        begin
         
     | 
| 
      
 29 
     | 
    
         
            +
                          Bootsnap::LoadPathCache.autoload_paths_cache.find(path)
         
     | 
| 
      
 30 
     | 
    
         
            +
                        rescue Bootsnap::LoadPathCache::ReturnFalse
         
     | 
| 
      
 31 
     | 
    
         
            +
                          nil # doesn't really apply here
         
     | 
| 
      
 32 
     | 
    
         
            +
                        end
         
     | 
| 
      
 33 
     | 
    
         
            +
                      end
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
                      def autoloadable_module?(path_suffix)
         
     | 
| 
      
 36 
     | 
    
         
            +
                        Bootsnap::LoadPathCache.autoload_paths_cache.has_dir?(path_suffix)
         
     | 
| 
      
 37 
     | 
    
         
            +
                      end
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
                      def remove_constant(const)
         
     | 
| 
      
 40 
     | 
    
         
            +
                        CoreExt::ActiveSupport.without_bootsnap_cache { super }
         
     | 
| 
      
 41 
     | 
    
         
            +
                      end
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
                      # If we can't find a constant using the patched implementation of
         
     | 
| 
      
 44 
     | 
    
         
            +
                      # search_for_file, try again with the default implementation.
         
     | 
| 
      
 45 
     | 
    
         
            +
                      #
         
     | 
| 
      
 46 
     | 
    
         
            +
                      # These methods call search_for_file, and we want to modify its
         
     | 
| 
      
 47 
     | 
    
         
            +
                      # behaviour.  The gymnastics here are a bit awkward, but it prevents
         
     | 
| 
      
 48 
     | 
    
         
            +
                      # 200+ lines of monkeypatches.
         
     | 
| 
      
 49 
     | 
    
         
            +
                      def load_missing_constant(from_mod, const_name)
         
     | 
| 
      
 50 
     | 
    
         
            +
                        CoreExt::ActiveSupport.with_bootsnap_fallback(NameError) { super }
         
     | 
| 
      
 51 
     | 
    
         
            +
                      end
         
     | 
| 
      
 52 
     | 
    
         
            +
             
     | 
| 
      
 53 
     | 
    
         
            +
                      def depend_on(file_name, message = "No such file to load -- %s.rb")
         
     | 
| 
      
 54 
     | 
    
         
            +
                        CoreExt::ActiveSupport.with_bootsnap_fallback(LoadError) { super }
         
     | 
| 
      
 55 
     | 
    
         
            +
                      end
         
     | 
| 
      
 56 
     | 
    
         
            +
                    end
         
     | 
| 
      
 57 
     | 
    
         
            +
                  end
         
     | 
| 
      
 58 
     | 
    
         
            +
                end
         
     | 
| 
      
 59 
     | 
    
         
            +
              end
         
     | 
| 
      
 60 
     | 
    
         
            +
            end
         
     | 
| 
      
 61 
     | 
    
         
            +
             
     | 
| 
      
 62 
     | 
    
         
            +
            module ActiveSupport
         
     | 
| 
      
 63 
     | 
    
         
            +
              module Dependencies
         
     | 
| 
      
 64 
     | 
    
         
            +
                class << self
         
     | 
| 
      
 65 
     | 
    
         
            +
                  prepend Bootsnap::LoadPathCache::CoreExt::ActiveSupport::ClassMethods
         
     | 
| 
      
 66 
     | 
    
         
            +
                end
         
     | 
| 
      
 67 
     | 
    
         
            +
              end
         
     | 
| 
      
 68 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,88 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Bootsnap
         
     | 
| 
      
 2 
     | 
    
         
            +
              module LoadPathCache
         
     | 
| 
      
 3 
     | 
    
         
            +
                module CoreExt
         
     | 
| 
      
 4 
     | 
    
         
            +
                  def self.make_load_error(path)
         
     | 
| 
      
 5 
     | 
    
         
            +
                    err = LoadError.new("cannot load such file -- #{path}")
         
     | 
| 
      
 6 
     | 
    
         
            +
                    err.define_singleton_method(:path) { path }
         
     | 
| 
      
 7 
     | 
    
         
            +
                    err
         
     | 
| 
      
 8 
     | 
    
         
            +
                  end
         
     | 
| 
      
 9 
     | 
    
         
            +
                end
         
     | 
| 
      
 10 
     | 
    
         
            +
              end
         
     | 
| 
      
 11 
     | 
    
         
            +
            end
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
            module Kernel
         
     | 
| 
      
 14 
     | 
    
         
            +
              alias_method :require_without_cache, :require
         
     | 
| 
      
 15 
     | 
    
         
            +
              def require(path)
         
     | 
| 
      
 16 
     | 
    
         
            +
                if resolved = Bootsnap::LoadPathCache.load_path_cache.find(path)
         
     | 
| 
      
 17 
     | 
    
         
            +
                  require_without_cache(resolved)
         
     | 
| 
      
 18 
     | 
    
         
            +
                else
         
     | 
| 
      
 19 
     | 
    
         
            +
                  raise Bootsnap::LoadPathCache::CoreExt.make_load_error(path)
         
     | 
| 
      
 20 
     | 
    
         
            +
                end
         
     | 
| 
      
 21 
     | 
    
         
            +
              rescue Bootsnap::LoadPathCache::ReturnFalse
         
     | 
| 
      
 22 
     | 
    
         
            +
                return false
         
     | 
| 
      
 23 
     | 
    
         
            +
              rescue Bootsnap::LoadPathCache::FallbackScan
         
     | 
| 
      
 24 
     | 
    
         
            +
                require_without_cache(path)
         
     | 
| 
      
 25 
     | 
    
         
            +
              end
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
              alias_method :load_without_cache, :load
         
     | 
| 
      
 28 
     | 
    
         
            +
              def load(path, wrap = false)
         
     | 
| 
      
 29 
     | 
    
         
            +
                if resolved = Bootsnap::LoadPathCache.load_path_cache.find(path)
         
     | 
| 
      
 30 
     | 
    
         
            +
                  load_without_cache(resolved, wrap)
         
     | 
| 
      
 31 
     | 
    
         
            +
                else
         
     | 
| 
      
 32 
     | 
    
         
            +
                  # load also allows relative paths from pwd even when not in $:
         
     | 
| 
      
 33 
     | 
    
         
            +
                  relative = File.expand_path(path)
         
     | 
| 
      
 34 
     | 
    
         
            +
                  if File.exist?(File.expand_path(path))
         
     | 
| 
      
 35 
     | 
    
         
            +
                    return load_without_cache(relative, wrap)
         
     | 
| 
      
 36 
     | 
    
         
            +
                  end
         
     | 
| 
      
 37 
     | 
    
         
            +
                  raise Bootsnap::LoadPathCache::CoreExt.make_load_error(path)
         
     | 
| 
      
 38 
     | 
    
         
            +
                end
         
     | 
| 
      
 39 
     | 
    
         
            +
              rescue Bootsnap::LoadPathCache::ReturnFalse
         
     | 
| 
      
 40 
     | 
    
         
            +
                return false
         
     | 
| 
      
 41 
     | 
    
         
            +
              rescue Bootsnap::LoadPathCache::FallbackScan
         
     | 
| 
      
 42 
     | 
    
         
            +
                load_without_cache(path, wrap)
         
     | 
| 
      
 43 
     | 
    
         
            +
              end
         
     | 
| 
      
 44 
     | 
    
         
            +
            end
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
      
 46 
     | 
    
         
            +
            class << Kernel
         
     | 
| 
      
 47 
     | 
    
         
            +
              alias_method :require_without_cache, :require
         
     | 
| 
      
 48 
     | 
    
         
            +
              def require(path)
         
     | 
| 
      
 49 
     | 
    
         
            +
                if resolved = Bootsnap::LoadPathCache.load_path_cache.find(path)
         
     | 
| 
      
 50 
     | 
    
         
            +
                  require_without_cache(resolved)
         
     | 
| 
      
 51 
     | 
    
         
            +
                else
         
     | 
| 
      
 52 
     | 
    
         
            +
                  raise Bootsnap::LoadPathCache::CoreExt.make_load_error(path)
         
     | 
| 
      
 53 
     | 
    
         
            +
                end
         
     | 
| 
      
 54 
     | 
    
         
            +
              rescue Bootsnap::LoadPathCache::ReturnFalse
         
     | 
| 
      
 55 
     | 
    
         
            +
                return false
         
     | 
| 
      
 56 
     | 
    
         
            +
              rescue Bootsnap::LoadPathCache::FallbackScan
         
     | 
| 
      
 57 
     | 
    
         
            +
                require_without_cache(path)
         
     | 
| 
      
 58 
     | 
    
         
            +
              end
         
     | 
| 
      
 59 
     | 
    
         
            +
             
     | 
| 
      
 60 
     | 
    
         
            +
              alias_method :load_without_cache, :load
         
     | 
| 
      
 61 
     | 
    
         
            +
              def load(path, wrap = false)
         
     | 
| 
      
 62 
     | 
    
         
            +
                if resolved = Bootsnap::LoadPathCache.load_path_cache.find(path)
         
     | 
| 
      
 63 
     | 
    
         
            +
                  load_without_cache(resolved, wrap)
         
     | 
| 
      
 64 
     | 
    
         
            +
                else
         
     | 
| 
      
 65 
     | 
    
         
            +
                  # load also allows relative paths from pwd even when not in $:
         
     | 
| 
      
 66 
     | 
    
         
            +
                  relative = File.expand_path(path)
         
     | 
| 
      
 67 
     | 
    
         
            +
                  if File.exist?(relative)
         
     | 
| 
      
 68 
     | 
    
         
            +
                    return load_without_cache(relative, wrap)
         
     | 
| 
      
 69 
     | 
    
         
            +
                  end
         
     | 
| 
      
 70 
     | 
    
         
            +
                  raise Bootsnap::LoadPathCache::CoreExt.make_load_error(path)
         
     | 
| 
      
 71 
     | 
    
         
            +
                end
         
     | 
| 
      
 72 
     | 
    
         
            +
              rescue Bootsnap::LoadPathCache::ReturnFalse
         
     | 
| 
      
 73 
     | 
    
         
            +
                return false
         
     | 
| 
      
 74 
     | 
    
         
            +
              rescue Bootsnap::LoadPathCache::FallbackScan
         
     | 
| 
      
 75 
     | 
    
         
            +
                load_without_cache(path, wrap)
         
     | 
| 
      
 76 
     | 
    
         
            +
              end
         
     | 
| 
      
 77 
     | 
    
         
            +
            end
         
     | 
| 
      
 78 
     | 
    
         
            +
             
     | 
| 
      
 79 
     | 
    
         
            +
            class Module
         
     | 
| 
      
 80 
     | 
    
         
            +
              alias_method :autoload_without_cache, :autoload
         
     | 
| 
      
 81 
     | 
    
         
            +
              def autoload(const, path)
         
     | 
| 
      
 82 
     | 
    
         
            +
                autoload_without_cache(const, Bootsnap::LoadPathCache.load_path_cache.find(path) || path)
         
     | 
| 
      
 83 
     | 
    
         
            +
              rescue Bootsnap::LoadPathCache::ReturnFalse
         
     | 
| 
      
 84 
     | 
    
         
            +
                return false
         
     | 
| 
      
 85 
     | 
    
         
            +
              rescue Bootsnap::LoadPathCache::FallbackScan
         
     | 
| 
      
 86 
     | 
    
         
            +
                autoload_without_cache(const, path)
         
     | 
| 
      
 87 
     | 
    
         
            +
              end
         
     | 
| 
      
 88 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,93 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require_relative 'path_scanner'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module Bootsnap
         
     | 
| 
      
 4 
     | 
    
         
            +
              module LoadPathCache
         
     | 
| 
      
 5 
     | 
    
         
            +
                class Path
         
     | 
| 
      
 6 
     | 
    
         
            +
                  # A path is considered 'stable' if it is part of a Gem.path or the ruby
         
     | 
| 
      
 7 
     | 
    
         
            +
                  # distribution. When adding or removing files in these paths, the cache
         
     | 
| 
      
 8 
     | 
    
         
            +
                  # must be cleared before the change will be noticed.
         
     | 
| 
      
 9 
     | 
    
         
            +
                  def stable?
         
     | 
| 
      
 10 
     | 
    
         
            +
                    stability == STABLE
         
     | 
| 
      
 11 
     | 
    
         
            +
                  end
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                  # A path is considered volatile if it doesn't live under a Gem.path or
         
     | 
| 
      
 14 
     | 
    
         
            +
                  # the ruby distribution root. These paths are scanned for new additions
         
     | 
| 
      
 15 
     | 
    
         
            +
                  # more frequently.
         
     | 
| 
      
 16 
     | 
    
         
            +
                  def volatile?
         
     | 
| 
      
 17 
     | 
    
         
            +
                    stability == VOLATILE
         
     | 
| 
      
 18 
     | 
    
         
            +
                  end
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                  attr_reader :path
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                  def initialize(path)
         
     | 
| 
      
 23 
     | 
    
         
            +
                    @path = path
         
     | 
| 
      
 24 
     | 
    
         
            +
                  end
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
                  # Return a list of all the requirable files and all of the subdirectories
         
     | 
| 
      
 27 
     | 
    
         
            +
                  # of this +Path+.
         
     | 
| 
      
 28 
     | 
    
         
            +
                  def entries_and_dirs(store)
         
     | 
| 
      
 29 
     | 
    
         
            +
                    if stable?
         
     | 
| 
      
 30 
     | 
    
         
            +
                      # the cached_mtime field is unused for 'stable' paths, but is
         
     | 
| 
      
 31 
     | 
    
         
            +
                      # set to zero anyway, just in case we change the stability heuristics.
         
     | 
| 
      
 32 
     | 
    
         
            +
                      _, entries, dirs = store.get(path)
         
     | 
| 
      
 33 
     | 
    
         
            +
                      return [entries, dirs] if entries # cache hit
         
     | 
| 
      
 34 
     | 
    
         
            +
                      entries, dirs = scan!
         
     | 
| 
      
 35 
     | 
    
         
            +
                      store.set(path, [0, entries, dirs])
         
     | 
| 
      
 36 
     | 
    
         
            +
                      return [entries, dirs]
         
     | 
| 
      
 37 
     | 
    
         
            +
                    end
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
                    cached_mtime, entries, dirs = store.get(path)
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
                    current_mtime = latest_mtime(path, dirs || [])
         
     | 
| 
      
 42 
     | 
    
         
            +
                    return [[], []]        if current_mtime == -1 # path does not exist
         
     | 
| 
      
 43 
     | 
    
         
            +
                    return [entries, dirs] if cached_mtime == current_mtime
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
                    entries, dirs = scan!
         
     | 
| 
      
 46 
     | 
    
         
            +
                    store.set(path, [current_mtime, entries, dirs])
         
     | 
| 
      
 47 
     | 
    
         
            +
                    [entries, dirs]
         
     | 
| 
      
 48 
     | 
    
         
            +
                  end
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
                  private
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
                  def scan! # (expensive) returns [entries, dirs]
         
     | 
| 
      
 53 
     | 
    
         
            +
                    PathScanner.call(path)
         
     | 
| 
      
 54 
     | 
    
         
            +
                  end
         
     | 
| 
      
 55 
     | 
    
         
            +
             
     | 
| 
      
 56 
     | 
    
         
            +
                  # last time a directory was modified in this subtree. +dirs+ should be a
         
     | 
| 
      
 57 
     | 
    
         
            +
                  # list of relative paths to directories under +path+. e.g. for /a/b and
         
     | 
| 
      
 58 
     | 
    
         
            +
                  # /a/b/c, pass ('/a/b', ['c'])
         
     | 
| 
      
 59 
     | 
    
         
            +
                  def latest_mtime(path, dirs)
         
     | 
| 
      
 60 
     | 
    
         
            +
                    max = -1
         
     | 
| 
      
 61 
     | 
    
         
            +
                    ["", *dirs].each do |dir|
         
     | 
| 
      
 62 
     | 
    
         
            +
                      curr = begin
         
     | 
| 
      
 63 
     | 
    
         
            +
                        File.mtime("#{path}/#{dir}").to_i
         
     | 
| 
      
 64 
     | 
    
         
            +
                      rescue Errno::ENOENT
         
     | 
| 
      
 65 
     | 
    
         
            +
                        -1
         
     | 
| 
      
 66 
     | 
    
         
            +
                      end
         
     | 
| 
      
 67 
     | 
    
         
            +
                      max = curr if curr > max
         
     | 
| 
      
 68 
     | 
    
         
            +
                    end
         
     | 
| 
      
 69 
     | 
    
         
            +
                    max
         
     | 
| 
      
 70 
     | 
    
         
            +
                  end
         
     | 
| 
      
 71 
     | 
    
         
            +
             
     | 
| 
      
 72 
     | 
    
         
            +
                  # a Path can be either stable of volatile, depending on how frequently we
         
     | 
| 
      
 73 
     | 
    
         
            +
                  # expect its contents may change. Stable paths aren't rescanned nearly as
         
     | 
| 
      
 74 
     | 
    
         
            +
                  # often.
         
     | 
| 
      
 75 
     | 
    
         
            +
                  STABLE   = :stable
         
     | 
| 
      
 76 
     | 
    
         
            +
                  VOLATILE = :volatile
         
     | 
| 
      
 77 
     | 
    
         
            +
             
     | 
| 
      
 78 
     | 
    
         
            +
                  RUBY_PREFIX = RbConfig::CONFIG['prefix']
         
     | 
| 
      
 79 
     | 
    
         
            +
             
     | 
| 
      
 80 
     | 
    
         
            +
                  def stability
         
     | 
| 
      
 81 
     | 
    
         
            +
                    @stability ||= begin
         
     | 
| 
      
 82 
     | 
    
         
            +
                      if Gem.path.detect { |p| path.start_with?(p) }
         
     | 
| 
      
 83 
     | 
    
         
            +
                        STABLE
         
     | 
| 
      
 84 
     | 
    
         
            +
                      elsif path.start_with?(RUBY_PREFIX)
         
     | 
| 
      
 85 
     | 
    
         
            +
                        STABLE
         
     | 
| 
      
 86 
     | 
    
         
            +
                      else
         
     | 
| 
      
 87 
     | 
    
         
            +
                        VOLATILE
         
     | 
| 
      
 88 
     | 
    
         
            +
                      end
         
     | 
| 
      
 89 
     | 
    
         
            +
                    end
         
     | 
| 
      
 90 
     | 
    
         
            +
                  end
         
     | 
| 
      
 91 
     | 
    
         
            +
                end
         
     | 
| 
      
 92 
     | 
    
         
            +
              end
         
     | 
| 
      
 93 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,44 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require_relative '../load_path_cache'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module Bootsnap
         
     | 
| 
      
 4 
     | 
    
         
            +
              module LoadPathCache
         
     | 
| 
      
 5 
     | 
    
         
            +
                module PathScanner
         
     | 
| 
      
 6 
     | 
    
         
            +
                  RelativePathNotSupported = Class.new(StandardError)
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
                  REQUIRABLES_AND_DIRS = "/**/*{#{DOT_RB},#{DL_EXTENSIONS.join(',')},/}"
         
     | 
| 
      
 9 
     | 
    
         
            +
                  IS_DIR = %r{(.*)/\z}
         
     | 
| 
      
 10 
     | 
    
         
            +
                  NORMALIZE_NATIVE_EXTENSIONS = !DL_EXTENSIONS.include?(LoadPathCache::DOT_SO)
         
     | 
| 
      
 11 
     | 
    
         
            +
                  ALTERNATIVE_NATIVE_EXTENSIONS_PATTERN = /\.(o|bundle|dylib)\z/
         
     | 
| 
      
 12 
     | 
    
         
            +
                  BUNDLE_PATH = (Bundler.bundle_path.cleanpath.to_s << LoadPathCache::SLASH).freeze
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                  def self.call(path)
         
     | 
| 
      
 15 
     | 
    
         
            +
                    raise RelativePathNotSupported unless path.start_with?(SLASH)
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                    relative_slice = (path.size + 1)..-1
         
     | 
| 
      
 18 
     | 
    
         
            +
                    # If the bundle path is a descendent of this path, we do additional
         
     | 
| 
      
 19 
     | 
    
         
            +
                    # checks to prevent recursing into the bundle path as we recurse
         
     | 
| 
      
 20 
     | 
    
         
            +
                    # through this path. We don't want to scan the bundle path because
         
     | 
| 
      
 21 
     | 
    
         
            +
                    # anything useful in it will be present on other load path items.
         
     | 
| 
      
 22 
     | 
    
         
            +
                    #
         
     | 
| 
      
 23 
     | 
    
         
            +
                    # This can happen if, for example, the user adds '.' to the load path,
         
     | 
| 
      
 24 
     | 
    
         
            +
                    # and the bundle path is '.bundle'.
         
     | 
| 
      
 25 
     | 
    
         
            +
                    contains_bundle_path = BUNDLE_PATH.start_with?(path)
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                    dirs = []
         
     | 
| 
      
 28 
     | 
    
         
            +
                    requirables = []
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
                    Dir.glob(path + REQUIRABLES_AND_DIRS).each do |absolute_path|
         
     | 
| 
      
 31 
     | 
    
         
            +
                      next if contains_bundle_path && absolute_path.start_with?(BUNDLE_PATH)
         
     | 
| 
      
 32 
     | 
    
         
            +
                      relative_path = absolute_path.slice!(relative_slice)
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                      if md = relative_path.match(IS_DIR)
         
     | 
| 
      
 35 
     | 
    
         
            +
                        dirs << md[1]
         
     | 
| 
      
 36 
     | 
    
         
            +
                      else
         
     | 
| 
      
 37 
     | 
    
         
            +
                        requirables << relative_path
         
     | 
| 
      
 38 
     | 
    
         
            +
                      end
         
     | 
| 
      
 39 
     | 
    
         
            +
                    end
         
     | 
| 
      
 40 
     | 
    
         
            +
                    [requirables, dirs]
         
     | 
| 
      
 41 
     | 
    
         
            +
                  end
         
     | 
| 
      
 42 
     | 
    
         
            +
                end
         
     | 
| 
      
 43 
     | 
    
         
            +
              end
         
     | 
| 
      
 44 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,77 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require_relative '../explicit_require'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            Bootsnap::ExplicitRequire.with_gems('snappy')  { require 'snappy' }
         
     | 
| 
      
 4 
     | 
    
         
            +
            Bootsnap::ExplicitRequire.with_gems('msgpack') { require 'msgpack' }
         
     | 
| 
      
 5 
     | 
    
         
            +
            Bootsnap::ExplicitRequire.from_rubylibdir('fileutils')
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
            module Bootsnap
         
     | 
| 
      
 8 
     | 
    
         
            +
              module LoadPathCache
         
     | 
| 
      
 9 
     | 
    
         
            +
                class Store
         
     | 
| 
      
 10 
     | 
    
         
            +
                  NestedTransactionError = Class.new(StandardError)
         
     | 
| 
      
 11 
     | 
    
         
            +
                  SetOutsideTransactionNotAllowed = Class.new(StandardError)
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                  def initialize(store_path)
         
     | 
| 
      
 14 
     | 
    
         
            +
                    @store_path = store_path
         
     | 
| 
      
 15 
     | 
    
         
            +
                    load_data
         
     | 
| 
      
 16 
     | 
    
         
            +
                  end
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                  def get(key)
         
     | 
| 
      
 19 
     | 
    
         
            +
                    @data[key]
         
     | 
| 
      
 20 
     | 
    
         
            +
                  end
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                  def fetch(key)
         
     | 
| 
      
 23 
     | 
    
         
            +
                    raise SetOutsideTransactionNotAllowed unless @in_txn
         
     | 
| 
      
 24 
     | 
    
         
            +
                    v = get(key)
         
     | 
| 
      
 25 
     | 
    
         
            +
                    unless v
         
     | 
| 
      
 26 
     | 
    
         
            +
                      @dirty = true
         
     | 
| 
      
 27 
     | 
    
         
            +
                      v = yield
         
     | 
| 
      
 28 
     | 
    
         
            +
                      @data[key] = v
         
     | 
| 
      
 29 
     | 
    
         
            +
                    end
         
     | 
| 
      
 30 
     | 
    
         
            +
                    v
         
     | 
| 
      
 31 
     | 
    
         
            +
                  end
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
                  def set(key, value)
         
     | 
| 
      
 34 
     | 
    
         
            +
                    raise SetOutsideTransactionNotAllowed unless @in_txn
         
     | 
| 
      
 35 
     | 
    
         
            +
                    if value != @data[key]
         
     | 
| 
      
 36 
     | 
    
         
            +
                      @dirty = true
         
     | 
| 
      
 37 
     | 
    
         
            +
                      @data[key] = value
         
     | 
| 
      
 38 
     | 
    
         
            +
                    end
         
     | 
| 
      
 39 
     | 
    
         
            +
                  end
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
                  def transaction
         
     | 
| 
      
 42 
     | 
    
         
            +
                    raise NestedTransactionError if @in_txn
         
     | 
| 
      
 43 
     | 
    
         
            +
                    @in_txn = true
         
     | 
| 
      
 44 
     | 
    
         
            +
                    yield
         
     | 
| 
      
 45 
     | 
    
         
            +
                  ensure
         
     | 
| 
      
 46 
     | 
    
         
            +
                    commit_transaction
         
     | 
| 
      
 47 
     | 
    
         
            +
                    @in_txn = false
         
     | 
| 
      
 48 
     | 
    
         
            +
                  end
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
                  private
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
                  def commit_transaction
         
     | 
| 
      
 53 
     | 
    
         
            +
                    if @dirty
         
     | 
| 
      
 54 
     | 
    
         
            +
                      dump_data
         
     | 
| 
      
 55 
     | 
    
         
            +
                      @dirty = false
         
     | 
| 
      
 56 
     | 
    
         
            +
                    end
         
     | 
| 
      
 57 
     | 
    
         
            +
                  end
         
     | 
| 
      
 58 
     | 
    
         
            +
             
     | 
| 
      
 59 
     | 
    
         
            +
                  def load_data
         
     | 
| 
      
 60 
     | 
    
         
            +
                    @data = begin
         
     | 
| 
      
 61 
     | 
    
         
            +
                      MessagePack.load(Snappy.inflate(File.binread(@store_path)))
         
     | 
| 
      
 62 
     | 
    
         
            +
                    rescue Errno::ENOENT, Snappy::Error
         
     | 
| 
      
 63 
     | 
    
         
            +
                      {}
         
     | 
| 
      
 64 
     | 
    
         
            +
                    end
         
     | 
| 
      
 65 
     | 
    
         
            +
                  end
         
     | 
| 
      
 66 
     | 
    
         
            +
             
     | 
| 
      
 67 
     | 
    
         
            +
                  def dump_data
         
     | 
| 
      
 68 
     | 
    
         
            +
                    # Change contents atomically so other processes can't get invalid
         
     | 
| 
      
 69 
     | 
    
         
            +
                    # caches if they read at an inopportune time.
         
     | 
| 
      
 70 
     | 
    
         
            +
                    tmp = "#{@store_path}.#{(rand * 100000).to_i}.tmp"
         
     | 
| 
      
 71 
     | 
    
         
            +
                    FileUtils.mkpath(File.dirname(tmp))
         
     | 
| 
      
 72 
     | 
    
         
            +
                    File.binwrite(tmp, Snappy.deflate(MessagePack.dump(@data)))
         
     | 
| 
      
 73 
     | 
    
         
            +
                    FileUtils.mv(tmp, @store_path)
         
     | 
| 
      
 74 
     | 
    
         
            +
                  end
         
     | 
| 
      
 75 
     | 
    
         
            +
                end
         
     | 
| 
      
 76 
     | 
    
         
            +
              end
         
     | 
| 
      
 77 
     | 
    
         
            +
            end
         
     | 
    
        metadata
    ADDED
    
    | 
         @@ -0,0 +1,172 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            --- !ruby/object:Gem::Specification
         
     | 
| 
      
 2 
     | 
    
         
            +
            name: bootsnap
         
     | 
| 
      
 3 
     | 
    
         
            +
            version: !ruby/object:Gem::Version
         
     | 
| 
      
 4 
     | 
    
         
            +
              version: 0.2.0
         
     | 
| 
      
 5 
     | 
    
         
            +
            platform: ruby
         
     | 
| 
      
 6 
     | 
    
         
            +
            authors:
         
     | 
| 
      
 7 
     | 
    
         
            +
            - Burke Libbey
         
     | 
| 
      
 8 
     | 
    
         
            +
            autorequire: 
         
     | 
| 
      
 9 
     | 
    
         
            +
            bindir: exe
         
     | 
| 
      
 10 
     | 
    
         
            +
            cert_chain: []
         
     | 
| 
      
 11 
     | 
    
         
            +
            date: 2017-03-31 00:00:00.000000000 Z
         
     | 
| 
      
 12 
     | 
    
         
            +
            dependencies:
         
     | 
| 
      
 13 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 14 
     | 
    
         
            +
              name: bundler
         
     | 
| 
      
 15 
     | 
    
         
            +
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
      
 16 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 17 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 18 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 19 
     | 
    
         
            +
                    version: '0'
         
     | 
| 
      
 20 
     | 
    
         
            +
              type: :development
         
     | 
| 
      
 21 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 22 
     | 
    
         
            +
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
      
 23 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 24 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 25 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 26 
     | 
    
         
            +
                    version: '0'
         
     | 
| 
      
 27 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 28 
     | 
    
         
            +
              name: rake
         
     | 
| 
      
 29 
     | 
    
         
            +
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
      
 30 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 31 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 32 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 33 
     | 
    
         
            +
                    version: '10.0'
         
     | 
| 
      
 34 
     | 
    
         
            +
              type: :development
         
     | 
| 
      
 35 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 36 
     | 
    
         
            +
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
      
 37 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 38 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 39 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 40 
     | 
    
         
            +
                    version: '10.0'
         
     | 
| 
      
 41 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 42 
     | 
    
         
            +
              name: rake-compiler
         
     | 
| 
      
 43 
     | 
    
         
            +
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
      
 44 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 45 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 46 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 47 
     | 
    
         
            +
                    version: '0'
         
     | 
| 
      
 48 
     | 
    
         
            +
              type: :development
         
     | 
| 
      
 49 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 50 
     | 
    
         
            +
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
      
 51 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 52 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 53 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 54 
     | 
    
         
            +
                    version: '0'
         
     | 
| 
      
 55 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 56 
     | 
    
         
            +
              name: minitest
         
     | 
| 
      
 57 
     | 
    
         
            +
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
      
 58 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 59 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 60 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 61 
     | 
    
         
            +
                    version: '5.0'
         
     | 
| 
      
 62 
     | 
    
         
            +
              type: :development
         
     | 
| 
      
 63 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 64 
     | 
    
         
            +
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
      
 65 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 66 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 67 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 68 
     | 
    
         
            +
                    version: '5.0'
         
     | 
| 
      
 69 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 70 
     | 
    
         
            +
              name: mocha
         
     | 
| 
      
 71 
     | 
    
         
            +
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
      
 72 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 73 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 74 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 75 
     | 
    
         
            +
                    version: '1.2'
         
     | 
| 
      
 76 
     | 
    
         
            +
              type: :development
         
     | 
| 
      
 77 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 78 
     | 
    
         
            +
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
      
 79 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 80 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 81 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 82 
     | 
    
         
            +
                    version: '1.2'
         
     | 
| 
      
 83 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 84 
     | 
    
         
            +
              name: msgpack
         
     | 
| 
      
 85 
     | 
    
         
            +
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
      
 86 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 87 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 88 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 89 
     | 
    
         
            +
                    version: '1.0'
         
     | 
| 
      
 90 
     | 
    
         
            +
              type: :runtime
         
     | 
| 
      
 91 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 92 
     | 
    
         
            +
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
      
 93 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 94 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 95 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 96 
     | 
    
         
            +
                    version: '1.0'
         
     | 
| 
      
 97 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 98 
     | 
    
         
            +
              name: snappy
         
     | 
| 
      
 99 
     | 
    
         
            +
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
      
 100 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 101 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 102 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 103 
     | 
    
         
            +
                    version: 0.0.15
         
     | 
| 
      
 104 
     | 
    
         
            +
              type: :runtime
         
     | 
| 
      
 105 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 106 
     | 
    
         
            +
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
      
 107 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 108 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 109 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 110 
     | 
    
         
            +
                    version: 0.0.15
         
     | 
| 
      
 111 
     | 
    
         
            +
            description: wip.
         
     | 
| 
      
 112 
     | 
    
         
            +
            email:
         
     | 
| 
      
 113 
     | 
    
         
            +
            - burke.libbey@shopify.com
         
     | 
| 
      
 114 
     | 
    
         
            +
            executables: []
         
     | 
| 
      
 115 
     | 
    
         
            +
            extensions:
         
     | 
| 
      
 116 
     | 
    
         
            +
            - ext/bootsnap/extconf.rb
         
     | 
| 
      
 117 
     | 
    
         
            +
            extra_rdoc_files: []
         
     | 
| 
      
 118 
     | 
    
         
            +
            files:
         
     | 
| 
      
 119 
     | 
    
         
            +
            - ".gitignore"
         
     | 
| 
      
 120 
     | 
    
         
            +
            - ".rubocop.yml"
         
     | 
| 
      
 121 
     | 
    
         
            +
            - CONTRIBUTING.md
         
     | 
| 
      
 122 
     | 
    
         
            +
            - Gemfile
         
     | 
| 
      
 123 
     | 
    
         
            +
            - README.md
         
     | 
| 
      
 124 
     | 
    
         
            +
            - Rakefile
         
     | 
| 
      
 125 
     | 
    
         
            +
            - bin/console
         
     | 
| 
      
 126 
     | 
    
         
            +
            - bin/setup
         
     | 
| 
      
 127 
     | 
    
         
            +
            - bin/testunit
         
     | 
| 
      
 128 
     | 
    
         
            +
            - bootsnap.gemspec
         
     | 
| 
      
 129 
     | 
    
         
            +
            - dev.yml
         
     | 
| 
      
 130 
     | 
    
         
            +
            - ext/bootsnap/bootsnap.c
         
     | 
| 
      
 131 
     | 
    
         
            +
            - ext/bootsnap/bootsnap.h
         
     | 
| 
      
 132 
     | 
    
         
            +
            - ext/bootsnap/crc32.c
         
     | 
| 
      
 133 
     | 
    
         
            +
            - ext/bootsnap/extconf.rb
         
     | 
| 
      
 134 
     | 
    
         
            +
            - lib/bootsnap.rb
         
     | 
| 
      
 135 
     | 
    
         
            +
            - lib/bootsnap/compile_cache.rb
         
     | 
| 
      
 136 
     | 
    
         
            +
            - lib/bootsnap/compile_cache/iseq.rb
         
     | 
| 
      
 137 
     | 
    
         
            +
            - lib/bootsnap/compile_cache/yaml.rb
         
     | 
| 
      
 138 
     | 
    
         
            +
            - lib/bootsnap/explicit_require.rb
         
     | 
| 
      
 139 
     | 
    
         
            +
            - lib/bootsnap/load_path_cache.rb
         
     | 
| 
      
 140 
     | 
    
         
            +
            - lib/bootsnap/load_path_cache/cache.rb
         
     | 
| 
      
 141 
     | 
    
         
            +
            - lib/bootsnap/load_path_cache/change_observer.rb
         
     | 
| 
      
 142 
     | 
    
         
            +
            - lib/bootsnap/load_path_cache/core_ext/active_support.rb
         
     | 
| 
      
 143 
     | 
    
         
            +
            - lib/bootsnap/load_path_cache/core_ext/kernel_require.rb
         
     | 
| 
      
 144 
     | 
    
         
            +
            - lib/bootsnap/load_path_cache/path.rb
         
     | 
| 
      
 145 
     | 
    
         
            +
            - lib/bootsnap/load_path_cache/path_scanner.rb
         
     | 
| 
      
 146 
     | 
    
         
            +
            - lib/bootsnap/load_path_cache/store.rb
         
     | 
| 
      
 147 
     | 
    
         
            +
            - lib/bootsnap/version.rb
         
     | 
| 
      
 148 
     | 
    
         
            +
            homepage: https://github.com/Shopify/bootsnap
         
     | 
| 
      
 149 
     | 
    
         
            +
            licenses:
         
     | 
| 
      
 150 
     | 
    
         
            +
            - MIT
         
     | 
| 
      
 151 
     | 
    
         
            +
            metadata: {}
         
     | 
| 
      
 152 
     | 
    
         
            +
            post_install_message: 
         
     | 
| 
      
 153 
     | 
    
         
            +
            rdoc_options: []
         
     | 
| 
      
 154 
     | 
    
         
            +
            require_paths:
         
     | 
| 
      
 155 
     | 
    
         
            +
            - lib
         
     | 
| 
      
 156 
     | 
    
         
            +
            required_ruby_version: !ruby/object:Gem::Requirement
         
     | 
| 
      
 157 
     | 
    
         
            +
              requirements:
         
     | 
| 
      
 158 
     | 
    
         
            +
              - - ">="
         
     | 
| 
      
 159 
     | 
    
         
            +
                - !ruby/object:Gem::Version
         
     | 
| 
      
 160 
     | 
    
         
            +
                  version: '0'
         
     | 
| 
      
 161 
     | 
    
         
            +
            required_rubygems_version: !ruby/object:Gem::Requirement
         
     | 
| 
      
 162 
     | 
    
         
            +
              requirements:
         
     | 
| 
      
 163 
     | 
    
         
            +
              - - ">="
         
     | 
| 
      
 164 
     | 
    
         
            +
                - !ruby/object:Gem::Version
         
     | 
| 
      
 165 
     | 
    
         
            +
                  version: '0'
         
     | 
| 
      
 166 
     | 
    
         
            +
            requirements: []
         
     | 
| 
      
 167 
     | 
    
         
            +
            rubyforge_project: 
         
     | 
| 
      
 168 
     | 
    
         
            +
            rubygems_version: 2.6.10
         
     | 
| 
      
 169 
     | 
    
         
            +
            signing_key: 
         
     | 
| 
      
 170 
     | 
    
         
            +
            specification_version: 4
         
     | 
| 
      
 171 
     | 
    
         
            +
            summary: wip
         
     | 
| 
      
 172 
     | 
    
         
            +
            test_files: []
         
     |