bootsnap 1.9.1 → 1.16.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,19 +1,23 @@
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
 
13
- def initialize(store_path)
16
+ def initialize(store_path, readonly: false)
14
17
  @store_path = store_path
15
18
  @txn_mutex = Mutex.new
16
19
  @dirty = false
20
+ @readonly = readonly
17
21
  load_data
18
22
  end
19
23
 
@@ -23,10 +27,11 @@ module Bootsnap
23
27
 
24
28
  def fetch(key)
25
29
  raise(SetOutsideTransactionNotAllowed) unless @txn_mutex.owned?
30
+
26
31
  v = get(key)
27
32
  unless v
28
- @dirty = true
29
33
  v = yield
34
+ mark_for_mutation!
30
35
  @data[key] = v
31
36
  end
32
37
  v
@@ -34,27 +39,32 @@ module Bootsnap
34
39
 
35
40
  def set(key, value)
36
41
  raise(SetOutsideTransactionNotAllowed) unless @txn_mutex.owned?
42
+
37
43
  if value != @data[key]
38
- @dirty = true
44
+ mark_for_mutation!
39
45
  @data[key] = value
40
46
  end
41
47
  end
42
48
 
43
49
  def transaction
44
50
  raise(NestedTransactionError) if @txn_mutex.owned?
51
+
45
52
  @txn_mutex.synchronize do
46
- begin
47
- yield
48
- ensure
49
- commit_transaction
50
- end
53
+ yield
54
+ ensure
55
+ commit_transaction
51
56
  end
52
57
  end
53
58
 
54
59
  private
55
60
 
61
+ def mark_for_mutation!
62
+ @dirty = true
63
+ @data = @data.dup if @data.frozen?
64
+ end
65
+
56
66
  def commit_transaction
57
- if @dirty
67
+ if @dirty && !@readonly
58
68
  dump_data
59
69
  @dirty = false
60
70
  end
@@ -62,15 +72,20 @@ module Bootsnap
62
72
 
63
73
  def load_data
64
74
  @data = begin
65
- File.open(@store_path, encoding: Encoding::BINARY) do |io|
66
- MessagePack.load(io)
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
67
82
  end
68
83
  # handle malformed data due to upgrade incompatibility
69
84
  rescue Errno::ENOENT, MessagePack::MalformedFormatError, MessagePack::UnknownExtTypeError, EOFError
70
- {}
85
+ default_data
71
86
  rescue ArgumentError => error
72
87
  if error.message =~ /negative array size/
73
- {}
88
+ default_data
74
89
  else
75
90
  raise
76
91
  end
@@ -80,19 +95,36 @@ module Bootsnap
80
95
  def dump_data
81
96
  # Change contents atomically so other processes can't get invalid
82
97
  # caches if they read at an inopportune time.
83
- tmp = "#{@store_path}.#{Process.pid}.#{(rand * 100000).to_i}.tmp"
84
- FileUtils.mkpath(File.dirname(tmp))
98
+ tmp = "#{@store_path}.#{Process.pid}.#{(rand * 100_000).to_i}.tmp"
99
+ mkdir_p(File.dirname(tmp))
85
100
  exclusive_write = File::Constants::CREAT | File::Constants::EXCL | File::Constants::WRONLY
86
101
  # `encoding:` looks redundant wrt `binwrite`, but necessary on windows
87
102
  # because binary is part of mode.
88
103
  File.open(tmp, mode: exclusive_write, encoding: Encoding::BINARY) do |io|
89
- MessagePack.dump(@data, io, freeze: true)
104
+ MessagePack.dump(@data, io)
90
105
  end
91
- FileUtils.mv(tmp, @store_path)
106
+ File.rename(tmp, @store_path)
92
107
  rescue Errno::EEXIST
93
108
  retry
94
109
  rescue SystemCallError
95
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
127
+ end
96
128
  end
97
129
  end
98
130
  end
@@ -2,20 +2,14 @@
2
2
 
3
3
  module Bootsnap
4
4
  module LoadPathCache
5
- ReturnFalse = Class.new(StandardError)
6
- FallbackScan = Class.new(StandardError)
5
+ FALLBACK_SCAN = BasicObject.new
7
6
 
8
- DOT_RB = '.rb'
9
- DOT_SO = '.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('DLEXT', 'DLEXT2')
12
+ .values_at("DLEXT", "DLEXT2")
19
13
  .reject { |ext| !ext || ext.empty? }
20
14
  .map { |ext| ".#{ext}" }
21
15
  .freeze
@@ -27,39 +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, :loaded_features_index, :realpath_cache)
27
+ attr_reader(:load_path_cache, :loaded_features_index, :enabled)
28
+ alias_method :enabled?, :enabled
29
+ remove_method(:enabled)
32
30
 
33
- def setup(cache_path:, development_mode:)
31
+ def setup(cache_path:, development_mode:, ignore_directories:, readonly: false)
34
32
  unless supported?
35
33
  warn("[bootsnap/setup] Load path caching is not supported on this implementation of Ruby") if $VERBOSE
36
34
  return
37
35
  end
38
36
 
39
- store = Store.new(cache_path)
37
+ store = Store.new(cache_path, readonly: readonly)
40
38
 
41
39
  @loaded_features_index = LoadedFeaturesIndex.new
42
- @realpath_cache = RealpathCache.new
43
40
 
44
41
  @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')
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
47
+
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)
47
54
  end
48
55
 
49
56
  def supported?
50
- RUBY_ENGINE == 'ruby' &&
51
- RUBY_PLATFORM =~ /darwin|linux|bsd|mswin|mingw|cygwin/
57
+ RUBY_ENGINE == "ruby" &&
58
+ RUBY_PLATFORM =~ /darwin|linux|bsd|mswin|mingw|cygwin/
52
59
  end
53
60
  end
54
61
  end
55
62
  end
56
63
 
57
64
  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')
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")
65
71
  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.1"
4
+ VERSION = "1.16.0"
4
5
  end
data/lib/bootsnap.rb CHANGED
@@ -1,126 +1,138 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative('bootsnap/version')
4
- require_relative('bootsnap/bundler')
5
- require_relative('bootsnap/load_path_cache')
6
- require_relative('bootsnap/compile_cache')
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
11
  class << self
12
12
  attr_reader :logger
13
- end
14
-
15
- def self.log!
16
- self.logger = $stderr.method(:puts)
17
- end
18
13
 
19
- def self.logger=(logger)
20
- @logger = logger
21
- if logger.respond_to?(:debug)
22
- self.instrumentation = ->(event, path) { @logger.debug("[Bootsnap] #{event} #{path}") }
23
- else
24
- self.instrumentation = ->(event, path) { @logger.call("[Bootsnap] #{event} #{path}") }
14
+ def log!
15
+ self.logger = $stderr.method(:puts)
25
16
  end
26
- end
27
17
 
28
- def self.instrumentation=(callback)
29
- @instrumentation = callback
30
- if respond_to?(:instrumentation_enabled=, true)
31
- self.instrumentation_enabled = !!callback
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
32
25
  end
33
- end
34
26
 
35
- def self._instrument(event, path)
36
- @instrumentation.call(event, path)
37
- end
27
+ def instrumentation=(callback)
28
+ @instrumentation = callback
29
+ if respond_to?(:instrumentation_enabled=, true)
30
+ self.instrumentation_enabled = !!callback
31
+ end
32
+ end
38
33
 
39
- def self.setup(
40
- cache_dir:,
41
- development_mode: true,
42
- load_path_cache: true,
43
- autoload_paths_cache: nil,
44
- disable_trace: nil,
45
- compile_cache_iseq: true,
46
- compile_cache_yaml: true,
47
- compile_cache_json: true
48
- )
49
- unless autoload_paths_cache.nil?
50
- warn "[DEPRECATED] Bootsnap's `autoload_paths_cache:` option is deprecated and will be removed. " \
51
- "If you use Zeitwerk this option is useless, and if you are still using the classic autoloader " \
52
- "upgrading is recommended."
34
+ def _instrument(event, path)
35
+ @instrumentation.call(event, path)
53
36
  end
54
37
 
55
- unless disable_trace.nil?
56
- warn "[DEPRECATED] Bootsnap's `disable_trace:` option is deprecated and will be removed. " \
57
- "If you use Ruby 2.5 or newer this option is useless, if not upgrading is recommended."
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
47
+ )
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
56
+
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,
63
+ )
58
64
  end
59
65
 
60
- if compile_cache_iseq && !iseq_cache_supported?
61
- warn "Ruby 2.5 has a bug that break code tracing when code is loaded from cache. It is recommened " \
62
- "to turn `compile_cache_iseq` off on Ruby 2.5"
66
+ def unload_cache!
67
+ LoadPathCache.unload!
63
68
  end
64
69
 
65
- Bootsnap::LoadPathCache.setup(
66
- cache_path: cache_dir + '/bootsnap/load-path-cache',
67
- development_mode: development_mode,
68
- ) if load_path_cache
70
+ def default_setup
71
+ env = ENV["RAILS_ENV"] || ENV["RACK_ENV"] || ENV["ENV"]
72
+ development_mode = ["", nil, "development"].include?(env)
69
73
 
70
- Bootsnap::CompileCache.setup(
71
- cache_dir: cache_dir + '/bootsnap/compile-cache',
72
- iseq: compile_cache_iseq,
73
- yaml: compile_cache_yaml,
74
- json: compile_cache_json,
75
- )
76
- end
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
77
80
 
78
- def self.iseq_cache_supported?
79
- return @iseq_cache_supported if defined? @iseq_cache_supported
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")
80
85
 
81
- ruby_version = Gem::Version.new(RUBY_VERSION)
82
- @iseq_cache_supported = ruby_version < Gem::Version.new('2.5.0') || ruby_version >= Gem::Version.new('2.6.0')
83
- end
86
+ raise("couldn't infer bootsnap cache directory")
87
+ end
84
88
 
85
- def self.default_setup
86
- env = ENV['RAILS_ENV'] || ENV['RACK_ENV'] || ENV['ENV']
87
- development_mode = ['', nil, 'development'].include?(env)
89
+ path = config_dir_frame.split(/:\d+:/).first
90
+ path = File.dirname(path) until File.basename(path) == "config"
91
+ app_root = File.dirname(path)
88
92
 
89
- unless ENV['DISABLE_BOOTSNAP']
90
- cache_dir = ENV['BOOTSNAP_CACHE_DIR']
91
- unless cache_dir
92
- config_dir_frame = caller.detect do |line|
93
- line.include?('/config/')
93
+ cache_dir = File.join(app_root, "tmp", "cache")
94
94
  end
95
95
 
96
- unless config_dir_frame
97
- $stderr.puts("[bootsnap/setup] couldn't infer cache directory! Either:")
98
- $stderr.puts("[bootsnap/setup] 1. require bootsnap/setup from your application's config directory; or")
99
- $stderr.puts("[bootsnap/setup] 2. Define the environment variable BOOTSNAP_CACHE_DIR")
100
-
101
- raise("couldn't infer bootsnap cache directory")
96
+ ignore_directories = if ENV.key?("BOOTSNAP_IGNORE_DIRECTORIES")
97
+ ENV["BOOTSNAP_IGNORE_DIRECTORIES"].split(",")
102
98
  end
103
99
 
104
- path = config_dir_frame.split(/:\d+:/).first
105
- path = File.dirname(path) until File.basename(path) == 'config'
106
- app_root = File.dirname(path)
107
-
108
- cache_dir = File.join(app_root, 'tmp', 'cache')
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
109
114
  end
115
+ end
110
116
 
111
-
112
- setup(
113
- cache_dir: cache_dir,
114
- development_mode: development_mode,
115
- load_path_cache: !ENV['DISABLE_BOOTSNAP_LOAD_PATH_CACHE'],
116
- compile_cache_iseq: !ENV['DISABLE_BOOTSNAP_COMPILE_CACHE'] && iseq_cache_supported?,
117
- compile_cache_yaml: !ENV['DISABLE_BOOTSNAP_COMPILE_CACHE'],
118
- compile_cache_json: !ENV['DISABLE_BOOTSNAP_COMPILE_CACHE'],
119
- )
120
-
121
- if ENV['BOOTSNAP_LOG']
122
- log!
117
+ if RbConfig::CONFIG["host_os"] =~ /mswin|mingw|cygwin/
118
+ def absolute_path?(path)
119
+ path[1] == ":"
120
+ end
121
+ else
122
+ def absolute_path?(path)
123
+ path.start_with?("/")
123
124
  end
124
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
125
137
  end
126
138
  end
metadata CHANGED
@@ -1,99 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bootsnap
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.9.1
4
+ version: 1.16.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Burke Libbey
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-09-20 00:00:00.000000000 Z
11
+ date: 2023-01-25 00:00:00.000000000 Z
12
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: '0'
34
- type: :development
35
- prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - ">="
39
- - !ruby/object:Gem::Version
40
- version: '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
13
  - !ruby/object:Gem::Dependency
84
14
  name: msgpack
85
15
  requirement: !ruby/object:Gem::Requirement
86
16
  requirements:
87
17
  - - "~>"
88
18
  - !ruby/object:Gem::Version
89
- version: '1.0'
19
+ version: '1.2'
90
20
  type: :runtime
91
21
  prerelease: false
92
22
  version_requirements: !ruby/object:Gem::Requirement
93
23
  requirements:
94
24
  - - "~>"
95
25
  - !ruby/object:Gem::Version
96
- version: '1.0'
26
+ version: '1.2'
97
27
  description: Boot large ruby/rails apps faster
98
28
  email:
99
29
  - burke.libbey@shopify.com
@@ -127,7 +57,6 @@ files:
127
57
  - lib/bootsnap/load_path_cache/loaded_features_index.rb
128
58
  - lib/bootsnap/load_path_cache/path.rb
129
59
  - lib/bootsnap/load_path_cache/path_scanner.rb
130
- - lib/bootsnap/load_path_cache/realpath_cache.rb
131
60
  - lib/bootsnap/load_path_cache/store.rb
132
61
  - lib/bootsnap/setup.rb
133
62
  - lib/bootsnap/version.rb
@@ -136,7 +65,7 @@ licenses:
136
65
  - MIT
137
66
  metadata:
138
67
  bug_tracker_uri: https://github.com/Shopify/bootsnap/issues
139
- changelog_uri: https://github.com/Shopify/bootsnap/blob/master/CHANGELOG.md
68
+ changelog_uri: https://github.com/Shopify/bootsnap/blob/main/CHANGELOG.md
140
69
  source_code_uri: https://github.com/Shopify/bootsnap
141
70
  allowed_push_host: https://rubygems.org
142
71
  post_install_message:
@@ -147,14 +76,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
147
76
  requirements:
148
77
  - - ">="
149
78
  - !ruby/object:Gem::Version
150
- version: 2.3.0
79
+ version: 2.6.0
151
80
  required_rubygems_version: !ruby/object:Gem::Requirement
152
81
  requirements:
153
82
  - - ">="
154
83
  - !ruby/object:Gem::Version
155
84
  version: '0'
156
85
  requirements: []
157
- rubygems_version: 3.2.20
86
+ rubygems_version: 3.3.3
158
87
  signing_key:
159
88
  specification_version: 4
160
89
  summary: Boot large ruby/rails apps faster
@@ -1,32 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Bootsnap
4
- module LoadPathCache
5
- class RealpathCache
6
- def initialize
7
- @cache = Hash.new { |h, k| h[k] = realpath(*k) }
8
- end
9
-
10
- def call(*key)
11
- @cache[key]
12
- end
13
-
14
- private
15
-
16
- def realpath(caller_location, path)
17
- base = File.dirname(caller_location)
18
- abspath = File.expand_path(path, base).freeze
19
- find_file(abspath)
20
- end
21
-
22
- def find_file(name)
23
- return File.realpath(name).freeze if File.exist?(name)
24
- CACHED_EXTENSIONS.each do |ext|
25
- filename = "#{name}#{ext}"
26
- return File.realpath(filename).freeze if File.exist?(filename)
27
- end
28
- name
29
- end
30
- end
31
- end
32
- end