From 98beabd66687b741cd2d72d7e0517ae23100d2ff Mon Sep 17 00:00:00 2001 From: Earlopain <14981592+Earlopain@users.noreply.github.com> Date: Wed, 10 Sep 2025 13:18:36 +0200 Subject: [PATCH] [rubygems/rubygems] Fix outdated lockfile during `bundle lock` when source changes When the source used to be git and switches back to rubygems, it is possible that the git source contains a version that ruybgems doesn't know about yet. So don't add the locked spec to the base resolve, and also don't add a lower bound requirement on the version, since the version in the new source may actually be lower. https://github.com/rubygems/rubygems/commit/85514e3a1e --- lib/bundler/definition.rb | 3 ++- spec/bundler/lock/git_spec.rb | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/lib/bundler/definition.rb b/lib/bundler/definition.rb index 8b1e082ae9..e177b6e396 100644 --- a/lib/bundler/definition.rb +++ b/lib/bundler/definition.rb @@ -1051,6 +1051,7 @@ module Bundler # Replace the locked dependency's source with the equivalent source from the Gemfile s.source = replacement_source || default_source + next if s.source_changed? source = s.source next if @sources_to_unlock.include?(source.name) @@ -1138,7 +1139,7 @@ module Bundler def additional_base_requirements_to_prevent_downgrades(resolution_base) return resolution_base unless @locked_gems && !sources.expired_sources?(@locked_gems.sources) @originally_locked_specs.each do |locked_spec| - next if locked_spec.source.is_a?(Source::Path) + next if locked_spec.source.is_a?(Source::Path) || locked_spec.source_changed? name = locked_spec.name next if @changed_dependencies.include?(name) diff --git a/spec/bundler/lock/git_spec.rb b/spec/bundler/lock/git_spec.rb index 49c0a2af1c..4e41651830 100644 --- a/spec/bundler/lock/git_spec.rb +++ b/spec/bundler/lock/git_spec.rb @@ -220,4 +220,39 @@ RSpec.describe "bundle lock with git gems" do expect(lockfile).to include("securerandom (0.3.2)") end + + it "does not lock versions that don't exist in the repository when changing a GIT direct dep to a GEM direct dep" do + build_repo4 do + build_gem "ruby-lsp", "0.16.1" + end + + path = lib_path("ruby-lsp") + revision = build_git("ruby-lsp", "0.16.2", path: path).ref_for("HEAD") + + lockfile <<~L + GIT + remote: #{path} + revision: #{revision} + specs: + ruby-lsp (0.16.2) + + PLATFORMS + #{lockfile_platforms} + + DEPENDENCIES + ruby-lsp! + + BUNDLED WITH + #{Bundler::VERSION} + L + + gemfile <<~G + source "https://gem.repo4" + gem "ruby-lsp" + G + + bundle "lock" + + expect(lockfile).to include("ruby-lsp (0.16.1)") + end end