Skip to content

Commit 94c7870

Browse files
Merge pull request #7379 from rubygems/fix-require-issue
Fix `require` activation conflicts when requiring default gems under some situations (cherry picked from commit 271c922)
1 parent 26469e1 commit 94c7870

File tree

3 files changed

+77
-2
lines changed

3 files changed

+77
-2
lines changed

lib/rubygems.rb

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1216,6 +1216,13 @@ def register_default_spec(spec)
12161216
##
12171217
# Find a Gem::Specification of default gem from +path+
12181218

1219+
def find_default_spec(path)
1220+
@path_to_default_spec_map[path]
1221+
end
1222+
1223+
##
1224+
# Find an unresolved Gem::Specification of default gem from +path+
1225+
12191226
def find_unresolved_default_spec(path)
12201227
default_spec = @path_to_default_spec_map[path]
12211228
return default_spec if default_spec && loaded_specs[default_spec.name] != default_spec

lib/rubygems/core_ext/kernel_require.rb

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,14 @@ def require(path) # :doc:
3939
RUBYGEMS_ACTIVATION_MONITOR.synchronize do
4040
path = File.path(path)
4141

42-
if spec = Gem.find_unresolved_default_spec(path)
42+
# If +path+ belongs to a default gem, we activate it and then go straight
43+
# to normal require
44+
45+
if spec = Gem.find_default_spec(path)
46+
name = spec.name
47+
48+
next if Gem.loaded_specs[name]
49+
4350
# Ensure -I beats a default gem
4451
resolved_path = begin
4552
rp = nil
@@ -57,8 +64,10 @@ def require(path) # :doc:
5764
rp
5865
end
5966

60-
Kernel.send(:gem, spec.name, Gem::Requirement.default_prerelease) unless
67+
Kernel.send(:gem, name, Gem::Requirement.default_prerelease) unless
6168
resolved_path
69+
70+
next
6271
end
6372

6473
# If there are no unresolved deps, then we can use just try

test/rubygems/test_require.rb

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -529,6 +529,65 @@ def test_default_gem_prerelease
529529
assert_equal %w[default-3.0.0.rc2], loaded_spec_names
530530
end
531531

532+
def test_default_gem_with_unresolved_gems_depending_on_it
533+
net_http_old = util_spec "net-http", "0.1.1", nil, "lib/net/http.rb"
534+
install_gem net_http_old
535+
536+
net_http_default = new_default_spec "net-http", "0.3.0", nil, "net/http.rb"
537+
install_default_gems net_http_default
538+
539+
faraday_1 = util_spec "faraday", "1", { "net-http" => ">= 0" }
540+
install_gem faraday_1
541+
542+
faraday_2 = util_spec "faraday", "2", { "net-http" => ">= 0" }
543+
install_gem faraday_2
544+
545+
chef = util_spec "chef", "1", { "faraday" => [">= 1", "< 3"] }, "lib/chef.rb"
546+
install_gem chef
547+
548+
assert_require "chef"
549+
assert_require "net/http"
550+
end
551+
552+
def test_default_gem_required_circulary_with_unresolved_gems_depending_on_it
553+
net_http_old = util_spec "net-http", "0.1.1", nil, "lib/net/http.rb"
554+
install_gem net_http_old
555+
556+
net_http_default = new_default_spec "net-http", "0.3.0", nil, "net/http.rb"
557+
net_http_default_path = File.join(@tempdir, "default_gems", "lib", "net/http.rb")
558+
install_default_gems net_http_default
559+
File.write(net_http_default_path, 'require "net/http"')
560+
561+
faraday_1 = util_spec "faraday", "1", { "net-http" => ">= 0" }
562+
install_gem faraday_1
563+
564+
faraday_2 = util_spec "faraday", "2", { "net-http" => ">= 0" }
565+
install_gem faraday_2
566+
567+
chef = util_spec "chef", "1", { "faraday" => [">= 1", "< 3"] }, "lib/chef.rb"
568+
install_gem chef
569+
570+
assert_require "chef"
571+
572+
out, err = capture_output do
573+
assert_require "net/http"
574+
end
575+
576+
assert_empty out
577+
578+
circular_require_warning = false
579+
580+
err_lines = err.split("\n").reject do |line|
581+
if line.include?("circular require")
582+
circular_require_warning = true
583+
elsif circular_require_warning # ignore backtrace lines for circular require warning
584+
circular_require_warning = line.start_with?(/[\s]/)
585+
end
586+
end
587+
588+
assert_empty err_lines
589+
end
590+
532591
def loaded_spec_names
533592
Gem.loaded_specs.values.map(&:full_name).sort
534593
end

0 commit comments

Comments
 (0)