bootsnap 1.9.2 → 1.10.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.
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative('../explicit_require')
3
+ require_relative("../explicit_require")
4
4
 
5
5
  module Bootsnap
6
6
  module LoadPathCache
@@ -28,15 +28,16 @@ module Bootsnap
28
28
  BUILTIN_FEATURES = $LOADED_FEATURES.each_with_object({}) do |feat, features|
29
29
  # Builtin features are of the form 'enumerator.so'.
30
30
  # All others include paths.
31
- next unless feat.size < 20 && !feat.include?('/')
31
+ next unless feat.size < 20 && !feat.include?("/")
32
32
 
33
- base = File.basename(feat, '.*') # enumerator.so -> enumerator
33
+ base = File.basename(feat, ".*") # enumerator.so -> enumerator
34
34
  ext = File.extname(feat) # .so
35
35
 
36
36
  features[feat] = nil # enumerator.so
37
37
  features[base] = nil # enumerator
38
38
 
39
39
  next unless [DOT_SO, *DL_EXTENSIONS].include?(ext)
40
+
40
41
  DL_EXTENSIONS.each do |dl_ext|
41
42
  features["#{base}#{dl_ext}"] = nil # enumerator.bundle
42
43
  end
@@ -48,9 +49,9 @@ module Bootsnap
48
49
  reinitialize if (@has_relative_paths && dir_changed?) || stale?
49
50
  feature = feature.to_s.freeze
50
51
 
51
- return feature if absolute_path?(feature)
52
+ return feature if Bootsnap.absolute_path?(feature)
52
53
 
53
- if feature.start_with?('./', '../')
54
+ if feature.start_with?("./", "../")
54
55
  return try_extensions ? expand_path(feature) : File.expand_path(feature).freeze
55
56
  end
56
57
 
@@ -64,7 +65,7 @@ module Bootsnap
64
65
  # returns false as if it were already loaded; however, there is no
65
66
  # file to find on disk. We've pre-built a list of these, and we
66
67
  # return false if any of them is loaded.
67
- raise(LoadPathCache::ReturnFalse, '', []) if BUILTIN_FEATURES.key?(feature)
68
+ raise(LoadPathCache::ReturnFalse, "", []) if BUILTIN_FEATURES.key?(feature)
68
69
 
69
70
  # The feature wasn't found on our preliminary search through the index.
70
71
  # We resolve this differently depending on what the extension was.
@@ -73,13 +74,14 @@ module Bootsnap
73
74
  # native dynamic extension, e.g. .bundle or .so), we know it was a
74
75
  # failure and there's nothing more we can do to find the file.
75
76
  # no extension, .rb, (.bundle or .so)
76
- when '', *CACHED_EXTENSIONS
77
+ when "", *CACHED_EXTENSIONS
77
78
  nil
78
79
  # Ruby allows specifying native extensions as '.so' even when DLEXT
79
80
  # is '.bundle'. This is where we handle that case.
80
81
  when DOT_SO
81
82
  x = search_index(feature[0..-4] + DLEXT)
82
83
  return x if x
84
+
83
85
  if DLEXT2
84
86
  x = search_index(feature[0..-4] + DLEXT2)
85
87
  return x if x
@@ -87,7 +89,7 @@ module Bootsnap
87
89
  else
88
90
  # other, unknown extension. For example, `.rake`. Since we haven't
89
91
  # cached these, we legitimately need to run the load path search.
90
- raise(LoadPathCache::FallbackScan, '', [])
92
+ raise(LoadPathCache::FallbackScan, "", [])
91
93
  end
92
94
  end
93
95
 
@@ -95,26 +97,18 @@ module Bootsnap
95
97
  # cases where the file doesn't appear to be on the load path. We should
96
98
  # be able to detect newly-created files without rebooting the
97
99
  # application.
98
- raise(LoadPathCache::FallbackScan, '', []) if @development_mode
99
- end
100
-
101
- if RbConfig::CONFIG['host_os'] =~ /mswin|mingw|cygwin/
102
- def absolute_path?(path)
103
- path[1] == ':'
104
- end
105
- else
106
- def absolute_path?(path)
107
- path.start_with?(SLASH)
108
- end
100
+ raise(LoadPathCache::FallbackScan, "", []) if @development_mode
109
101
  end
110
102
 
111
103
  def unshift_paths(sender, *paths)
112
104
  return unless sender == @path_obj
105
+
113
106
  @mutex.synchronize { unshift_paths_locked(*paths) }
114
107
  end
115
108
 
116
109
  def push_paths(sender, *paths)
117
110
  return unless sender == @path_obj
111
+
118
112
  @mutex.synchronize { push_paths_locked(*paths) }
119
113
  end
120
114
 
@@ -147,6 +141,7 @@ module Bootsnap
147
141
  p = Path.new(path)
148
142
  @has_relative_paths = true if p.relative?
149
143
  next if p.non_directory?
144
+
150
145
  expanded_path = p.expanded_path
151
146
  entries, dirs = p.entries_and_dirs(@store)
152
147
  # push -> low precedence -> set only if unset
@@ -161,6 +156,7 @@ module Bootsnap
161
156
  paths.map(&:to_s).reverse_each do |path|
162
157
  p = Path.new(path)
163
158
  next if p.non_directory?
159
+
164
160
  expanded_path = p.expanded_path
165
161
  entries, dirs = p.entries_and_dirs(@store)
166
162
  # unshift -> high precedence -> unconditional set
@@ -183,56 +179,62 @@ module Bootsnap
183
179
  end
184
180
 
185
181
  if DLEXT2
186
- def search_index(f, try_extensions: true)
182
+ def search_index(feature, try_extensions: true)
187
183
  if try_extensions
188
- try_index(f + DOT_RB) || try_index(f + DLEXT) || try_index(f + DLEXT2) || try_index(f)
184
+ try_index(feature + DOT_RB) ||
185
+ try_index(feature + DLEXT) ||
186
+ try_index(feature + DLEXT2) ||
187
+ try_index(feature)
189
188
  else
190
- try_index(f)
189
+ try_index(feature)
191
190
  end
192
191
  end
193
192
 
194
- def maybe_append_extension(f)
195
- try_ext(f + DOT_RB) || try_ext(f + DLEXT) || try_ext(f + DLEXT2) || f
193
+ def maybe_append_extension(feature)
194
+ try_ext(feature + DOT_RB) ||
195
+ try_ext(feature + DLEXT) ||
196
+ try_ext(feature + DLEXT2) ||
197
+ feature
196
198
  end
197
199
  else
198
- def search_index(f, try_extensions: true)
200
+ def search_index(feature, try_extensions: true)
199
201
  if try_extensions
200
- try_index(f + DOT_RB) || try_index(f + DLEXT) || try_index(f)
202
+ try_index(feature + DOT_RB) || try_index(feature + DLEXT) || try_index(feature)
201
203
  else
202
- try_index(f)
204
+ try_index(feature)
203
205
  end
204
206
  end
205
207
 
206
- def maybe_append_extension(f)
207
- try_ext(f + DOT_RB) || try_ext(f + DLEXT) || f
208
+ def maybe_append_extension(feature)
209
+ try_ext(feature + DOT_RB) || try_ext(feature + DLEXT) || feature
208
210
  end
209
211
  end
210
212
 
211
213
  s = rand.to_s.force_encoding(Encoding::US_ASCII).freeze
212
214
  if s.respond_to?(:-@)
213
- if (-s).equal?(s) && (-s.dup).equal?(s) || RUBY_VERSION >= '2.7'
214
- def try_index(f)
215
- if (p = @index[f])
216
- -(File.join(p, f).freeze)
215
+ if (-s).equal?(s) && (-s.dup).equal?(s) || RUBY_VERSION >= "2.7"
216
+ def try_index(feature)
217
+ if (path = @index[feature])
218
+ -File.join(path, feature).freeze
217
219
  end
218
220
  end
219
221
  else
220
- def try_index(f)
221
- if (p = @index[f])
222
- -File.join(p, f).untaint
222
+ def try_index(feature)
223
+ if (path = @index[feature])
224
+ -File.join(path, feature).untaint
223
225
  end
224
226
  end
225
227
  end
226
228
  else
227
- def try_index(f)
228
- if (p = @index[f])
229
- File.join(p, f)
229
+ def try_index(feature)
230
+ if (path = @index[feature])
231
+ File.join(path, feature)
230
232
  end
231
233
  end
232
234
  end
233
235
 
234
- def try_ext(f)
235
- f if File.exist?(f)
236
+ def try_ext(feature)
237
+ feature if File.exist?(feature)
236
238
  end
237
239
  end
238
240
  end
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Bootsnap
3
4
  module LoadPathCache
4
5
  module ChangeObserver
@@ -57,6 +58,7 @@ module Bootsnap
57
58
 
58
59
  def self.register(observer, arr)
59
60
  return if arr.frozen? # can't register observer, but no need to.
61
+
60
62
  arr.instance_variable_set(:@lpc_observer, observer)
61
63
  arr.extend(ArrayMixin)
62
64
  end
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Bootsnap
3
4
  module LoadPathCache
4
5
  module CoreExt
@@ -13,35 +14,42 @@ module Bootsnap
13
14
  end
14
15
 
15
16
  module Kernel
16
- module_function # rubocop:disable Style/ModuleFunction
17
+ module_function
17
18
 
18
19
  alias_method(:require_without_bootsnap, :require)
19
20
 
20
- # Note that require registers to $LOADED_FEATURES while load does not.
21
- def require_with_bootsnap_lfi(path, resolved = nil)
22
- Bootsnap::LoadPathCache.loaded_features_index.register(path, resolved) do
23
- require_without_bootsnap(resolved || path)
24
- end
25
- end
26
-
27
21
  def require(path)
28
- return false if Bootsnap::LoadPathCache.loaded_features_index.key?(path)
22
+ fallback = false
23
+ string_path = path.to_s
24
+ return false if Bootsnap::LoadPathCache.loaded_features_index.key?(string_path)
29
25
 
30
- if (resolved = Bootsnap::LoadPathCache.load_path_cache.find(path))
31
- return require_with_bootsnap_lfi(path, resolved)
26
+ if (resolved = Bootsnap::LoadPathCache.load_path_cache.find(string_path))
27
+ # Note that require registers to $LOADED_FEATURES while load does not.
28
+ ret = require_without_bootsnap(resolved)
29
+ Bootsnap::LoadPathCache.loaded_features_index.register(string_path, resolved)
30
+ return ret
32
31
  end
33
32
 
34
33
  raise(Bootsnap::LoadPathCache::CoreExt.make_load_error(path))
35
- rescue LoadError => e
36
- e.instance_variable_set(Bootsnap::LoadPathCache::ERROR_TAG_IVAR, true)
37
- raise(e)
34
+ rescue LoadError => error
35
+ error.instance_variable_set(Bootsnap::LoadPathCache::ERROR_TAG_IVAR, true)
36
+ raise(error)
38
37
  rescue Bootsnap::LoadPathCache::ReturnFalse
39
38
  false
40
39
  rescue Bootsnap::LoadPathCache::FallbackScan
41
40
  fallback = true
42
41
  ensure
42
+ # We raise from `ensure` so that any further exception don't have FallbackScan as a cause
43
+ # See: https://github.com/Shopify/bootsnap/issues/250
43
44
  if fallback
44
- require_with_bootsnap_lfi(path)
45
+ if (cursor = Bootsnap::LoadPathCache.loaded_features_index.cursor(string_path))
46
+ ret = require_without_bootsnap(path)
47
+ resolved = Bootsnap::LoadPathCache.loaded_features_index.identify(string_path, cursor)
48
+ Bootsnap::LoadPathCache.loaded_features_index.register(string_path, resolved)
49
+ ret
50
+ else # If we're not given a cursor, it means we don't need to register the path (likely an absolute path)
51
+ require_without_bootsnap(path)
52
+ end
45
53
  end
46
54
  end
47
55
 
@@ -67,6 +75,7 @@ end
67
75
  class Module
68
76
  alias_method(:autoload_without_bootsnap, :autoload)
69
77
  def autoload(const, path)
78
+ fallback = false
70
79
  # NOTE: This may defeat LoadedFeaturesIndex, but it's not immediately
71
80
  # obvious how to make it work. This feels like a pretty niche case, unclear
72
81
  # if it will ever burn anyone.
@@ -75,16 +84,16 @@ class Module
75
84
  # added to $LOADED_FEATURES and won't be able to hook that modification
76
85
  # since it's done in C-land.
77
86
  autoload_without_bootsnap(const, Bootsnap::LoadPathCache.load_path_cache.find(path) || path)
78
- rescue LoadError => e
79
- e.instance_variable_set(Bootsnap::LoadPathCache::ERROR_TAG_IVAR, true)
80
- raise(e)
87
+ rescue LoadError => error
88
+ error.instance_variable_set(Bootsnap::LoadPathCache::ERROR_TAG_IVAR, true)
89
+ raise(error)
81
90
  rescue Bootsnap::LoadPathCache::ReturnFalse
82
91
  false
83
92
  rescue Bootsnap::LoadPathCache::FallbackScan
84
93
  fallback = true
85
94
  ensure
86
- if fallback
87
- autoload_without_bootsnap(const, path)
88
- end
95
+ # We raise from `ensure` so that any further exception don't have FallbackScan as a cause
96
+ # See: https://github.com/Shopify/bootsnap/issues/250
97
+ autoload_without_bootsnap(const, path)
89
98
  end
90
99
  end
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  class << $LOADED_FEATURES
3
4
  alias_method(:delete_without_bootsnap, :delete)
4
5
  def delete(key)
@@ -29,14 +29,15 @@ module Bootsnap
29
29
  @mutex = Mutex.new
30
30
 
31
31
  # In theory the user could mutate $LOADED_FEATURES and invalidate our
32
- # cache. If this ever comes up in practice or if you, the
33
- # enterprising reader, feels inclined to solve this problem we could
32
+ # cache. If this ever comes up in practice - or if you, the
33
+ # enterprising reader, feels inclined to solve this problem - we could
34
34
  # parallel the work done with ChangeObserver on $LOAD_PATH to mirror
35
35
  # updates to our @lfi.
36
36
  $LOADED_FEATURES.each do |feat|
37
37
  hash = feat.hash
38
38
  $LOAD_PATH.each do |lpe|
39
39
  next unless feat.start_with?(lpe)
40
+
40
41
  # /a/b/lib/my/foo.rb
41
42
  # ^^^^^^^^^
42
43
  short = feat[(lpe.length + 1)..-1]
@@ -68,6 +69,25 @@ module Bootsnap
68
69
  @mutex.synchronize { @lfi.key?(feature) }
69
70
  end
70
71
 
72
+ def cursor(short)
73
+ unless Bootsnap.absolute_path?(short.to_s)
74
+ $LOADED_FEATURES.size
75
+ end
76
+ end
77
+
78
+ def identify(short, cursor)
79
+ $LOADED_FEATURES[cursor..-1].detect do |feat|
80
+ offset = 0
81
+ while (offset = feat.index(short, offset))
82
+ if feat.index(".", offset + 1) && !feat.index("/", offset + 2)
83
+ break true
84
+ else
85
+ offset += 1
86
+ end
87
+ end
88
+ end
89
+ end
90
+
71
91
  # There is a relatively uncommon case where we could miss adding an
72
92
  # entry:
73
93
  #
@@ -82,23 +102,8 @@ module Bootsnap
82
102
  # not quite right; or
83
103
  # 2. Inspect $LOADED_FEATURES upon return from yield to find the matching
84
104
  # entry.
85
- def register(short, long = nil)
86
- if long.nil?
87
- len = $LOADED_FEATURES.size
88
- ret = yield
89
- long = $LOADED_FEATURES[len..-1].detect do |feat|
90
- offset = 0
91
- while offset = feat.index(short, offset)
92
- if feat.index(".", offset + 1) && !feat.index("/", offset + 2)
93
- break true
94
- else
95
- offset += 1
96
- end
97
- end
98
- end
99
- else
100
- ret = yield
101
- end
105
+ def register(short, long)
106
+ return if Bootsnap.absolute_path?(short)
102
107
 
103
108
  hash = long.hash
104
109
 
@@ -117,13 +122,11 @@ module Bootsnap
117
122
  @lfi[short] = hash
118
123
  (@lfi[altname] = hash) if altname
119
124
  end
120
-
121
- ret
122
125
  end
123
126
 
124
127
  private
125
128
 
126
- STRIP_EXTENSION = /\.[^.]*?$/
129
+ STRIP_EXTENSION = /\.[^.]*?$/.freeze
127
130
  private_constant(:STRIP_EXTENSION)
128
131
 
129
132
  # Might Ruby automatically search for this extension if
@@ -140,15 +143,15 @@ module Bootsnap
140
143
  # with calling a Ruby file 'x.dylib.rb' and then requiring it as 'x.dylib'.)
141
144
  #
142
145
  # See <https://ruby-doc.org/core-2.6.4/Kernel.html#method-i-require>.
143
- def extension_elidable?(f)
144
- f.to_s.end_with?('.rb', '.so', '.o', '.dll', '.dylib')
146
+ def extension_elidable?(feature)
147
+ feature.to_s.end_with?(".rb", ".so", ".o", ".dll", ".dylib")
145
148
  end
146
149
 
147
- def strip_extension_if_elidable(f)
148
- if extension_elidable?(f)
149
- f.sub(STRIP_EXTENSION, '')
150
+ def strip_extension_if_elidable(feature)
151
+ if extension_elidable?(feature)
152
+ feature.sub(STRIP_EXTENSION, "")
150
153
  else
151
- f
154
+ feature
152
155
  end
153
156
  end
154
157
  end
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
- require_relative('path_scanner')
2
+
3
+ require_relative("path_scanner")
3
4
 
4
5
  module Bootsnap
5
6
  module LoadPathCache
@@ -43,6 +44,7 @@ module Bootsnap
43
44
  # set to zero anyway, just in case we change the stability heuristics.
44
45
  _, entries, dirs = store.get(expanded_path)
45
46
  return [entries, dirs] if entries # cache hit
47
+
46
48
  entries, dirs = scan!
47
49
  store.set(expanded_path, [0, entries, dirs])
48
50
  return [entries, dirs]
@@ -93,8 +95,8 @@ module Bootsnap
93
95
 
94
96
  # Built-in ruby lib stuff doesn't change, but things can occasionally be
95
97
  # installed into sitedir, which generally lives under libdir.
96
- RUBY_LIBDIR = RbConfig::CONFIG['libdir']
97
- RUBY_SITEDIR = RbConfig::CONFIG['sitedir']
98
+ RUBY_LIBDIR = RbConfig::CONFIG["libdir"]
99
+ RUBY_SITEDIR = RbConfig::CONFIG["sitedir"]
98
100
 
99
101
  def stability
100
102
  @stability ||= begin
@@ -1,18 +1,18 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative('../explicit_require')
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
18
  class << self
@@ -44,7 +44,8 @@ module Bootsnap
44
44
 
45
45
  def walk(absolute_dir_path, relative_dir_path, &block)
46
46
  Dir.foreach(absolute_dir_path) do |name|
47
- next if name.start_with?('.')
47
+ next if name.start_with?(".")
48
+
48
49
  relative_path = relative_dir_path ? File.join(relative_dir_path, name) : name
49
50
 
50
51
  absolute_path = "#{absolute_dir_path}/#{name}"
@@ -58,7 +59,7 @@ module Bootsnap
58
59
  end
59
60
  end
60
61
 
61
- if RUBY_VERSION >= '3.1'
62
+ if RUBY_VERSION >= "3.1"
62
63
  def os_path(path)
63
64
  path.freeze
64
65
  end
@@ -21,6 +21,7 @@ module Bootsnap
21
21
 
22
22
  def find_file(name)
23
23
  return File.realpath(name).freeze if File.exist?(name)
24
+
24
25
  CACHED_EXTENSIONS.each do |ext|
25
26
  filename = "#{name}#{ext}"
26
27
  return File.realpath(filename).freeze if File.exist?(filename)
@@ -1,12 +1,15 @@
1
1
  # frozen_string_literal: true
2
- require_relative('../explicit_require')
3
2
 
4
- Bootsnap::ExplicitRequire.with_gems('msgpack') { require('msgpack') }
5
- Bootsnap::ExplicitRequire.from_rubylibdir('fileutils')
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
 
@@ -23,6 +26,7 @@ module Bootsnap
23
26
 
24
27
  def fetch(key)
25
28
  raise(SetOutsideTransactionNotAllowed) unless @txn_mutex.owned?
29
+
26
30
  v = get(key)
27
31
  unless v
28
32
  @dirty = true
@@ -34,6 +38,7 @@ module Bootsnap
34
38
 
35
39
  def set(key, value)
36
40
  raise(SetOutsideTransactionNotAllowed) unless @txn_mutex.owned?
41
+
37
42
  if value != @data[key]
38
43
  @dirty = true
39
44
  @data[key] = value
@@ -42,6 +47,7 @@ module Bootsnap
42
47
 
43
48
  def transaction
44
49
  raise(NestedTransactionError) if @txn_mutex.owned?
50
+
45
51
  @txn_mutex.synchronize do
46
52
  begin
47
53
  yield
@@ -62,15 +68,20 @@ module Bootsnap
62
68
 
63
69
  def load_data
64
70
  @data = begin
65
- File.open(@store_path, encoding: Encoding::BINARY) do |io|
71
+ data = File.open(@store_path, encoding: Encoding::BINARY) do |io|
66
72
  MessagePack.load(io)
67
73
  end
74
+ if data.is_a?(Hash) && data[VERSION_KEY] == CURRENT_VERSION
75
+ data
76
+ else
77
+ default_data
78
+ end
68
79
  # handle malformed data due to upgrade incompatibility
69
80
  rescue Errno::ENOENT, MessagePack::MalformedFormatError, MessagePack::UnknownExtTypeError, EOFError
70
- {}
81
+ default_data
71
82
  rescue ArgumentError => error
72
83
  if error.message =~ /negative array size/
73
- {}
84
+ default_data
74
85
  else
75
86
  raise
76
87
  end
@@ -78,9 +89,11 @@ module Bootsnap
78
89
  end
79
90
 
80
91
  def dump_data
92
+ require "fileutils" unless defined? FileUtils
93
+
81
94
  # Change contents atomically so other processes can't get invalid
82
95
  # caches if they read at an inopportune time.
83
- tmp = "#{@store_path}.#{Process.pid}.#{(rand * 100000).to_i}.tmp"
96
+ tmp = "#{@store_path}.#{Process.pid}.#{(rand * 100_000).to_i}.tmp"
84
97
  FileUtils.mkpath(File.dirname(tmp))
85
98
  exclusive_write = File::Constants::CREAT | File::Constants::EXCL | File::Constants::WRONLY
86
99
  # `encoding:` looks redundant wrt `binwrite`, but necessary on windows
@@ -93,6 +106,10 @@ module Bootsnap
93
106
  retry
94
107
  rescue SystemCallError
95
108
  end
109
+
110
+ def default_data
111
+ {VERSION_KEY => CURRENT_VERSION}
112
+ end
96
113
  end
97
114
  end
98
115
  end
@@ -5,9 +5,9 @@ module Bootsnap
5
5
  ReturnFalse = Class.new(StandardError)
6
6
  FallbackScan = Class.new(StandardError)
7
7
 
8
- DOT_RB = '.rb'
9
- DOT_SO = '.so'
10
- SLASH = '/'
8
+ DOT_RB = ".rb"
9
+ DOT_SO = ".so"
10
+ SLASH = "/"
11
11
 
12
12
  # If a NameError happens several levels deep, don't re-handle it
13
13
  # all the way up the chain: mark it once and bubble it up without
@@ -15,7 +15,7 @@ module Bootsnap
15
15
  ERROR_TAG_IVAR = :@__bootsnap_rescued
16
16
 
17
17
  DL_EXTENSIONS = ::RbConfig::CONFIG
18
- .values_at('DLEXT', 'DLEXT2')
18
+ .values_at("DLEXT", "DLEXT2")
19
19
  .reject { |ext| !ext || ext.empty? }
20
20
  .map { |ext| ".#{ext}" }
21
21
  .freeze
@@ -42,24 +42,24 @@ module Bootsnap
42
42
  @realpath_cache = RealpathCache.new
43
43
 
44
44
  @load_path_cache = Cache.new(store, $LOAD_PATH, development_mode: development_mode)
45
- require_relative('load_path_cache/core_ext/kernel_require')
46
- require_relative('load_path_cache/core_ext/loaded_features')
45
+ require_relative("load_path_cache/core_ext/kernel_require")
46
+ require_relative("load_path_cache/core_ext/loaded_features")
47
47
  end
48
48
 
49
49
  def supported?
50
- RUBY_ENGINE == 'ruby' &&
51
- RUBY_PLATFORM =~ /darwin|linux|bsd|mswin|mingw|cygwin/
50
+ RUBY_ENGINE == "ruby" &&
51
+ RUBY_PLATFORM =~ /darwin|linux|bsd|mswin|mingw|cygwin/
52
52
  end
53
53
  end
54
54
  end
55
55
  end
56
56
 
57
57
  if Bootsnap::LoadPathCache.supported?
58
- require_relative('load_path_cache/path_scanner')
59
- require_relative('load_path_cache/path')
60
- require_relative('load_path_cache/cache')
61
- require_relative('load_path_cache/store')
62
- require_relative('load_path_cache/change_observer')
63
- require_relative('load_path_cache/loaded_features_index')
64
- require_relative('load_path_cache/realpath_cache')
58
+ require_relative("load_path_cache/path_scanner")
59
+ require_relative("load_path_cache/path")
60
+ require_relative("load_path_cache/cache")
61
+ require_relative("load_path_cache/store")
62
+ require_relative("load_path_cache/change_observer")
63
+ require_relative("load_path_cache/loaded_features_index")
64
+ require_relative("load_path_cache/realpath_cache")
65
65
  end
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
- require_relative('../bootsnap')
2
+
3
+ require_relative("../bootsnap")
3
4
 
4
5
  Bootsnap.default_setup
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Bootsnap
3
- VERSION = "1.9.2"
4
+ VERSION = "1.10.0"
4
5
  end