summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHiroshi SHIBATA <hsbt@ruby-lang.org>2026-05-07 20:08:37 +0900
committergit <svn-admin@ruby-lang.org>2026-05-08 06:43:45 +0000
commitdff3200e5ca078977a40d92ad4236b9c8d60499e (patch)
tree2346f9213fde8e6d0604a6078d17d86881728fe2
parent0beb804ef79c3355c19ed272106c42b02780b607 (diff)
[ruby/rubygems] Stop blanket-unlocking the lockfile on :all overrides
Previously, any :all override called unlock_all_locked_specs_for_override which pushed every locked spec into @gems_to_unlock. A user adding a narrow `override :all, required_ruby_version: :ignore_upper` thus paid for a full re-resolve that could pull unrelated dependency upgrades/downgrades. Make :all overrides leave the lockfile alone at converge time. They take effect on a fresh resolution (no lockfile) or when the user opts in via `bundle update`. Per-gem overrides retain their unlock for the named gem since the user explicitly named the target. https://github.com/ruby/rubygems/commit/3c95ab99e3 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
-rw-r--r--lib/bundler/definition.rb18
-rw-r--r--spec/bundler/install/gemfile/override_spec.rb8
2 files changed, 11 insertions, 15 deletions
diff --git a/lib/bundler/definition.rb b/lib/bundler/definition.rb
index 2fe28f7656..2aa74804ba 100644
--- a/lib/bundler/definition.rb
+++ b/lib/bundler/definition.rb
@@ -1061,11 +1061,10 @@ module Bundler
def converge_overrides_outside_dependencies
@overrides.each do |override|
- if override.target == :all
- unlock_all_locked_specs_for_override
- next
- end
-
+ # :all overrides are intentionally not pre-unlocked. They take effect on
+ # fresh resolution (no lockfile) or when the user runs `bundle update`.
+ # Forcing a full re-resolve from a single :all directive would surprise
+ # users with unrelated dependency churn.
next unless override.target.is_a?(String)
name = override.target
@@ -1081,15 +1080,6 @@ module Bundler
end
end
- def unlock_all_locked_specs_for_override
- @originally_locked_specs.each do |locked_spec|
- name = locked_spec.name
- next if @changed_dependencies.include?(name)
- @gems_to_unlock << name
- @changed_dependencies << name
- end
- end
-
# Remove elements from the locked specs that are expired. This will most
# commonly happen if the Gemfile has changed since the lockfile was last
# generated
diff --git a/spec/bundler/install/gemfile/override_spec.rb b/spec/bundler/install/gemfile/override_spec.rb
index 19fa2ee915..02b0e7d772 100644
--- a/spec/bundler/install/gemfile/override_spec.rb
+++ b/spec/bundler/install/gemfile/override_spec.rb
@@ -291,7 +291,7 @@ RSpec.describe "override DSL" do
expect(err).to include("still_blocked")
end
- it "re-resolves a previously locked spec when an :all metadata override is added" do
+ it "preserves locked versions when an :all metadata override is added without bundle update" do
build_repo2 do
build_gem "selectable", "1.0"
build_gem "selectable", "2.0" do |s|
@@ -313,7 +313,13 @@ RSpec.describe "override DSL" do
gem "selectable"
G
+ # :all override alone does not pre-unlock locked specs; narrow change
+ # should not trigger unrelated lockfile churn.
bundle :lock
+ expect(lockfile).to include("selectable (1.0)")
+
+ # bundle update opts the user into re-resolution under the override.
+ bundle "update selectable"
expect(lockfile).to include("selectable (2.0)")
end
end