[rubygems/rubygems] Let gem exec raise an error in ambiguous cases

When `gem exec foo` is run, and "foo" is a gem that has multiple
executables, none of them named "foo", raise an error explaining the
situation and telling user to be more specific.

Currently the first command in the executables array is run, but this
may come as surprising sometimes, so better raise an error.

https://github.com/rubygems/rubygems/commit/acda5d8f6e
This commit is contained in:
David Rodríguez 2025-03-17 20:10:17 +01:00 committed by Hiroshi SHIBATA
parent ee7cfb1d1e
commit 4fe882e2c9
Notes: git 2025-03-24 04:25:31 +00:00
2 changed files with 20 additions and 8 deletions

View File

@ -195,7 +195,7 @@ to the same gem path as user-installed gems.
argv = ARGV.clone
ARGV.replace options[:args]
exe = executable = options[:executable]
executable = options[:executable]
contains_executable = Gem.loaded_specs.values.select do |spec|
spec.executables.include?(executable)
@ -206,13 +206,22 @@ to the same gem path as user-installed gems.
end
if contains_executable.empty?
if (spec = Gem.loaded_specs[executable]) && (exe = spec.executable)
contains_executable << spec
else
spec = Gem.loaded_specs[executable]
if spec.nil? || spec.executables.empty?
alert_error "Failed to load executable `#{executable}`," \
" are you sure the gem `#{options[:gem_name]}` contains it?"
terminate_interaction 1
end
if spec.executables.size > 1
alert_error "Ambiguous which executable from gem `#{executable}` should be run: " \
"the options are #{spec.executables}, specify one via COMMAND, and use `-g` and `-v` to specify gem and version"
terminate_interaction 1
end
contains_executable << spec
executable = spec.executable
end
if contains_executable.size > 1
@ -223,8 +232,8 @@ to the same gem path as user-installed gems.
end
old_exe = $0
$0 = exe
load Gem.activate_bin_path(contains_executable.first.name, exe, ">= 0.a")
$0 = executable
load Gem.activate_bin_path(contains_executable.first.name, executable, ">= 0.a")
ensure
$0 = old_exe if old_exe
ARGV.replace argv

View File

@ -370,8 +370,11 @@ class TestGemCommandsExecCommand < Gem::TestCase
util_clear_gems
use_ui @ui do
@cmd.invoke "a:2"
assert_equal "a-2 foo\n", @ui.output
e = assert_raise Gem::MockGemUi::TermError do
@cmd.invoke "a:2"
end
assert_equal 1, e.exit_code
assert_equal "ERROR: Ambiguous which executable from gem `a` should be run: the options are [\"foo\", \"bar\"], specify one via COMMAND, and use `-g` and `-v` to specify gem and version\n", @ui.error
end
end