summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/bundler/definition.rb14
-rw-r--r--spec/bundler/commands/update_spec.rb66
2 files changed, 75 insertions, 5 deletions
diff --git a/lib/bundler/definition.rb b/lib/bundler/definition.rb
index 61add4be10..24dae86493 100644
--- a/lib/bundler/definition.rb
+++ b/lib/bundler/definition.rb
@@ -938,7 +938,7 @@ module Bundler
def converge_dependencies
@missing_lockfile_dep = nil
- changes = false
+ @changed_dependencies = []
current_dependencies.each do |dep|
if dep.source
@@ -960,10 +960,10 @@ module Bundler
end
end
- changes ||= dep_changed
+ @changed_dependencies << name if dep_changed
end
- changes
+ @changed_dependencies.any?
end
# Remove elements from the locked specs that are expired. This will most
@@ -1095,9 +1095,13 @@ module Bundler
def additional_base_requirements_to_prevent_downgrades(resolution_packages)
return resolution_packages unless @locked_gems && !sources.expired_sources?(@locked_gems.sources)
- converge_specs(@originally_locked_specs).each do |locked_spec|
+ @originally_locked_specs.each do |locked_spec|
next if locked_spec.source.is_a?(Source::Path)
- resolution_packages.base_requirements[locked_spec.name] = Gem::Requirement.new(">= #{locked_spec.version}")
+
+ name = locked_spec.name
+ next if @changed_dependencies.include?(name)
+
+ resolution_packages.base_requirements[name] = Gem::Requirement.new(">= #{locked_spec.version}")
end
resolution_packages
end
diff --git a/spec/bundler/commands/update_spec.rb b/spec/bundler/commands/update_spec.rb
index 058cd2ec82..f6d0188794 100644
--- a/spec/bundler/commands/update_spec.rb
+++ b/spec/bundler/commands/update_spec.rb
@@ -428,6 +428,72 @@ RSpec.describe "bundle update" do
expect(out).to include("Installing sneakers 2.11.0").and include("Installing rake 13.0.6")
end
+ it "does not downgrade direct dependencies unnecessarily" do
+ build_repo4 do
+ build_gem "redis", "4.8.1"
+ build_gem "redis", "5.3.0"
+
+ build_gem "sidekiq", "6.5.5" do |s|
+ s.add_dependency "redis", ">= 4.5.0"
+ end
+
+ build_gem "sidekiq", "6.5.12" do |s|
+ s.add_dependency "redis", ">= 4.5.0", "< 5"
+ end
+
+ # one version of sidekiq above Gemfile's range is needed to make the
+ # resolver choose `redis` first and trying to upgrade it, reproducing
+ # the accidental sidekiq downgrade as a result
+ build_gem "sidekiq", "7.0.0 " do |s|
+ s.add_dependency "redis", ">= 4.2.0"
+ end
+
+ build_gem "sentry-sidekiq", "5.22.0" do |s|
+ s.add_dependency "sidekiq", ">= 3.0"
+ end
+
+ build_gem "sentry-sidekiq", "5.22.4" do |s|
+ s.add_dependency "sidekiq", ">= 3.0"
+ end
+ end
+
+ gemfile <<~G
+ source "https://gem.repo4"
+
+ gem "redis"
+ gem "sidekiq", "~> 6.5"
+ gem "sentry-sidekiq"
+ G
+
+ original_lockfile = <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ redis (4.8.1)
+ sentry-sidekiq (5.22.0)
+ sidekiq (>= 3.0)
+ sidekiq (6.5.12)
+ redis (>= 4.5.0, < 5)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ redis
+ sentry-sidekiq
+ sidekiq (~> 6.5)
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ lockfile original_lockfile
+
+ bundle "lock --update sentry-sidekiq"
+
+ expect(lockfile).to eq(original_lockfile.sub("sentry-sidekiq (5.22.0)", "sentry-sidekiq (5.22.4)"))
+ end
+
it "does not downgrade indirect dependencies unnecessarily" do
build_repo4 do
build_gem "a" do |s|