Skip to content

Commit 190375e

Browse files
committed
Get rid of RealPathCache and the Kernel.require_relative decorator
It was added in #136 to handle a very specific scenario: ``` /app/lib/ - real directory /symlink/ - symlink to /app/ ```
1 parent 970e178 commit 190375e

8 files changed

Lines changed: 146 additions & 144 deletions

File tree

lib/bootsnap/load_path_cache.rb

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ module LoadPathCache
2222
CACHED_EXTENSIONS = DLEXT2 ? [DOT_RB, DLEXT, DLEXT2] : [DOT_RB, DLEXT]
2323

2424
class << self
25-
attr_reader(:load_path_cache, :loaded_features_index, :realpath_cache)
25+
attr_reader(:load_path_cache, :loaded_features_index)
2626

2727
def setup(cache_path:, development_mode:)
2828
unless supported?
@@ -33,7 +33,6 @@ def setup(cache_path:, development_mode:)
3333
store = Store.new(cache_path)
3434

3535
@loaded_features_index = LoadedFeaturesIndex.new
36-
@realpath_cache = RealpathCache.new
3736

3837
@load_path_cache = Cache.new(store, $LOAD_PATH, development_mode: development_mode)
3938
require_relative("load_path_cache/core_ext/kernel_require")
@@ -55,5 +54,4 @@ def supported?
5554
require_relative("load_path_cache/store")
5655
require_relative("load_path_cache/change_observer")
5756
require_relative("load_path_cache/loaded_features_index")
58-
require_relative("load_path_cache/realpath_cache")
5957
end

lib/bootsnap/load_path_cache/core_ext/kernel_require.rb

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -33,15 +33,6 @@ def require(path)
3333
end
3434
end
3535

36-
alias_method(:require_relative_without_bootsnap, :require_relative)
37-
def require_relative(path)
38-
location = caller_locations(1..1).first
39-
realpath = Bootsnap::LoadPathCache.realpath_cache.call(
40-
location.absolute_path || location.path, path
41-
)
42-
require(realpath)
43-
end
44-
4536
alias_method(:load_without_bootsnap, :load)
4637
def load(path, wrap = false)
4738
if (resolved = Bootsnap::LoadPathCache.load_path_cache.find(path, try_extensions: false))

lib/bootsnap/load_path_cache/path.rb

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,11 @@ def entries_and_dirs(store)
6262
end
6363

6464
def expanded_path
65-
File.expand_path(path).freeze
65+
@expanded_path ||= begin
66+
File.realpath(path).freeze
67+
rescue Errno::ENOENT
68+
File.expand_path(path).freeze
69+
end
6670
end
6771

6872
private

lib/bootsnap/load_path_cache/realpath_cache.rb

Lines changed: 0 additions & 33 deletions
This file was deleted.

test/integration/kernel_test.rb

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
# frozen_string_literal: true
2+
3+
require("test_helper")
4+
5+
module Bootsnap
6+
class KernelTest < Minitest::Test
7+
include TmpdirHelper
8+
9+
def test_require_symlinked_file_twice
10+
setup_symlinked_files
11+
if RUBY_VERSION >= "3.1"
12+
# Fixed in https://github.com/ruby/ruby/commit/79a4484a072e9769b603e7b4fbdb15b1d7eccb15 (Ruby 3.1)
13+
assert_both_pass(<<~RUBY)
14+
require "b/test.rb"
15+
require "a/test.rb"
16+
RUBY
17+
else
18+
assert_both_pass(<<~RUBY)
19+
require "b/test.rb"
20+
begin
21+
require "a/test.rb"
22+
rescue RuntimeError
23+
exit 0
24+
else
25+
exit 1
26+
end
27+
RUBY
28+
end
29+
end
30+
31+
def test_require_symlinked_file_twice_aliased
32+
setup_symlinked_files
33+
assert_both_pass(<<~RUBY)
34+
$LOAD_PATH.unshift(File.expand_path("b"))
35+
require "test.rb"
36+
37+
$LOAD_PATH.unshift(File.expand_path("a"))
38+
require "test.rb"
39+
RUBY
40+
end
41+
42+
def test_require_relative_symlinked_file_twice
43+
setup_symlinked_files
44+
if RUBY_VERSION >= "3.1"
45+
# Fixed in https://github.com/ruby/ruby/commit/79a4484a072e9769b603e7b4fbdb15b1d7eccb15 (Ruby 3.1)
46+
assert_both_pass(<<~RUBY)
47+
require_relative "b/test.rb"
48+
require_relative "a/test.rb"
49+
RUBY
50+
else
51+
assert_both_pass(<<~RUBY)
52+
require_relative "b/test.rb"
53+
begin
54+
require_relative "a/test.rb"
55+
rescue RuntimeError
56+
exit 0
57+
else
58+
exit 1
59+
end
60+
RUBY
61+
end
62+
end
63+
64+
def test_require_and_then_require_relative_symlinked_file
65+
setup_symlinked_files
66+
assert_both_pass(<<~RUBY)
67+
$LOAD_PATH.unshift(File.expand_path("b"))
68+
require "test"
69+
70+
require_relative "a/test.rb"
71+
RUBY
72+
end
73+
74+
def test_require_relative_and_then_require_symlinked_file
75+
setup_symlinked_files
76+
assert_both_pass(<<~RUBY)
77+
require_relative "a/test.rb"
78+
79+
$LOAD_PATH.unshift(File.expand_path("b"))
80+
require "test"
81+
RUBY
82+
end
83+
84+
private
85+
86+
def assert_both_pass(source)
87+
Help.set_file("without_bootsnap.rb", source)
88+
unless execute("without_bootsnap.rb", "debug.txt")
89+
flunk "expected snippet to pass WITHOUT bootsnap enabled:\n#{debug_output}"
90+
end
91+
92+
Help.set_file("with_bootsnap.rb", %{require "bootsnap/setup"\n#{source}})
93+
unless execute("with_bootsnap.rb", "debug.txt")
94+
flunk "expected snippet to pass WITH bootsnap enabled:\n#{debug_output}"
95+
end
96+
end
97+
98+
def debug_output
99+
File.read("debug.txt")
100+
rescue Errno::ENOENT
101+
end
102+
103+
def execute(script_path, output_path)
104+
system(
105+
{"BOOTSNAP_CACHE_DIR" => "tmp/cache"},
106+
RbConfig.ruby, "-I.", script_path,
107+
out: output_path, err: output_path
108+
)
109+
end
110+
111+
def assert_successful(source)
112+
Help.set_file("test_case.rb", source)
113+
114+
Help.set_file("test_case.rb", %{require "bootsnap/setup"\n#{source}})
115+
assert system({"BOOTSNAP_CACHE_DIR" => "tmp/cache"}, RbConfig.ruby, "-I.", "test_case.rb")
116+
end
117+
118+
def setup_symlinked_files
119+
skip("Platform doesn't support symlinks") unless File.respond_to?(:symlink)
120+
121+
Help.set_file("a/test.rb", <<-RUBY)
122+
if $already_required
123+
raise "required more than once"
124+
else
125+
$already_required = true
126+
end
127+
RUBY
128+
File.symlink("a", "b")
129+
end
130+
end
131+
end

test/load_path_cache/path_test.rb

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ def test_volatile_cache_valid_when_mtime_has_not_changed
5555
entries, dirs = PathScanner.call(dir)
5656
path = Path.new(dir) # volatile, since it'll be in /tmp
5757

58-
@cache.expects(:get).with(dir).returns([100, entries, dirs])
58+
@cache.expects(:get).with(path.expanded_path).returns([100, entries, dirs])
5959

6060
path.entries_and_dirs(@cache)
6161
end
@@ -68,11 +68,11 @@ def test_volatile_cache_invalid_when_mtime_changed
6868

6969
FileUtils.touch(a_b, mtime: Time.at(101))
7070

71-
@cache.expects(:get).with(dir).returns([100, entries, dirs])
72-
@cache.expects(:set).with(dir, [101, entries, dirs])
71+
@cache.expects(:get).with(path.expanded_path).returns([100, entries, dirs])
72+
@cache.expects(:set).with(path.expanded_path, [101, entries, dirs])
7373

7474
# next read doesn't regen
75-
@cache.expects(:get).with(dir).returns([101, entries, dirs])
75+
@cache.expects(:get).with(path.expanded_path).returns([101, entries, dirs])
7676

7777
path.entries_and_dirs(@cache)
7878
path.entries_and_dirs(@cache)
@@ -84,8 +84,8 @@ def test_volatile_cache_generated_when_missing
8484
entries, dirs = PathScanner.call(dir)
8585
path = Path.new(dir) # volatile, since it'll be in /tmp
8686

87-
@cache.expects(:get).with(dir).returns(nil)
88-
@cache.expects(:set).with(dir, [100, entries, dirs])
87+
@cache.expects(:get).with(path.expanded_path).returns(nil)
88+
@cache.expects(:set).with(path.expanded_path, [100, entries, dirs])
8989

9090
path.entries_and_dirs(@cache)
9191
end
@@ -101,7 +101,7 @@ def test_stable_cache_does_not_notice_when_mtime_changes
101101

102102
# It's unfortunate that we're stubbing the impl of #fetch here.
103103
PathScanner.expects(:call).never
104-
@cache.expects(:get).with(dir).returns([100, entries, dirs])
104+
@cache.expects(:get).with(path.expanded_path).returns([100, entries, dirs])
105105

106106
path.entries_and_dirs(@cache)
107107
end

test/load_path_cache/realpath_cache_test.rb

Lines changed: 0 additions & 89 deletions
This file was deleted.

test/test_helper.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,10 +81,10 @@ def fnv1a_64(data)
8181
hash
8282
end
8383

84-
def set_file(path, contents, mtime)
84+
def set_file(path, contents, mtime = nil)
8585
FileUtils.mkdir_p(File.dirname(path))
8686
File.write(path, contents)
87-
FileUtils.touch(path, mtime: mtime)
87+
FileUtils.touch(path, mtime: mtime) if mtime
8888
path
8989
end
9090
end

0 commit comments

Comments
 (0)