From 1f43c7a9887fd0d3c75756f1c58e86b82aafdb8f Mon Sep 17 00:00:00 2001 From: lolwut Date: Thu, 25 Dec 2025 21:05:50 -0600 Subject: [PATCH 1/4] Compare like values in find_bundler The input to this method is not guaranteed to be a string, it could be a `Gem::Version` this normalizes the comparison. --- bundler/lib/bundler/rubygems_integration.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bundler/lib/bundler/rubygems_integration.rb b/bundler/lib/bundler/rubygems_integration.rb index d8f95cffb8fc..e04ef232592a 100644 --- a/bundler/lib/bundler/rubygems_integration.rb +++ b/bundler/lib/bundler/rubygems_integration.rb @@ -432,7 +432,7 @@ def default_specs end def find_bundler(version) - find_name("bundler").find {|s| s.version.to_s == version } + find_name("bundler").find {|s| s.version.to_s == version.to_s } end def find_name(name) From 5a6eca4cf9b34f4baa87329a591bf93cc9c99400 Mon Sep 17 00:00:00 2001 From: Schneems Date: Fri, 26 Dec 2025 12:21:51 -0600 Subject: [PATCH 2/4] Split logic to two lines --- bundler/lib/bundler/runtime.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/bundler/lib/bundler/runtime.rb b/bundler/lib/bundler/runtime.rb index 5eb827dcb2a8..f632ce9144ef 100644 --- a/bundler/lib/bundler/runtime.rb +++ b/bundler/lib/bundler/runtime.rb @@ -174,7 +174,8 @@ def clean(dry_run = false) spec_cache_paths = [] spec_gemspec_paths = [] spec_extension_paths = [] - Bundler.rubygems.add_default_gems_to(specs).values.each do |spec| + specs_to_keep = Bundler.rubygems.add_default_gems_to(specs).values + specs_to_keep.each do |spec| spec_gem_paths << spec.full_gem_path # need to check here in case gems are nested like for the rails git repo md = %r{(.+bundler/gems/.+-[a-f0-9]{7,12})}.match(spec.full_gem_path) From 675342e6d0ac40a3e65f1762da84f6bd7262e685 Mon Sep 17 00:00:00 2001 From: Schneems Date: Fri, 26 Dec 2025 12:21:51 -0600 Subject: [PATCH 3/4] Test for removing current bundler version --- bundler/spec/commands/clean_spec.rb | 37 +++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/bundler/spec/commands/clean_spec.rb b/bundler/spec/commands/clean_spec.rb index 6b678d0aa545..793aacf5c2b5 100644 --- a/bundler/spec/commands/clean_spec.rb +++ b/bundler/spec/commands/clean_spec.rb @@ -898,4 +898,41 @@ def should_not_have_gems(*gems) expect(very_simple_binary_extensions_dir).to be_nil end + + it "does not remove the bundler version currently running" do + gemfile <<-G + source "https://gem.repo1" + + gem "myrack" + G + + bundle "config set path vendor/bundle" + bundle "install" + + version = Bundler.gem_version.to_s + # Simulate that the locked bundler version is installed in the bundle path + # by creating the gem directory and gemspec (as would happen after bundle install with that version) + Pathname(vendored_gems("cache/bundler-#{version}.gem")).tap do |path| + path.basename.mkpath + FileUtils.touch(path) + end + FileUtils.touch(vendored_gems("gems/bundler-#{version}")) + Pathname(vendored_gems("specifications/bundler-#{version}.gemspec")).tap do |path| + path.basename.mkpath + path.write(<<~GEMSPEC) + Gem::Specification.new do |s| + s.name = "bundler" + s.version = "#{version}" + s.authors = ["bundler team"] + s.summary = "The best way to manage your application's dependencies" + end + GEMSPEC + end + + should_have_gems "bundler-#{version}" + + bundle :clean + + should_have_gems "bundler-#{version}" + end end From e3f0167ae4d6029d3b0b953493dafe704ea06e47 Mon Sep 17 00:00:00 2001 From: Schneems Date: Fri, 26 Dec 2025 12:21:51 -0600 Subject: [PATCH 4/4] Retain current bundler version on `bundle clean` Previously: In #9218 a reproduction is shared where running `bundle clean` using a binstub (`bin/bundle`) results in bundler removing itself. This results in Ruby falling back to its default bundler version. This behavior seems to be present for as long as there has been a default version of bundler (Ruby 2.6+). Now: Bundler will explicitly add its current version number to the specs to be preserved. This prevents `bundle clean` from removing the current bundler version. close #9218 --- bundler/lib/bundler/runtime.rb | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/bundler/lib/bundler/runtime.rb b/bundler/lib/bundler/runtime.rb index f632ce9144ef..5280e72aa24b 100644 --- a/bundler/lib/bundler/runtime.rb +++ b/bundler/lib/bundler/runtime.rb @@ -175,6 +175,12 @@ def clean(dry_run = false) spec_gemspec_paths = [] spec_extension_paths = [] specs_to_keep = Bundler.rubygems.add_default_gems_to(specs).values + + current_bundler = Bundler.rubygems.find_bundler(Bundler.gem_version) + if current_bundler + specs_to_keep << current_bundler + end + specs_to_keep.each do |spec| spec_gem_paths << spec.full_gem_path # need to check here in case gems are nested like for the rails git repo