Skip to content

Fix bundle binstub broken by gem update --system on Homebrew ruby#9688

Open
hsbt wants to merge 3 commits into
masterfrom
default-bundler-install-dir
Open

Fix bundle binstub broken by gem update --system on Homebrew ruby#9688
hsbt wants to merge 3 commits into
masterfrom
default-bundler-install-dir

Conversation

@hsbt

@hsbt hsbt commented Jul 14, 2026

Copy link
Copy Markdown
Member

On rubies where Gem.default_specifications_dir lives under a different root than Gem.default_dir, like Homebrew ruby, gem update --system wrote the new default bundler gemspec next to the previous one but extracted its executables under Gem.default_dir. Activating the default bundler then resolved an executable path that never existed, so the bundle binstub broke with a LoadError right after every RubyGems update until the user ran gem install bundler. This installs the executables and removes the previous default gem under the same root as the gemspec so the two stay together.

While fixing this I dropped a redundant second write of the default gemspec through the installer, and pointed the removal of a promoted same-version regular bundler gem at default_dir where regular gems actually live instead of at the default gemspec root.

Fixed #9685

hsbt and others added 3 commits July 14, 2026 09:55
`gem update --system` wrote the new default bundler gemspec next to the
previous one, but extracted its executables under `Gem.default_dir`. On
rubies where `Gem.default_specifications_dir` lives under a different
root than `Gem.default_dir`, like Homebrew ruby, activating the default
bundler then computes an executable path that does not exist, breaking
the `bundle` binstub. Extract the executables and remove the previous
default gem under the same root as the gemspec instead.

#9685

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The default gemspec is already written to the default specifications
directory before building the gem, so `installer.write_default_spec`
just wrote the same file a second time. Drop the redundant call and let
the installer only extract and generate the executables.
When a regular gem of the vendored bundler version was already
installed, its files were removed from the default gemspec's gems
directory instead of from default_dir. On rubies where those roots
differ, like Homebrew ruby, the regular gem files were left behind after
being promoted to the default gem. Remove them from default_dir, where
regular gems actually live.
Copilot AI review requested due to automatic review settings July 14, 2026 06:00

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes a RubyGems setup/gem update --system edge case where default Bundler gemspecs and extracted executables can end up under different roots (notably on Homebrew Ruby), causing bundle binstubs to fail with LoadError when activation resolves a non-existent executable path.

Changes:

  • Install Bundler executables under the same root as the default Bundler gemspec (derived from specs_dir) so Gem.activate_and_load_bin_path resolves a real path.
  • Correct removal of a promoted same-version regular Bundler gem to target default_dir (where regular gems live), not the default gemspec root.
  • Add a regression test simulating the Homebrew-style split-root layout and asserting both cleanup and executable placement.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
lib/rubygems/commands/setup_command.rb Align Bundler executable extraction directory with the default gemspec root; fix cleanup paths for prior default and promoted regular Bundler installs.
test/rubygems/test_gem_commands_setup_command.rb Adds coverage for split-root default gemspec vs default gem install layouts to prevent bundle binstub regressions.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

2 participants