bootsnap 1.4.8 → 1.16.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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,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, :autoload_paths_cache,
32
- :loaded_features_index, :realpath_cache)
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:, active_support: true)
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
- require_relative('load_path_cache/core_ext/kernel_require')
47
- 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
48
47
 
49
- if active_support
50
- # this should happen after setting up the initial cache because it
51
- # loads a lot of code. It's better to do after +require+ is optimized.
52
- require('active_support/dependencies')
53
- @autoload_paths_cache = Cache.new(
54
- store,
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 == 'ruby' &&
64
- RUBY_PLATFORM =~ /darwin|linux|bsd/
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('load_path_cache/path_scanner')
72
- require_relative('load_path_cache/path')
73
- require_relative('load_path_cache/cache')
74
- require_relative('load_path_cache/store')
75
- require_relative('load_path_cache/change_observer')
76
- require_relative('load_path_cache/loaded_features_index')
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
@@ -1,39 +1,5 @@
1
1
  # frozen_string_literal: true
2
- require_relative('../bootsnap')
3
2
 
4
- env = ENV['RAILS_ENV'] || ENV['RACK_ENV'] || ENV['ENV']
5
- development_mode = ['', nil, 'development'].include?(env)
3
+ require_relative("../bootsnap")
6
4
 
7
- cache_dir = ENV['BOOTSNAP_CACHE_DIR']
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
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Bootsnap
3
- VERSION = "1.4.8"
4
+ VERSION = "1.16.0"
4
5
  end
data/lib/bootsnap.rb CHANGED
@@ -1,49 +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
- def self.setup(
12
- cache_dir:,
13
- development_mode: true,
14
- load_path_cache: true,
15
- autoload_paths_cache: true,
16
- disable_trace: false,
17
- compile_cache_iseq: true,
18
- compile_cache_yaml: true
19
- )
20
- if autoload_paths_cache && !load_path_cache
21
- raise(InvalidConfiguration, "feature 'autoload_paths_cache' depends on feature 'load_path_cache'")
22
- end
23
-
24
- setup_disable_trace if disable_trace
25
-
26
- Bootsnap::LoadPathCache.setup(
27
- cache_path: cache_dir + '/bootsnap-load-path-cache',
28
- development_mode: development_mode,
29
- active_support: autoload_paths_cache
30
- ) if load_path_cache
31
-
32
- Bootsnap::CompileCache.setup(
33
- cache_dir: cache_dir + '/bootsnap-compile-cache',
34
- iseq: compile_cache_iseq,
35
- yaml: compile_cache_yaml
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
- end
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
- def self.setup_disable_trace
40
- if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('2.5.0')
41
- warn(
42
- "from #{caller_locations(1, 1)[0]}: The 'disable_trace' method is not allowed with this Ruby version. " \
43
- "current: #{RUBY_VERSION}, allowed version: < 2.5.0",
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
- RubyVM::InstructionSequence.compile_option = { trace_instruction: false }
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
metadata CHANGED
@@ -1,103 +1,34 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bootsnap
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.8
4
+ version: 1.16.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Burke Libbey
8
8
  autorequire:
9
- bindir: bin
9
+ bindir: exe
10
10
  cert_chain: []
11
- date: 2020-08-11 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
100
- executables: []
30
+ executables:
31
+ - bootsnap
101
32
  extensions:
102
33
  - ext/bootsnap/extconf.rb
103
34
  extra_rdoc_files: []
@@ -105,25 +36,27 @@ files:
105
36
  - CHANGELOG.md
106
37
  - LICENSE.txt
107
38
  - README.md
39
+ - exe/bootsnap
108
40
  - ext/bootsnap/bootsnap.c
109
41
  - ext/bootsnap/bootsnap.h
110
42
  - ext/bootsnap/extconf.rb
111
43
  - lib/bootsnap.rb
112
44
  - lib/bootsnap/bundler.rb
45
+ - lib/bootsnap/cli.rb
46
+ - lib/bootsnap/cli/worker_pool.rb
113
47
  - lib/bootsnap/compile_cache.rb
114
48
  - lib/bootsnap/compile_cache/iseq.rb
49
+ - lib/bootsnap/compile_cache/json.rb
115
50
  - lib/bootsnap/compile_cache/yaml.rb
116
51
  - lib/bootsnap/explicit_require.rb
117
52
  - lib/bootsnap/load_path_cache.rb
118
53
  - lib/bootsnap/load_path_cache/cache.rb
119
54
  - lib/bootsnap/load_path_cache/change_observer.rb
120
- - lib/bootsnap/load_path_cache/core_ext/active_support.rb
121
55
  - lib/bootsnap/load_path_cache/core_ext/kernel_require.rb
122
56
  - lib/bootsnap/load_path_cache/core_ext/loaded_features.rb
123
57
  - lib/bootsnap/load_path_cache/loaded_features_index.rb
124
58
  - lib/bootsnap/load_path_cache/path.rb
125
59
  - lib/bootsnap/load_path_cache/path_scanner.rb
126
- - lib/bootsnap/load_path_cache/realpath_cache.rb
127
60
  - lib/bootsnap/load_path_cache/store.rb
128
61
  - lib/bootsnap/setup.rb
129
62
  - lib/bootsnap/version.rb
@@ -132,8 +65,9 @@ licenses:
132
65
  - MIT
133
66
  metadata:
134
67
  bug_tracker_uri: https://github.com/Shopify/bootsnap/issues
135
- changelog_uri: https://github.com/Shopify/bootsnap/blob/master/CHANGELOG.md
68
+ changelog_uri: https://github.com/Shopify/bootsnap/blob/main/CHANGELOG.md
136
69
  source_code_uri: https://github.com/Shopify/bootsnap
70
+ allowed_push_host: https://rubygems.org
137
71
  post_install_message:
138
72
  rdoc_options: []
139
73
  require_paths:
@@ -142,14 +76,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
142
76
  requirements:
143
77
  - - ">="
144
78
  - !ruby/object:Gem::Version
145
- version: 2.3.0
79
+ version: 2.6.0
146
80
  required_rubygems_version: !ruby/object:Gem::Requirement
147
81
  requirements:
148
82
  - - ">="
149
83
  - !ruby/object:Gem::Version
150
84
  version: '0'
151
85
  requirements: []
152
- rubygems_version: 3.0.2
86
+ rubygems_version: 3.3.3
153
87
  signing_key:
154
88
  specification_version: 4
155
89
  summary: Boot large ruby/rails apps faster
@@ -1,107 +0,0 @@
1
- # frozen_string_literal: true
2
- module Bootsnap
3
- module LoadPathCache
4
- module CoreExt
5
- module ActiveSupport
6
- def self.without_bootsnap_cache
7
- prev = Thread.current[:without_bootsnap_cache] || false
8
- Thread.current[:without_bootsnap_cache] = true
9
- yield
10
- ensure
11
- Thread.current[:without_bootsnap_cache] = prev
12
- end
13
-
14
- def self.allow_bootsnap_retry(allowed)
15
- prev = Thread.current[:without_bootsnap_retry] || false
16
- Thread.current[:without_bootsnap_retry] = !allowed
17
- yield
18
- ensure
19
- Thread.current[:without_bootsnap_retry] = prev
20
- end
21
-
22
- module ClassMethods
23
- def autoload_paths=(o)
24
- super
25
- Bootsnap::LoadPathCache.autoload_paths_cache.reinitialize(o)
26
- end
27
-
28
- def search_for_file(path)
29
- return super if Thread.current[:without_bootsnap_cache]
30
- begin
31
- Bootsnap::LoadPathCache.autoload_paths_cache.find(path)
32
- rescue Bootsnap::LoadPathCache::ReturnFalse
33
- nil # doesn't really apply here
34
- rescue Bootsnap::LoadPathCache::FallbackScan
35
- nil # doesn't really apply here
36
- end
37
- end
38
-
39
- def autoloadable_module?(path_suffix)
40
- Bootsnap::LoadPathCache.autoload_paths_cache.load_dir(path_suffix)
41
- end
42
-
43
- def remove_constant(const)
44
- CoreExt::ActiveSupport.without_bootsnap_cache { super }
45
- end
46
-
47
- def require_or_load(*)
48
- CoreExt::ActiveSupport.allow_bootsnap_retry(true) do
49
- super
50
- end
51
- end
52
-
53
- # If we can't find a constant using the patched implementation of
54
- # search_for_file, try again with the default implementation.
55
- #
56
- # These methods call search_for_file, and we want to modify its
57
- # behaviour. The gymnastics here are a bit awkward, but it prevents
58
- # 200+ lines of monkeypatches.
59
- def load_missing_constant(from_mod, const_name)
60
- CoreExt::ActiveSupport.allow_bootsnap_retry(false) do
61
- super
62
- end
63
- rescue NameError => e
64
- raise(e) if e.instance_variable_defined?(Bootsnap::LoadPathCache::ERROR_TAG_IVAR)
65
- e.instance_variable_set(Bootsnap::LoadPathCache::ERROR_TAG_IVAR, true)
66
-
67
- # This function can end up called recursively, we only want to
68
- # retry at the top-level.
69
- raise(e) if Thread.current[:without_bootsnap_retry]
70
- # If we already had cache disabled, there's no use retrying
71
- raise(e) if Thread.current[:without_bootsnap_cache]
72
- # NoMethodError is a NameError, but we only want to handle actual
73
- # NameError instances.
74
- raise(e) unless e.class == NameError
75
- # We can only confidently handle cases when *this* constant fails
76
- # to load, not other constants referred to by it.
77
- raise(e) unless e.name == const_name
78
- # If the constant was actually loaded, something else went wrong?
79
- raise(e) if from_mod.const_defined?(const_name)
80
- CoreExt::ActiveSupport.without_bootsnap_cache { super }
81
- end
82
-
83
- # Signature has changed a few times over the years; easiest to not
84
- # reiterate it with version polymorphism here...
85
- def depend_on(*)
86
- super
87
- rescue LoadError => e
88
- raise(e) if e.instance_variable_defined?(Bootsnap::LoadPathCache::ERROR_TAG_IVAR)
89
- e.instance_variable_set(Bootsnap::LoadPathCache::ERROR_TAG_IVAR, true)
90
-
91
- # If we already had cache disabled, there's no use retrying
92
- raise(e) if Thread.current[:without_bootsnap_cache]
93
- CoreExt::ActiveSupport.without_bootsnap_cache { super }
94
- end
95
- end
96
- end
97
- end
98
- end
99
- end
100
-
101
- module ActiveSupport
102
- module Dependencies
103
- class << self
104
- prepend(Bootsnap::LoadPathCache::CoreExt::ActiveSupport::ClassMethods)
105
- end
106
- end
107
- end
@@ -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