bootsnap 1.6.0 → 1.15.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 +4 -4
 - data/CHANGELOG.md +174 -0
 - data/LICENSE.txt +1 -1
 - data/README.md +41 -18
 - data/exe/bootsnap +1 -1
 - data/ext/bootsnap/bootsnap.c +133 -105
 - data/ext/bootsnap/extconf.rb +21 -14
 - data/lib/bootsnap/bundler.rb +1 -0
 - data/lib/bootsnap/cli/worker_pool.rb +6 -1
 - data/lib/bootsnap/cli.rb +84 -49
 - data/lib/bootsnap/compile_cache/iseq.rb +43 -13
 - data/lib/bootsnap/compile_cache/json.rb +93 -0
 - data/lib/bootsnap/compile_cache/yaml.rb +299 -61
 - data/lib/bootsnap/compile_cache.rb +24 -7
 - data/lib/bootsnap/explicit_require.rb +4 -3
 - data/lib/bootsnap/load_path_cache/cache.rb +63 -35
 - data/lib/bootsnap/load_path_cache/change_observer.rb +17 -2
 - data/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb +27 -95
 - data/lib/bootsnap/load_path_cache/core_ext/loaded_features.rb +1 -0
 - data/lib/bootsnap/load_path_cache/loaded_features_index.rb +36 -25
 - data/lib/bootsnap/load_path_cache/path.rb +39 -17
 - data/lib/bootsnap/load_path_cache/path_scanner.rb +25 -7
 - data/lib/bootsnap/load_path_cache/store.rb +64 -24
 - data/lib/bootsnap/load_path_cache.rb +31 -38
 - data/lib/bootsnap/setup.rb +2 -36
 - data/lib/bootsnap/version.rb +2 -1
 - data/lib/bootsnap.rb +125 -36
 - metadata +8 -79
 - data/lib/bootsnap/load_path_cache/core_ext/active_support.rb +0 -107
 - data/lib/bootsnap/load_path_cache/realpath_cache.rb +0 -32
 
| 
         @@ -1,21 +1,25 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            # frozen_string_literal: true
         
     | 
| 
       2 
2 
     | 
    
         | 
| 
       3 
     | 
    
         
            -
            require_relative( 
     | 
| 
      
 3 
     | 
    
         
            +
            require_relative("../explicit_require")
         
     | 
| 
       4 
4 
     | 
    
         | 
| 
       5 
5 
     | 
    
         
             
            module Bootsnap
         
     | 
| 
       6 
6 
     | 
    
         
             
              module LoadPathCache
         
     | 
| 
       7 
7 
     | 
    
         
             
                module PathScanner
         
     | 
| 
       8 
8 
     | 
    
         
             
                  REQUIRABLE_EXTENSIONS = [DOT_RB] + DL_EXTENSIONS
         
     | 
| 
       9 
9 
     | 
    
         
             
                  NORMALIZE_NATIVE_EXTENSIONS = !DL_EXTENSIONS.include?(LoadPathCache::DOT_SO)
         
     | 
| 
       10 
     | 
    
         
            -
                  ALTERNATIVE_NATIVE_EXTENSIONS_PATTERN = /\.(o|bundle|dylib)\z 
     | 
| 
      
 10 
     | 
    
         
            +
                  ALTERNATIVE_NATIVE_EXTENSIONS_PATTERN = /\.(o|bundle|dylib)\z/.freeze
         
     | 
| 
       11 
11 
     | 
    
         | 
| 
       12 
12 
     | 
    
         
             
                  BUNDLE_PATH = if Bootsnap.bundler?
         
     | 
| 
       13 
13 
     | 
    
         
             
                    (Bundler.bundle_path.cleanpath.to_s << LoadPathCache::SLASH).freeze
         
     | 
| 
       14 
14 
     | 
    
         
             
                  else
         
     | 
| 
       15 
     | 
    
         
            -
                     
     | 
| 
      
 15 
     | 
    
         
            +
                    ""
         
     | 
| 
       16 
16 
     | 
    
         
             
                  end
         
     | 
| 
       17 
17 
     | 
    
         | 
| 
      
 18 
     | 
    
         
            +
                  @ignored_directories = %w(node_modules)
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
       18 
20 
     | 
    
         
             
                  class << self
         
     | 
| 
      
 21 
     | 
    
         
            +
                    attr_accessor :ignored_directories
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
       19 
23 
     | 
    
         
             
                    def call(path)
         
     | 
| 
       20 
24 
     | 
    
         
             
                      path = File.expand_path(path.to_s).freeze
         
     | 
| 
       21 
25 
     | 
    
         
             
                      return [[], []] unless File.directory?(path)
         
     | 
| 
         @@ -33,10 +37,10 @@ module Bootsnap 
     | 
|
| 
       33 
37 
     | 
    
         
             
                      requirables = []
         
     | 
| 
       34 
38 
     | 
    
         
             
                      walk(path, nil) do |relative_path, absolute_path, is_directory|
         
     | 
| 
       35 
39 
     | 
    
         
             
                        if is_directory
         
     | 
| 
       36 
     | 
    
         
            -
                          dirs << relative_path
         
     | 
| 
      
 40 
     | 
    
         
            +
                          dirs << os_path(relative_path)
         
     | 
| 
       37 
41 
     | 
    
         
             
                          !contains_bundle_path || !absolute_path.start_with?(BUNDLE_PATH)
         
     | 
| 
       38 
42 
     | 
    
         
             
                        elsif relative_path.end_with?(*REQUIRABLE_EXTENSIONS)
         
     | 
| 
       39 
     | 
    
         
            -
                          requirables << relative_path
         
     | 
| 
      
 43 
     | 
    
         
            +
                          requirables << os_path(relative_path)
         
     | 
| 
       40 
44 
     | 
    
         
             
                        end
         
     | 
| 
       41 
45 
     | 
    
         
             
                      end
         
     | 
| 
       42 
46 
     | 
    
         
             
                      [requirables, dirs]
         
     | 
| 
         @@ -44,11 +48,14 @@ module Bootsnap 
     | 
|
| 
       44 
48 
     | 
    
         | 
| 
       45 
49 
     | 
    
         
             
                    def walk(absolute_dir_path, relative_dir_path, &block)
         
     | 
| 
       46 
50 
     | 
    
         
             
                      Dir.foreach(absolute_dir_path) do |name|
         
     | 
| 
       47 
     | 
    
         
            -
                        next if name.start_with?( 
     | 
| 
       48 
     | 
    
         
            -
             
     | 
| 
      
 51 
     | 
    
         
            +
                        next if name.start_with?(".")
         
     | 
| 
      
 52 
     | 
    
         
            +
             
     | 
| 
      
 53 
     | 
    
         
            +
                        relative_path = relative_dir_path ? File.join(relative_dir_path, name) : name
         
     | 
| 
       49 
54 
     | 
    
         | 
| 
       50 
55 
     | 
    
         
             
                        absolute_path = "#{absolute_dir_path}/#{name}"
         
     | 
| 
       51 
56 
     | 
    
         
             
                        if File.directory?(absolute_path)
         
     | 
| 
      
 57 
     | 
    
         
            +
                          next if ignored_directories.include?(name)
         
     | 
| 
      
 58 
     | 
    
         
            +
             
     | 
| 
       52 
59 
     | 
    
         
             
                          if yield relative_path, absolute_path, true
         
     | 
| 
       53 
60 
     | 
    
         
             
                            walk(absolute_path, relative_path, &block)
         
     | 
| 
       54 
61 
     | 
    
         
             
                          end
         
     | 
| 
         @@ -57,6 +64,17 @@ module Bootsnap 
     | 
|
| 
       57 
64 
     | 
    
         
             
                        end
         
     | 
| 
       58 
65 
     | 
    
         
             
                      end
         
     | 
| 
       59 
66 
     | 
    
         
             
                    end
         
     | 
| 
      
 67 
     | 
    
         
            +
             
     | 
| 
      
 68 
     | 
    
         
            +
                    if RUBY_VERSION >= "3.1"
         
     | 
| 
      
 69 
     | 
    
         
            +
                      def os_path(path)
         
     | 
| 
      
 70 
     | 
    
         
            +
                        path.freeze
         
     | 
| 
      
 71 
     | 
    
         
            +
                      end
         
     | 
| 
      
 72 
     | 
    
         
            +
                    else
         
     | 
| 
      
 73 
     | 
    
         
            +
                      def os_path(path)
         
     | 
| 
      
 74 
     | 
    
         
            +
                        path.force_encoding(Encoding::US_ASCII) if path.ascii_only?
         
     | 
| 
      
 75 
     | 
    
         
            +
                        path.freeze
         
     | 
| 
      
 76 
     | 
    
         
            +
                      end
         
     | 
| 
      
 77 
     | 
    
         
            +
                    end
         
     | 
| 
       60 
78 
     | 
    
         
             
                  end
         
     | 
| 
       61 
79 
     | 
    
         
             
                end
         
     | 
| 
       62 
80 
     | 
    
         
             
              end
         
     | 
| 
         @@ -1,20 +1,23 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            # frozen_string_literal: true
         
     | 
| 
       2 
     | 
    
         
            -
            require_relative('../explicit_require')
         
     | 
| 
       3 
2 
     | 
    
         | 
| 
       4 
     | 
    
         
            -
             
     | 
| 
       5 
     | 
    
         
            -
             
     | 
| 
      
 3 
     | 
    
         
            +
            require_relative("../explicit_require")
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            Bootsnap::ExplicitRequire.with_gems("msgpack") { require("msgpack") }
         
     | 
| 
       6 
6 
     | 
    
         | 
| 
       7 
7 
     | 
    
         
             
            module Bootsnap
         
     | 
| 
       8 
8 
     | 
    
         
             
              module LoadPathCache
         
     | 
| 
       9 
9 
     | 
    
         
             
                class Store
         
     | 
| 
      
 10 
     | 
    
         
            +
                  VERSION_KEY = "__bootsnap_ruby_version__"
         
     | 
| 
      
 11 
     | 
    
         
            +
                  CURRENT_VERSION = "#{RUBY_REVISION}-#{RUBY_PLATFORM}".freeze # rubocop:disable Style/RedundantFreeze
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
       10 
13 
     | 
    
         
             
                  NestedTransactionError = Class.new(StandardError)
         
     | 
| 
       11 
14 
     | 
    
         
             
                  SetOutsideTransactionNotAllowed = Class.new(StandardError)
         
     | 
| 
       12 
15 
     | 
    
         | 
| 
       13 
     | 
    
         
            -
                  def initialize(store_path)
         
     | 
| 
      
 16 
     | 
    
         
            +
                  def initialize(store_path, readonly: false)
         
     | 
| 
       14 
17 
     | 
    
         
             
                    @store_path = store_path
         
     | 
| 
       15 
     | 
    
         
            -
                     
     | 
| 
       16 
     | 
    
         
            -
                    @txn_mutex =  defined?(::Mutex) ? ::Mutex.new : ::Thread::Mutex.new
         
     | 
| 
      
 18 
     | 
    
         
            +
                    @txn_mutex = Mutex.new
         
     | 
| 
       17 
19 
     | 
    
         
             
                    @dirty = false
         
     | 
| 
      
 20 
     | 
    
         
            +
                    @readonly = readonly
         
     | 
| 
       18 
21 
     | 
    
         
             
                    load_data
         
     | 
| 
       19 
22 
     | 
    
         
             
                  end
         
     | 
| 
       20 
23 
     | 
    
         | 
| 
         @@ -24,10 +27,11 @@ module Bootsnap 
     | 
|
| 
       24 
27 
     | 
    
         | 
| 
       25 
28 
     | 
    
         
             
                  def fetch(key)
         
     | 
| 
       26 
29 
     | 
    
         
             
                    raise(SetOutsideTransactionNotAllowed) unless @txn_mutex.owned?
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
       27 
31 
     | 
    
         
             
                    v = get(key)
         
     | 
| 
       28 
32 
     | 
    
         
             
                    unless v
         
     | 
| 
       29 
     | 
    
         
            -
                      @dirty = true
         
     | 
| 
       30 
33 
     | 
    
         
             
                      v = yield
         
     | 
| 
      
 34 
     | 
    
         
            +
                      mark_for_mutation!
         
     | 
| 
       31 
35 
     | 
    
         
             
                      @data[key] = v
         
     | 
| 
       32 
36 
     | 
    
         
             
                    end
         
     | 
| 
       33 
37 
     | 
    
         
             
                    v
         
     | 
| 
         @@ -35,27 +39,32 @@ module Bootsnap 
     | 
|
| 
       35 
39 
     | 
    
         | 
| 
       36 
40 
     | 
    
         
             
                  def set(key, value)
         
     | 
| 
       37 
41 
     | 
    
         
             
                    raise(SetOutsideTransactionNotAllowed) unless @txn_mutex.owned?
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
       38 
43 
     | 
    
         
             
                    if value != @data[key]
         
     | 
| 
       39 
     | 
    
         
            -
                       
     | 
| 
      
 44 
     | 
    
         
            +
                      mark_for_mutation!
         
     | 
| 
       40 
45 
     | 
    
         
             
                      @data[key] = value
         
     | 
| 
       41 
46 
     | 
    
         
             
                    end
         
     | 
| 
       42 
47 
     | 
    
         
             
                  end
         
     | 
| 
       43 
48 
     | 
    
         | 
| 
       44 
49 
     | 
    
         
             
                  def transaction
         
     | 
| 
       45 
50 
     | 
    
         
             
                    raise(NestedTransactionError) if @txn_mutex.owned?
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
       46 
52 
     | 
    
         
             
                    @txn_mutex.synchronize do
         
     | 
| 
       47 
     | 
    
         
            -
                       
     | 
| 
       48 
     | 
    
         
            -
             
     | 
| 
       49 
     | 
    
         
            -
                       
     | 
| 
       50 
     | 
    
         
            -
                        commit_transaction
         
     | 
| 
       51 
     | 
    
         
            -
                      end
         
     | 
| 
      
 53 
     | 
    
         
            +
                      yield
         
     | 
| 
      
 54 
     | 
    
         
            +
                    ensure
         
     | 
| 
      
 55 
     | 
    
         
            +
                      commit_transaction
         
     | 
| 
       52 
56 
     | 
    
         
             
                    end
         
     | 
| 
       53 
57 
     | 
    
         
             
                  end
         
     | 
| 
       54 
58 
     | 
    
         | 
| 
       55 
59 
     | 
    
         
             
                  private
         
     | 
| 
       56 
60 
     | 
    
         | 
| 
      
 61 
     | 
    
         
            +
                  def mark_for_mutation!
         
     | 
| 
      
 62 
     | 
    
         
            +
                    @dirty = true
         
     | 
| 
      
 63 
     | 
    
         
            +
                    @data = @data.dup if @data.frozen?
         
     | 
| 
      
 64 
     | 
    
         
            +
                  end
         
     | 
| 
      
 65 
     | 
    
         
            +
             
     | 
| 
       57 
66 
     | 
    
         
             
                  def commit_transaction
         
     | 
| 
       58 
     | 
    
         
            -
                    if @dirty
         
     | 
| 
      
 67 
     | 
    
         
            +
                    if @dirty && !@readonly
         
     | 
| 
       59 
68 
     | 
    
         
             
                      dump_data
         
     | 
| 
       60 
69 
     | 
    
         
             
                      @dirty = false
         
     | 
| 
       61 
70 
     | 
    
         
             
                    end
         
     | 
| 
         @@ -63,27 +72,58 @@ module Bootsnap 
     | 
|
| 
       63 
72 
     | 
    
         | 
| 
       64 
73 
     | 
    
         
             
                  def load_data
         
     | 
| 
       65 
74 
     | 
    
         
             
                    @data = begin
         
     | 
| 
       66 
     | 
    
         
            -
                       
     | 
| 
       67 
     | 
    
         
            -
             
     | 
| 
       68 
     | 
    
         
            -
             
     | 
| 
       69 
     | 
    
         
            -
             
     | 
| 
       70 
     | 
    
         
            -
             
     | 
| 
       71 
     | 
    
         
            -
             
     | 
| 
      
 75 
     | 
    
         
            +
                      data = File.open(@store_path, encoding: Encoding::BINARY) do |io|
         
     | 
| 
      
 76 
     | 
    
         
            +
                        MessagePack.load(io, freeze: true)
         
     | 
| 
      
 77 
     | 
    
         
            +
                      end
         
     | 
| 
      
 78 
     | 
    
         
            +
                      if data.is_a?(Hash) && data[VERSION_KEY] == CURRENT_VERSION
         
     | 
| 
      
 79 
     | 
    
         
            +
                        data
         
     | 
| 
      
 80 
     | 
    
         
            +
                      else
         
     | 
| 
      
 81 
     | 
    
         
            +
                        default_data
         
     | 
| 
      
 82 
     | 
    
         
            +
                      end
         
     | 
| 
      
 83 
     | 
    
         
            +
                    # handle malformed data due to upgrade incompatibility
         
     | 
| 
      
 84 
     | 
    
         
            +
                    rescue Errno::ENOENT, MessagePack::MalformedFormatError, MessagePack::UnknownExtTypeError, EOFError
         
     | 
| 
      
 85 
     | 
    
         
            +
                      default_data
         
     | 
| 
      
 86 
     | 
    
         
            +
                    rescue ArgumentError => error
         
     | 
| 
      
 87 
     | 
    
         
            +
                      if error.message =~ /negative array size/
         
     | 
| 
      
 88 
     | 
    
         
            +
                        default_data
         
     | 
| 
      
 89 
     | 
    
         
            +
                      else
         
     | 
| 
      
 90 
     | 
    
         
            +
                        raise
         
     | 
| 
      
 91 
     | 
    
         
            +
                      end
         
     | 
| 
       72 
92 
     | 
    
         
             
                    end
         
     | 
| 
       73 
93 
     | 
    
         
             
                  end
         
     | 
| 
       74 
94 
     | 
    
         | 
| 
       75 
95 
     | 
    
         
             
                  def dump_data
         
     | 
| 
       76 
96 
     | 
    
         
             
                    # Change contents atomically so other processes can't get invalid
         
     | 
| 
       77 
97 
     | 
    
         
             
                    # caches if they read at an inopportune time.
         
     | 
| 
       78 
     | 
    
         
            -
                    tmp = "#{@store_path}.#{Process.pid}.#{(rand *  
     | 
| 
       79 
     | 
    
         
            -
                     
     | 
| 
      
 98 
     | 
    
         
            +
                    tmp = "#{@store_path}.#{Process.pid}.#{(rand * 100_000).to_i}.tmp"
         
     | 
| 
      
 99 
     | 
    
         
            +
                    mkdir_p(File.dirname(tmp))
         
     | 
| 
       80 
100 
     | 
    
         
             
                    exclusive_write = File::Constants::CREAT | File::Constants::EXCL | File::Constants::WRONLY
         
     | 
| 
       81 
101 
     | 
    
         
             
                    # `encoding:` looks redundant wrt `binwrite`, but necessary on windows
         
     | 
| 
       82 
102 
     | 
    
         
             
                    # because binary is part of mode.
         
     | 
| 
       83 
     | 
    
         
            -
                    File. 
     | 
| 
       84 
     | 
    
         
            -
             
     | 
| 
      
 103 
     | 
    
         
            +
                    File.open(tmp, mode: exclusive_write, encoding: Encoding::BINARY) do |io|
         
     | 
| 
      
 104 
     | 
    
         
            +
                      MessagePack.dump(@data, io)
         
     | 
| 
      
 105 
     | 
    
         
            +
                    end
         
     | 
| 
      
 106 
     | 
    
         
            +
                    File.rename(tmp, @store_path)
         
     | 
| 
       85 
107 
     | 
    
         
             
                  rescue Errno::EEXIST
         
     | 
| 
       86 
108 
     | 
    
         
             
                    retry
         
     | 
| 
      
 109 
     | 
    
         
            +
                  rescue SystemCallError
         
     | 
| 
      
 110 
     | 
    
         
            +
                  end
         
     | 
| 
      
 111 
     | 
    
         
            +
             
     | 
| 
      
 112 
     | 
    
         
            +
                  def default_data
         
     | 
| 
      
 113 
     | 
    
         
            +
                    {VERSION_KEY => CURRENT_VERSION}
         
     | 
| 
      
 114 
     | 
    
         
            +
                  end
         
     | 
| 
      
 115 
     | 
    
         
            +
             
     | 
| 
      
 116 
     | 
    
         
            +
                  def mkdir_p(path)
         
     | 
| 
      
 117 
     | 
    
         
            +
                    stack = []
         
     | 
| 
      
 118 
     | 
    
         
            +
                    until File.directory?(path)
         
     | 
| 
      
 119 
     | 
    
         
            +
                      stack.push path
         
     | 
| 
      
 120 
     | 
    
         
            +
                      path = File.dirname(path)
         
     | 
| 
      
 121 
     | 
    
         
            +
                    end
         
     | 
| 
      
 122 
     | 
    
         
            +
                    stack.reverse_each do |dir|
         
     | 
| 
      
 123 
     | 
    
         
            +
                      Dir.mkdir(dir)
         
     | 
| 
      
 124 
     | 
    
         
            +
                    rescue SystemCallError
         
     | 
| 
      
 125 
     | 
    
         
            +
                      raise unless File.directory?(dir)
         
     | 
| 
      
 126 
     | 
    
         
            +
                    end
         
     | 
| 
       87 
127 
     | 
    
         
             
                  end
         
     | 
| 
       88 
128 
     | 
    
         
             
                end
         
     | 
| 
       89 
129 
     | 
    
         
             
              end
         
     | 
| 
         @@ -2,20 +2,14 @@ 
     | 
|
| 
       2 
2 
     | 
    
         | 
| 
       3 
3 
     | 
    
         
             
            module Bootsnap
         
     | 
| 
       4 
4 
     | 
    
         
             
              module LoadPathCache
         
     | 
| 
       5 
     | 
    
         
            -
                 
     | 
| 
       6 
     | 
    
         
            -
                FallbackScan = Class.new(StandardError)
         
     | 
| 
      
 5 
     | 
    
         
            +
                FALLBACK_SCAN = BasicObject.new
         
     | 
| 
       7 
6 
     | 
    
         | 
| 
       8 
     | 
    
         
            -
                DOT_RB =  
     | 
| 
       9 
     | 
    
         
            -
                DOT_SO =  
     | 
| 
       10 
     | 
    
         
            -
                SLASH  =  
     | 
| 
       11 
     | 
    
         
            -
             
     | 
| 
       12 
     | 
    
         
            -
                # If a NameError happens several levels deep, don't re-handle it
         
     | 
| 
       13 
     | 
    
         
            -
                # all the way up the chain: mark it once and bubble it up without
         
     | 
| 
       14 
     | 
    
         
            -
                # more retries.
         
     | 
| 
       15 
     | 
    
         
            -
                ERROR_TAG_IVAR = :@__bootsnap_rescued
         
     | 
| 
      
 7 
     | 
    
         
            +
                DOT_RB = ".rb"
         
     | 
| 
      
 8 
     | 
    
         
            +
                DOT_SO = ".so"
         
     | 
| 
      
 9 
     | 
    
         
            +
                SLASH  = "/"
         
     | 
| 
       16 
10 
     | 
    
         | 
| 
       17 
11 
     | 
    
         
             
                DL_EXTENSIONS = ::RbConfig::CONFIG
         
     | 
| 
       18 
     | 
    
         
            -
                  .values_at( 
     | 
| 
      
 12 
     | 
    
         
            +
                  .values_at("DLEXT", "DLEXT2")
         
     | 
| 
       19 
13 
     | 
    
         
             
                  .reject { |ext| !ext || ext.empty? }
         
     | 
| 
       20 
14 
     | 
    
         
             
                  .map    { |ext| ".#{ext}" }
         
     | 
| 
       21 
15 
     | 
    
         
             
                  .freeze
         
     | 
| 
         @@ -27,52 +21,51 @@ module Bootsnap 
     | 
|
| 
       27 
21 
     | 
    
         | 
| 
       28 
22 
     | 
    
         
             
                CACHED_EXTENSIONS = DLEXT2 ? [DOT_RB, DLEXT, DLEXT2] : [DOT_RB, DLEXT]
         
     | 
| 
       29 
23 
     | 
    
         | 
| 
      
 24 
     | 
    
         
            +
                @enabled = false
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
       30 
26 
     | 
    
         
             
                class << self
         
     | 
| 
       31 
     | 
    
         
            -
                  attr_reader(:load_path_cache, : 
     | 
| 
       32 
     | 
    
         
            -
             
     | 
| 
      
 27 
     | 
    
         
            +
                  attr_reader(:load_path_cache, :loaded_features_index, :enabled)
         
     | 
| 
      
 28 
     | 
    
         
            +
                  alias_method :enabled?, :enabled
         
     | 
| 
      
 29 
     | 
    
         
            +
                  remove_method(:enabled)
         
     | 
| 
       33 
30 
     | 
    
         | 
| 
       34 
     | 
    
         
            -
                  def setup(cache_path:, development_mode:,  
     | 
| 
      
 31 
     | 
    
         
            +
                  def setup(cache_path:, development_mode:, ignore_directories:, readonly: false)
         
     | 
| 
       35 
32 
     | 
    
         
             
                    unless supported?
         
     | 
| 
       36 
33 
     | 
    
         
             
                      warn("[bootsnap/setup] Load path caching is not supported on this implementation of Ruby") if $VERBOSE
         
     | 
| 
       37 
34 
     | 
    
         
             
                      return
         
     | 
| 
       38 
35 
     | 
    
         
             
                    end
         
     | 
| 
       39 
36 
     | 
    
         | 
| 
       40 
     | 
    
         
            -
                    store = Store.new(cache_path)
         
     | 
| 
      
 37 
     | 
    
         
            +
                    store = Store.new(cache_path, readonly: readonly)
         
     | 
| 
       41 
38 
     | 
    
         | 
| 
       42 
39 
     | 
    
         
             
                    @loaded_features_index = LoadedFeaturesIndex.new
         
     | 
| 
       43 
     | 
    
         
            -
                    @realpath_cache = RealpathCache.new
         
     | 
| 
       44 
40 
     | 
    
         | 
| 
       45 
41 
     | 
    
         
             
                    @load_path_cache = Cache.new(store, $LOAD_PATH, development_mode: development_mode)
         
     | 
| 
       46 
     | 
    
         
            -
                     
     | 
| 
       47 
     | 
    
         
            -
                     
     | 
| 
      
 42 
     | 
    
         
            +
                    PathScanner.ignored_directories = ignore_directories if ignore_directories
         
     | 
| 
      
 43 
     | 
    
         
            +
                    @enabled = true
         
     | 
| 
      
 44 
     | 
    
         
            +
                    require_relative("load_path_cache/core_ext/kernel_require")
         
     | 
| 
      
 45 
     | 
    
         
            +
                    require_relative("load_path_cache/core_ext/loaded_features")
         
     | 
| 
      
 46 
     | 
    
         
            +
                  end
         
     | 
| 
       48 
47 
     | 
    
         | 
| 
       49 
     | 
    
         
            -
             
     | 
| 
       50 
     | 
    
         
            -
             
     | 
| 
       51 
     | 
    
         
            -
             
     | 
| 
       52 
     | 
    
         
            -
             
     | 
| 
       53 
     | 
    
         
            -
             
     | 
| 
       54 
     | 
    
         
            -
             
     | 
| 
       55 
     | 
    
         
            -
                        ::ActiveSupport::Dependencies.autoload_paths,
         
     | 
| 
       56 
     | 
    
         
            -
                        development_mode: development_mode
         
     | 
| 
       57 
     | 
    
         
            -
                      )
         
     | 
| 
       58 
     | 
    
         
            -
                      require_relative('load_path_cache/core_ext/active_support')
         
     | 
| 
       59 
     | 
    
         
            -
                    end
         
     | 
| 
      
 48 
     | 
    
         
            +
                  def unload!
         
     | 
| 
      
 49 
     | 
    
         
            +
                    @enabled = false
         
     | 
| 
      
 50 
     | 
    
         
            +
                    @loaded_features_index = nil
         
     | 
| 
      
 51 
     | 
    
         
            +
                    @realpath_cache = nil
         
     | 
| 
      
 52 
     | 
    
         
            +
                    @load_path_cache = nil
         
     | 
| 
      
 53 
     | 
    
         
            +
                    ChangeObserver.unregister($LOAD_PATH)
         
     | 
| 
       60 
54 
     | 
    
         
             
                  end
         
     | 
| 
       61 
55 
     | 
    
         | 
| 
       62 
56 
     | 
    
         
             
                  def supported?
         
     | 
| 
       63 
     | 
    
         
            -
                    RUBY_ENGINE ==  
     | 
| 
       64 
     | 
    
         
            -
             
     | 
| 
      
 57 
     | 
    
         
            +
                    RUBY_ENGINE == "ruby" &&
         
     | 
| 
      
 58 
     | 
    
         
            +
                      RUBY_PLATFORM =~ /darwin|linux|bsd|mswin|mingw|cygwin/
         
     | 
| 
       65 
59 
     | 
    
         
             
                  end
         
     | 
| 
       66 
60 
     | 
    
         
             
                end
         
     | 
| 
       67 
61 
     | 
    
         
             
              end
         
     | 
| 
       68 
62 
     | 
    
         
             
            end
         
     | 
| 
       69 
63 
     | 
    
         | 
| 
       70 
64 
     | 
    
         
             
            if Bootsnap::LoadPathCache.supported?
         
     | 
| 
       71 
     | 
    
         
            -
              require_relative( 
     | 
| 
       72 
     | 
    
         
            -
              require_relative( 
     | 
| 
       73 
     | 
    
         
            -
              require_relative( 
     | 
| 
       74 
     | 
    
         
            -
              require_relative( 
     | 
| 
       75 
     | 
    
         
            -
              require_relative( 
     | 
| 
       76 
     | 
    
         
            -
              require_relative( 
     | 
| 
       77 
     | 
    
         
            -
              require_relative('load_path_cache/realpath_cache')
         
     | 
| 
      
 65 
     | 
    
         
            +
              require_relative("load_path_cache/path_scanner")
         
     | 
| 
      
 66 
     | 
    
         
            +
              require_relative("load_path_cache/path")
         
     | 
| 
      
 67 
     | 
    
         
            +
              require_relative("load_path_cache/cache")
         
     | 
| 
      
 68 
     | 
    
         
            +
              require_relative("load_path_cache/store")
         
     | 
| 
      
 69 
     | 
    
         
            +
              require_relative("load_path_cache/change_observer")
         
     | 
| 
      
 70 
     | 
    
         
            +
              require_relative("load_path_cache/loaded_features_index")
         
     | 
| 
       78 
71 
     | 
    
         
             
            end
         
     | 
    
        data/lib/bootsnap/setup.rb
    CHANGED
    
    | 
         @@ -1,39 +1,5 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            # frozen_string_literal: true
         
     | 
| 
       2 
     | 
    
         
            -
            require_relative('../bootsnap')
         
     | 
| 
       3 
2 
     | 
    
         | 
| 
       4 
     | 
    
         
            -
             
     | 
| 
       5 
     | 
    
         
            -
            development_mode = ['', nil, 'development'].include?(env)
         
     | 
| 
      
 3 
     | 
    
         
            +
            require_relative("../bootsnap")
         
     | 
| 
       6 
4 
     | 
    
         | 
| 
       7 
     | 
    
         
            -
             
     | 
| 
       8 
     | 
    
         
            -
            unless cache_dir
         
     | 
| 
       9 
     | 
    
         
            -
              config_dir_frame = caller.detect do |line|
         
     | 
| 
       10 
     | 
    
         
            -
                line.include?('/config/')
         
     | 
| 
       11 
     | 
    
         
            -
              end
         
     | 
| 
       12 
     | 
    
         
            -
             
     | 
| 
       13 
     | 
    
         
            -
              unless config_dir_frame
         
     | 
| 
       14 
     | 
    
         
            -
                $stderr.puts("[bootsnap/setup] couldn't infer cache directory! Either:")
         
     | 
| 
       15 
     | 
    
         
            -
                $stderr.puts("[bootsnap/setup]   1. require bootsnap/setup from your application's config directory; or")
         
     | 
| 
       16 
     | 
    
         
            -
                $stderr.puts("[bootsnap/setup]   2. Define the environment variable BOOTSNAP_CACHE_DIR")
         
     | 
| 
       17 
     | 
    
         
            -
             
     | 
| 
       18 
     | 
    
         
            -
                raise("couldn't infer bootsnap cache directory")
         
     | 
| 
       19 
     | 
    
         
            -
              end
         
     | 
| 
       20 
     | 
    
         
            -
             
     | 
| 
       21 
     | 
    
         
            -
              path = config_dir_frame.split(/:\d+:/).first
         
     | 
| 
       22 
     | 
    
         
            -
              path = File.dirname(path) until File.basename(path) == 'config'
         
     | 
| 
       23 
     | 
    
         
            -
              app_root = File.dirname(path)
         
     | 
| 
       24 
     | 
    
         
            -
             
     | 
| 
       25 
     | 
    
         
            -
              cache_dir = File.join(app_root, 'tmp', 'cache')
         
     | 
| 
       26 
     | 
    
         
            -
            end
         
     | 
| 
       27 
     | 
    
         
            -
             
     | 
| 
       28 
     | 
    
         
            -
            ruby_version = Gem::Version.new(RUBY_VERSION)
         
     | 
| 
       29 
     | 
    
         
            -
            iseq_cache_enabled = ruby_version < Gem::Version.new('2.5.0') || ruby_version >= Gem::Version.new('2.6.0')
         
     | 
| 
       30 
     | 
    
         
            -
             
     | 
| 
       31 
     | 
    
         
            -
            Bootsnap.setup(
         
     | 
| 
       32 
     | 
    
         
            -
              cache_dir:            cache_dir,
         
     | 
| 
       33 
     | 
    
         
            -
              development_mode:     development_mode,
         
     | 
| 
       34 
     | 
    
         
            -
              load_path_cache:      true,
         
     | 
| 
       35 
     | 
    
         
            -
              autoload_paths_cache: true, # assume rails. open to PRs to impl. detection
         
     | 
| 
       36 
     | 
    
         
            -
              disable_trace:        false,
         
     | 
| 
       37 
     | 
    
         
            -
              compile_cache_iseq:   iseq_cache_enabled,
         
     | 
| 
       38 
     | 
    
         
            -
              compile_cache_yaml:   true,
         
     | 
| 
       39 
     | 
    
         
            -
            )
         
     | 
| 
      
 5 
     | 
    
         
            +
            Bootsnap.default_setup
         
     | 
    
        data/lib/bootsnap/version.rb
    CHANGED
    
    
    
        data/lib/bootsnap.rb
    CHANGED
    
    | 
         @@ -1,49 +1,138 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            # frozen_string_literal: true
         
     | 
| 
       2 
2 
     | 
    
         | 
| 
       3 
     | 
    
         
            -
            require_relative( 
     | 
| 
       4 
     | 
    
         
            -
            require_relative( 
     | 
| 
       5 
     | 
    
         
            -
            require_relative( 
     | 
| 
       6 
     | 
    
         
            -
            require_relative( 
     | 
| 
      
 3 
     | 
    
         
            +
            require_relative("bootsnap/version")
         
     | 
| 
      
 4 
     | 
    
         
            +
            require_relative("bootsnap/bundler")
         
     | 
| 
      
 5 
     | 
    
         
            +
            require_relative("bootsnap/load_path_cache")
         
     | 
| 
      
 6 
     | 
    
         
            +
            require_relative("bootsnap/compile_cache")
         
     | 
| 
       7 
7 
     | 
    
         | 
| 
       8 
8 
     | 
    
         
             
            module Bootsnap
         
     | 
| 
       9 
9 
     | 
    
         
             
              InvalidConfiguration = Class.new(StandardError)
         
     | 
| 
       10 
10 
     | 
    
         | 
| 
       11 
     | 
    
         
            -
               
     | 
| 
       12 
     | 
    
         
            -
                 
     | 
| 
       13 
     | 
    
         
            -
             
     | 
| 
       14 
     | 
    
         
            -
                 
     | 
| 
       15 
     | 
    
         
            -
             
     | 
| 
       16 
     | 
    
         
            -
                 
     | 
| 
       17 
     | 
    
         
            -
             
     | 
| 
       18 
     | 
    
         
            -
                 
     | 
| 
       19 
     | 
    
         
            -
             
     | 
| 
       20 
     | 
    
         
            -
             
     | 
| 
       21 
     | 
    
         
            -
             
     | 
| 
       22 
     | 
    
         
            -
             
     | 
| 
       23 
     | 
    
         
            -
             
     | 
| 
       24 
     | 
    
         
            -
             
     | 
| 
       25 
     | 
    
         
            -
             
     | 
| 
       26 
     | 
    
         
            -
             
     | 
| 
       27 
     | 
    
         
            -
             
     | 
| 
       28 
     | 
    
         
            -
                   
     | 
| 
       29 
     | 
    
         
            -
                   
     | 
| 
       30 
     | 
    
         
            -
             
     | 
| 
       31 
     | 
    
         
            -
             
     | 
| 
       32 
     | 
    
         
            -
                 
     | 
| 
       33 
     | 
    
         
            -
             
     | 
| 
       34 
     | 
    
         
            -
             
     | 
| 
       35 
     | 
    
         
            -
                   
     | 
| 
      
 11 
     | 
    
         
            +
              class << self
         
     | 
| 
      
 12 
     | 
    
         
            +
                attr_reader :logger
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                def log!
         
     | 
| 
      
 15 
     | 
    
         
            +
                  self.logger = $stderr.method(:puts)
         
     | 
| 
      
 16 
     | 
    
         
            +
                end
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                def logger=(logger)
         
     | 
| 
      
 19 
     | 
    
         
            +
                  @logger = logger
         
     | 
| 
      
 20 
     | 
    
         
            +
                  self.instrumentation = if logger.respond_to?(:debug)
         
     | 
| 
      
 21 
     | 
    
         
            +
                    ->(event, path) { @logger.debug("[Bootsnap] #{event} #{path}") }
         
     | 
| 
      
 22 
     | 
    
         
            +
                  else
         
     | 
| 
      
 23 
     | 
    
         
            +
                    ->(event, path) { @logger.call("[Bootsnap] #{event} #{path}") }
         
     | 
| 
      
 24 
     | 
    
         
            +
                  end
         
     | 
| 
      
 25 
     | 
    
         
            +
                end
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                def instrumentation=(callback)
         
     | 
| 
      
 28 
     | 
    
         
            +
                  @instrumentation = callback
         
     | 
| 
      
 29 
     | 
    
         
            +
                  if respond_to?(:instrumentation_enabled=, true)
         
     | 
| 
      
 30 
     | 
    
         
            +
                    self.instrumentation_enabled = !!callback
         
     | 
| 
      
 31 
     | 
    
         
            +
                  end
         
     | 
| 
      
 32 
     | 
    
         
            +
                end
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                def _instrument(event, path)
         
     | 
| 
      
 35 
     | 
    
         
            +
                  @instrumentation.call(event, path)
         
     | 
| 
      
 36 
     | 
    
         
            +
                end
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
                def setup(
         
     | 
| 
      
 39 
     | 
    
         
            +
                  cache_dir:,
         
     | 
| 
      
 40 
     | 
    
         
            +
                  development_mode: true,
         
     | 
| 
      
 41 
     | 
    
         
            +
                  load_path_cache: true,
         
     | 
| 
      
 42 
     | 
    
         
            +
                  ignore_directories: nil,
         
     | 
| 
      
 43 
     | 
    
         
            +
                  readonly: false,
         
     | 
| 
      
 44 
     | 
    
         
            +
                  compile_cache_iseq: true,
         
     | 
| 
      
 45 
     | 
    
         
            +
                  compile_cache_yaml: true,
         
     | 
| 
      
 46 
     | 
    
         
            +
                  compile_cache_json: true
         
     | 
| 
       36 
47 
     | 
    
         
             
                )
         
     | 
| 
       37 
     | 
    
         
            -
             
     | 
| 
      
 48 
     | 
    
         
            +
                  if load_path_cache
         
     | 
| 
      
 49 
     | 
    
         
            +
                    Bootsnap::LoadPathCache.setup(
         
     | 
| 
      
 50 
     | 
    
         
            +
                      cache_path: "#{cache_dir}/bootsnap/load-path-cache",
         
     | 
| 
      
 51 
     | 
    
         
            +
                      development_mode: development_mode,
         
     | 
| 
      
 52 
     | 
    
         
            +
                      ignore_directories: ignore_directories,
         
     | 
| 
      
 53 
     | 
    
         
            +
                      readonly: readonly,
         
     | 
| 
      
 54 
     | 
    
         
            +
                    )
         
     | 
| 
      
 55 
     | 
    
         
            +
                  end
         
     | 
| 
       38 
56 
     | 
    
         | 
| 
       39 
     | 
    
         
            -
             
     | 
| 
       40 
     | 
    
         
            -
             
     | 
| 
       41 
     | 
    
         
            -
             
     | 
| 
       42 
     | 
    
         
            -
                     
     | 
| 
       43 
     | 
    
         
            -
                     
     | 
| 
      
 57 
     | 
    
         
            +
                  Bootsnap::CompileCache.setup(
         
     | 
| 
      
 58 
     | 
    
         
            +
                    cache_dir: "#{cache_dir}/bootsnap/compile-cache",
         
     | 
| 
      
 59 
     | 
    
         
            +
                    iseq: compile_cache_iseq,
         
     | 
| 
      
 60 
     | 
    
         
            +
                    yaml: compile_cache_yaml,
         
     | 
| 
      
 61 
     | 
    
         
            +
                    json: compile_cache_json,
         
     | 
| 
      
 62 
     | 
    
         
            +
                    readonly: readonly,
         
     | 
| 
       44 
63 
     | 
    
         
             
                  )
         
     | 
| 
      
 64 
     | 
    
         
            +
                end
         
     | 
| 
      
 65 
     | 
    
         
            +
             
     | 
| 
      
 66 
     | 
    
         
            +
                def unload_cache!
         
     | 
| 
      
 67 
     | 
    
         
            +
                  LoadPathCache.unload!
         
     | 
| 
      
 68 
     | 
    
         
            +
                end
         
     | 
| 
      
 69 
     | 
    
         
            +
             
     | 
| 
      
 70 
     | 
    
         
            +
                def default_setup
         
     | 
| 
      
 71 
     | 
    
         
            +
                  env = ENV["RAILS_ENV"] || ENV["RACK_ENV"] || ENV["ENV"]
         
     | 
| 
      
 72 
     | 
    
         
            +
                  development_mode = ["", nil, "development"].include?(env)
         
     | 
| 
      
 73 
     | 
    
         
            +
             
     | 
| 
      
 74 
     | 
    
         
            +
                  unless ENV["DISABLE_BOOTSNAP"]
         
     | 
| 
      
 75 
     | 
    
         
            +
                    cache_dir = ENV["BOOTSNAP_CACHE_DIR"]
         
     | 
| 
      
 76 
     | 
    
         
            +
                    unless cache_dir
         
     | 
| 
      
 77 
     | 
    
         
            +
                      config_dir_frame = caller.detect do |line|
         
     | 
| 
      
 78 
     | 
    
         
            +
                        line.include?("/config/")
         
     | 
| 
      
 79 
     | 
    
         
            +
                      end
         
     | 
| 
      
 80 
     | 
    
         
            +
             
     | 
| 
      
 81 
     | 
    
         
            +
                      unless config_dir_frame
         
     | 
| 
      
 82 
     | 
    
         
            +
                        $stderr.puts("[bootsnap/setup] couldn't infer cache directory! Either:")
         
     | 
| 
      
 83 
     | 
    
         
            +
                        $stderr.puts("[bootsnap/setup]   1. require bootsnap/setup from your application's config directory; or")
         
     | 
| 
      
 84 
     | 
    
         
            +
                        $stderr.puts("[bootsnap/setup]   2. Define the environment variable BOOTSNAP_CACHE_DIR")
         
     | 
| 
      
 85 
     | 
    
         
            +
             
     | 
| 
      
 86 
     | 
    
         
            +
                        raise("couldn't infer bootsnap cache directory")
         
     | 
| 
      
 87 
     | 
    
         
            +
                      end
         
     | 
| 
      
 88 
     | 
    
         
            +
             
     | 
| 
      
 89 
     | 
    
         
            +
                      path = config_dir_frame.split(/:\d+:/).first
         
     | 
| 
      
 90 
     | 
    
         
            +
                      path = File.dirname(path) until File.basename(path) == "config"
         
     | 
| 
      
 91 
     | 
    
         
            +
                      app_root = File.dirname(path)
         
     | 
| 
      
 92 
     | 
    
         
            +
             
     | 
| 
      
 93 
     | 
    
         
            +
                      cache_dir = File.join(app_root, "tmp", "cache")
         
     | 
| 
      
 94 
     | 
    
         
            +
                    end
         
     | 
| 
      
 95 
     | 
    
         
            +
             
     | 
| 
      
 96 
     | 
    
         
            +
                    ignore_directories = if ENV.key?("BOOTSNAP_IGNORE_DIRECTORIES")
         
     | 
| 
      
 97 
     | 
    
         
            +
                      ENV["BOOTSNAP_IGNORE_DIRECTORIES"].split(",")
         
     | 
| 
      
 98 
     | 
    
         
            +
                    end
         
     | 
| 
      
 99 
     | 
    
         
            +
             
     | 
| 
      
 100 
     | 
    
         
            +
                    setup(
         
     | 
| 
      
 101 
     | 
    
         
            +
                      cache_dir: cache_dir,
         
     | 
| 
      
 102 
     | 
    
         
            +
                      development_mode: development_mode,
         
     | 
| 
      
 103 
     | 
    
         
            +
                      load_path_cache: !ENV["DISABLE_BOOTSNAP_LOAD_PATH_CACHE"],
         
     | 
| 
      
 104 
     | 
    
         
            +
                      compile_cache_iseq: !ENV["DISABLE_BOOTSNAP_COMPILE_CACHE"],
         
     | 
| 
      
 105 
     | 
    
         
            +
                      compile_cache_yaml: !ENV["DISABLE_BOOTSNAP_COMPILE_CACHE"],
         
     | 
| 
      
 106 
     | 
    
         
            +
                      compile_cache_json: !ENV["DISABLE_BOOTSNAP_COMPILE_CACHE"],
         
     | 
| 
      
 107 
     | 
    
         
            +
                      readonly: !!ENV["BOOTSNAP_READONLY"],
         
     | 
| 
      
 108 
     | 
    
         
            +
                      ignore_directories: ignore_directories,
         
     | 
| 
      
 109 
     | 
    
         
            +
                    )
         
     | 
| 
      
 110 
     | 
    
         
            +
             
     | 
| 
      
 111 
     | 
    
         
            +
                    if ENV["BOOTSNAP_LOG"]
         
     | 
| 
      
 112 
     | 
    
         
            +
                      log!
         
     | 
| 
      
 113 
     | 
    
         
            +
                    end
         
     | 
| 
      
 114 
     | 
    
         
            +
                  end
         
     | 
| 
      
 115 
     | 
    
         
            +
                end
         
     | 
| 
      
 116 
     | 
    
         
            +
             
     | 
| 
      
 117 
     | 
    
         
            +
                if RbConfig::CONFIG["host_os"] =~ /mswin|mingw|cygwin/
         
     | 
| 
      
 118 
     | 
    
         
            +
                  def absolute_path?(path)
         
     | 
| 
      
 119 
     | 
    
         
            +
                    path[1] == ":"
         
     | 
| 
      
 120 
     | 
    
         
            +
                  end
         
     | 
| 
       45 
121 
     | 
    
         
             
                else
         
     | 
| 
       46 
     | 
    
         
            -
                   
     | 
| 
      
 122 
     | 
    
         
            +
                  def absolute_path?(path)
         
     | 
| 
      
 123 
     | 
    
         
            +
                    path.start_with?("/")
         
     | 
| 
      
 124 
     | 
    
         
            +
                  end
         
     | 
| 
       47 
125 
     | 
    
         
             
                end
         
     | 
| 
      
 126 
     | 
    
         
            +
             
     | 
| 
      
 127 
     | 
    
         
            +
                # This is a semi-accurate ruby implementation of the native `rb_get_path(VALUE)` function.
         
     | 
| 
      
 128 
     | 
    
         
            +
                # The native version is very intricate and may behave differently on windows etc.
         
     | 
| 
      
 129 
     | 
    
         
            +
                # But we only use it for non-MRI platform.
         
     | 
| 
      
 130 
     | 
    
         
            +
                def rb_get_path(fname)
         
     | 
| 
      
 131 
     | 
    
         
            +
                  path_path = fname.respond_to?(:to_path) ? fname.to_path : fname
         
     | 
| 
      
 132 
     | 
    
         
            +
                  String.try_convert(path_path) || raise(TypeError, "no implicit conversion of #{path_path.class} into String")
         
     | 
| 
      
 133 
     | 
    
         
            +
                end
         
     | 
| 
      
 134 
     | 
    
         
            +
             
     | 
| 
      
 135 
     | 
    
         
            +
                # Allow the C extension to redefine `rb_get_path` without warning.
         
     | 
| 
      
 136 
     | 
    
         
            +
                alias_method :rb_get_path, :rb_get_path # rubocop:disable Lint/DuplicateMethods
         
     | 
| 
       48 
137 
     | 
    
         
             
              end
         
     | 
| 
       49 
138 
     | 
    
         
             
            end
         
     |