[rubygems/rubygems] Fix incorrect error message in frozen mode

When Bundler refuses to install in frozen mode, sometimes it would
incorrectly claim that some dependencies have been added to the Gemfile
when that's not really the case. Fix that by making sure
`locked_dependencies` always has all locked dependencies, even when
unlocking,

Additionally, the suggestion to run `bundle install` is also confusing
when unlocking, since `bundle update` is what has been run. So skip that
part as well when unlocking.

https://github.com/rubygems/rubygems/commit/64d84ad7d8
This commit is contained in:
David Rodríguez 2025-02-10 16:40:09 +01:00 committed by Hiroshi SHIBATA
parent d9267b4a71
commit 151b436c9d
No known key found for this signature in database
GPG Key ID: F9CF13417264FAC2
2 changed files with 20 additions and 15 deletions

View File

@ -93,17 +93,15 @@ module Bundler
@platforms = @locked_platforms.dup @platforms = @locked_platforms.dup
@locked_bundler_version = @locked_gems.bundler_version @locked_bundler_version = @locked_gems.bundler_version
@locked_ruby_version = @locked_gems.ruby_version @locked_ruby_version = @locked_gems.ruby_version
@originally_locked_deps = @locked_gems.dependencies @locked_deps = @locked_gems.dependencies
@originally_locked_specs = SpecSet.new(@locked_gems.specs) @originally_locked_specs = SpecSet.new(@locked_gems.specs)
@locked_checksums = @locked_gems.checksums @locked_checksums = @locked_gems.checksums
if unlock != true if unlock != true
@locked_deps = @originally_locked_deps
@locked_specs = @originally_locked_specs @locked_specs = @originally_locked_specs
@locked_sources = @locked_gems.sources @locked_sources = @locked_gems.sources
else else
@unlock = {} @unlock = {}
@locked_deps = {}
@locked_specs = SpecSet.new([]) @locked_specs = SpecSet.new([])
@locked_sources = [] @locked_sources = []
end end
@ -115,7 +113,6 @@ module Bundler
@platforms = [] @platforms = []
@locked_deps = {} @locked_deps = {}
@locked_specs = SpecSet.new([]) @locked_specs = SpecSet.new([])
@originally_locked_deps = {}
@originally_locked_specs = @locked_specs @originally_locked_specs = @locked_specs
@locked_sources = [] @locked_sources = []
@locked_checksums = Bundler.feature_flag.lockfile_checksums? @locked_checksums = Bundler.feature_flag.lockfile_checksums?
@ -443,13 +440,13 @@ module Bundler
msg << "\n\nYou have added to the Gemfile:\n" << added.join("\n") if added.any? msg << "\n\nYou have added to the Gemfile:\n" << added.join("\n") if added.any?
msg << "\n\nYou have deleted from the Gemfile:\n" << deleted.join("\n") if deleted.any? msg << "\n\nYou have deleted from the Gemfile:\n" << deleted.join("\n") if deleted.any?
msg << "\n\nYou have changed in the Gemfile:\n" << changed.join("\n") if changed.any? msg << "\n\nYou have changed in the Gemfile:\n" << changed.join("\n") if changed.any?
msg << "\n\nRun `bundle install` elsewhere and add the updated #{SharedHelpers.relative_gemfile_path} to version control.\n" msg << "\n\nRun `bundle install` elsewhere and add the updated #{SharedHelpers.relative_gemfile_path} to version control.\n" unless unlocking?
unless explicit_flag unless explicit_flag
suggested_command = unless Bundler.settings.locations("frozen").keys.include?(:env) suggested_command = unless Bundler.settings.locations("frozen").keys.include?(:env)
"bundle config set frozen false" "bundle config set frozen false"
end end
msg << "If this is a development machine, remove the #{SharedHelpers.relative_lockfile_path} " \ msg << "\n\nIf this is a development machine, remove the #{SharedHelpers.relative_lockfile_path} " \
"freeze by running `#{suggested_command}`." if suggested_command "freeze by running `#{suggested_command}`." if suggested_command
end end
@ -944,7 +941,7 @@ module Bundler
dep.source = sources.get(dep.source) dep.source = sources.get(dep.source)
end end
unless locked_dep = @originally_locked_deps[dep.name] unless locked_dep = @locked_deps[dep.name]
changes = true changes = true
next next
end end

View File

@ -694,28 +694,36 @@ RSpec.describe "bundle update" do
bundle "update", all: true, raise_on_error: false bundle "update", all: true, raise_on_error: false
expect(last_command).to be_failure expect(last_command).to be_failure
expect(err).to match(/Bundler is unlocking, but the lockfile can't be updated because frozen mode is set/) expect(err).to eq <<~ERROR.strip
expect(err).to match(/freeze by running `bundle config set frozen false`./) Bundler is unlocking, but the lockfile can't be updated because frozen mode is set
If this is a development machine, remove the Gemfile.lock freeze by running `bundle config set frozen false`.
ERROR
end end
it "should fail loudly when frozen is set globally" do it "should fail loudly when frozen is set globally" do
bundle "config set --global frozen 1" bundle "config set --global frozen 1"
bundle "update", all: true, raise_on_error: false bundle "update", all: true, raise_on_error: false
expect(err).to match(/Bundler is unlocking, but the lockfile can't be updated because frozen mode is set/). expect(err).to eq <<~ERROR.strip
and match(/freeze by running `bundle config set frozen false`./) Bundler is unlocking, but the lockfile can't be updated because frozen mode is set
If this is a development machine, remove the Gemfile.lock freeze by running `bundle config set frozen false`.
ERROR
end end
it "should fail loudly when deployment is set globally" do it "should fail loudly when deployment is set globally" do
bundle "config set --global deployment true" bundle "config set --global deployment true"
bundle "update", all: true, raise_on_error: false bundle "update", all: true, raise_on_error: false
expect(err).to match(/Bundler is unlocking, but the lockfile can't be updated because frozen mode is set/). expect(err).to eq <<~ERROR.strip
and match(/freeze by running `bundle config set frozen false`./) Bundler is unlocking, but the lockfile can't be updated because frozen mode is set
If this is a development machine, remove the Gemfile.lock freeze by running `bundle config set frozen false`.
ERROR
end end
it "should not suggest any command to unfreeze bundler if frozen is set through ENV" do it "should not suggest any command to unfreeze bundler if frozen is set through ENV" do
bundle "update", all: true, raise_on_error: false, env: { "BUNDLE_FROZEN" => "true" } bundle "update", all: true, raise_on_error: false, env: { "BUNDLE_FROZEN" => "true" }
expect(err).to match(/Bundler is unlocking, but the lockfile can't be updated because frozen mode is set/) expect(err).to eq("Bundler is unlocking, but the lockfile can't be updated because frozen mode is set")
expect(err).not_to match(/by running/)
end end
end end