Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions lib/rubygems.rb
Original file line number Diff line number Diff line change
Expand Up @@ -193,11 +193,12 @@ def self.try_activate(path)
begin
spec.activate
rescue Gem::LoadError => e # this could fail due to gem dep collisions, go lax
spec_by_name = Gem::Specification.find_by_name(spec.name)
if spec_by_name.nil?
spec = Gem::Specification.find_unloaded_by_path(path)
spec ||= Gem::Specification.find_by_name(spec.name)
if spec.nil?
raise e
else
spec_by_name.activate
spec.activate
end
end

Expand Down
9 changes: 9 additions & 0 deletions lib/rubygems/specification.rb
Original file line number Diff line number Diff line change
Expand Up @@ -958,6 +958,15 @@ def self.find_by_path(path)
specification_record.find_by_path(path)
end

##
# Return the best specification that contains the file matching +path+
# amongst the specs that are not loaded. This method is different than
# +find_inactive_by_path+ as it will filter out loaded specs by their name.

def self.find_unloaded_by_path(path)
specification_record.find_unloaded_by_path(path)
end

##
# Return the best specification that contains the file matching +path+
# amongst the specs that are not activated.
Expand Down
13 changes: 13 additions & 0 deletions lib/rubygems/specification_record.rb
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,19 @@ def find_by_path(path)
spec.to_spec
end

##
# Return the best specification that contains the file matching +path+
# amongst the specs that are not loaded. This method is different than
# +find_inactive_by_path+ as it will filter out loaded specs by their name.

def find_unloaded_by_path(path)
stub = stubs.find do |s|
next if Gem.loaded_specs[s.name]
s.contains_requirable_file? path
end
stub&.to_spec
end

##
# Return the best specification in the record that contains the file
# matching +path+ amongst the specs that are not activated.
Expand Down
16 changes: 16 additions & 0 deletions test/rubygems/test_require.rb
Original file line number Diff line number Diff line change
Expand Up @@ -431,6 +431,22 @@ def test_default_gem_only
assert_equal %w[default-2.0.0.0], loaded_spec_names
end

def test_multiple_gems_with_the_same_path_the_non_activated_spec_is_chosen
a1 = util_spec "a", "1", nil, "lib/ib.rb"
a2 = util_spec "a", "2", nil, "lib/foo.rb"
b1 = util_spec "b", "1", nil, "lib/ib.rb"

install_specs a1, a2, b1

a2.activate

assert_equal %w[a-2], loaded_spec_names
assert_empty unresolved_names

assert_require "ib"
assert_equal %w[a-2 b-1], loaded_spec_names
end

def test_default_gem_require_activates_just_once
default_gem_spec = new_default_spec("default", "2.0.0.0",
nil, "default/gem.rb")
Expand Down