From ca1c46d33c9ef86c288d4ae4226644451b4dedec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Wed, 23 Apr 2025 13:27:14 +0200 Subject: [PATCH] [rubygems/rubygems] Ignore local specifications if they have incorrect dependencies Currently ruby-dev installs an incorrect gemspec for rdoc, that does not declare its dependency on psych. This seems like a ruby-core bug, but it seems best for Bundler to ignore it, go with the remote specification instead, and print a warning. https://github.com/rubygems/rubygems/commit/227cafd657 --- lib/bundler/index.rb | 9 +++-- spec/bundler/commands/lock_spec.rb | 58 ++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+), 2 deletions(-) diff --git a/lib/bundler/index.rb b/lib/bundler/index.rb index df46facc88..d591b34cc7 100644 --- a/lib/bundler/index.rb +++ b/lib/bundler/index.rb @@ -131,6 +131,11 @@ module Bundler return unless other other.each do |spec| if existing = find_by_spec(spec) + unless dependencies_eql?(existing, spec) + Bundler.ui.warn "Local specification for #{spec.full_name} has different dependencies than the remote gem, ignoring it" + next + end + add_duplicate(existing) end add spec @@ -153,8 +158,8 @@ module Bundler end def dependencies_eql?(spec, other_spec) - deps = spec.dependencies.select {|d| d.type != :development } - other_deps = other_spec.dependencies.select {|d| d.type != :development } + deps = spec.runtime_dependencies + other_deps = other_spec.runtime_dependencies deps.sort == other_deps.sort end diff --git a/spec/bundler/commands/lock_spec.rb b/spec/bundler/commands/lock_spec.rb index 8d1bac2951..da21e44c9c 100644 --- a/spec/bundler/commands/lock_spec.rb +++ b/spec/bundler/commands/lock_spec.rb @@ -1609,6 +1609,64 @@ RSpec.describe "bundle lock" do end end + context "when a system gem has incorrect dependencies, different from remote gems" do + before do + build_repo4 do + build_gem "foo", "1.0.0" do |s| + s.add_dependency "bar" + end + + build_gem "bar", "1.0.0" + end + + system_gems "foo-1.0.0", gem_repo: gem_repo4, path: default_bundle_path + + # simulate gemspec with wrong empty dependencies + foo_gemspec_path = default_bundle_path("specifications/foo-1.0.0.gemspec") + foo_gemspec = Gem::Specification.load(foo_gemspec_path.to_s) + foo_gemspec.dependencies.clear + File.write(foo_gemspec_path, foo_gemspec.to_ruby) + end + + it "generates a lockfile using remote dependencies, and prints a warning" do + gemfile <<~G + source "https://gem.repo4" + + gem "foo" + G + + checksums = checksums_section_when_enabled do |c| + c.checksum gem_repo4, "foo", "1.0.0" + c.checksum gem_repo4, "bar", "1.0.0" + end + + simulate_platform "x86_64-linux" do + bundle "lock --verbose" + end + + expect(err).to eq("Local specification for foo-1.0.0 has different dependencies than the remote gem, ignoring it") + + expect(lockfile).to eq <<~L + GEM + remote: https://gem.repo4/ + specs: + bar (1.0.0) + foo (1.0.0) + bar + + PLATFORMS + ruby + x86_64-linux + + DEPENDENCIES + foo + #{checksums} + BUNDLED WITH + #{Bundler::VERSION} + L + end + end + it "properly shows resolution errors including OR requirements" do build_repo4 do build_gem "activeadmin", "2.13.1" do |s|