Skip to content

Commit 93b1c5b

Browse files
hsbtclaude
andcommitted
Apply override version operations in Resolver
Pass the Definition's overrides through to Resolver::Base and rewrite each dependency's requirement at the entry of to_dependency_hash so both direct and transitive deps are reshaped before PubGrub sees them. The hook is the same point Shopify/bundler-ignore-dependency uses, since prepare_dependencies and the @cached_dependencies closure both funnel through to_dependency_hash. Override#apply_to handles all three operation kinds, so :ignore_upper and nil also start working from this commit; integration coverage for those paths follows in later commits. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 1c90030 commit 93b1c5b

5 files changed

Lines changed: 50 additions & 3 deletions

File tree

bundler/lib/bundler/definition.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1275,7 +1275,7 @@ def unlocked_resolution_base
12751275

12761276
def new_resolution_base(last_resolve:, unlock:)
12771277
new_resolution_platforms = @current_platform_missing ? @new_platforms + [Bundler.local_platform] : @new_platforms
1278-
Resolver::Base.new(source_requirements, expanded_dependencies, last_resolve, @platforms, locked_specs: @originally_locked_specs, unlock: unlock, prerelease: gem_version_promoter.pre?, prefer_local: @prefer_local, new_platforms: new_resolution_platforms)
1278+
Resolver::Base.new(source_requirements, expanded_dependencies, last_resolve, @platforms, locked_specs: @originally_locked_specs, unlock: unlock, prerelease: gem_version_promoter.pre?, prefer_local: @prefer_local, new_platforms: new_resolution_platforms, overrides: @overrides)
12791279
end
12801280

12811281
def new_resolver(base)

bundler/lib/bundler/resolver.rb

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -510,7 +510,7 @@ def requirement_to_range(requirement)
510510
end
511511

512512
def to_dependency_hash(dependencies, packages)
513-
dependencies.inject({}) do |deps, dep|
513+
apply_overrides(dependencies).inject({}) do |deps, dep|
514514
package = packages[dep.name]
515515

516516
current_req = deps[package]
@@ -526,6 +526,16 @@ def to_dependency_hash(dependencies, packages)
526526
end
527527
end
528528

529+
def apply_overrides(dependencies)
530+
return dependencies if @base.overrides.empty?
531+
532+
dependencies.map do |dep|
533+
override = @base.overrides.find {|o| o.target == dep.name && o.field == :version }
534+
next dep unless override
535+
Gem::Dependency.new(dep.name, override.apply_to(dep.requirement))
536+
end
537+
end
538+
529539
def bundler_not_found_message(conflict_dependencies)
530540
candidate_specs = filter_matching_specs(default_bundler_source.specs.search("bundler"), conflict_dependencies)
531541

bundler/lib/bundler/resolver/base.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,10 @@
55
module Bundler
66
class Resolver
77
class Base
8-
attr_reader :packages, :requirements, :source_requirements, :locked_specs
8+
attr_reader :packages, :requirements, :source_requirements, :locked_specs, :overrides
99

1010
def initialize(source_requirements, dependencies, base, platforms, options)
11+
@overrides = options.delete(:overrides) || []
1112
@source_requirements = source_requirements
1213
@locked_specs = options[:locked_specs]
1314

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# frozen_string_literal: true
2+
3+
RSpec.describe "override DSL" do
4+
context "with a version: string operation" do
5+
it "replaces a direct dependency requirement with the override version spec" do
6+
install_gemfile <<-G
7+
source "https://gem.repo1"
8+
override "myrack", version: "= 0.9.1"
9+
gem "myrack"
10+
G
11+
12+
expect(the_bundle).to include_gems "myrack 0.9.1"
13+
end
14+
15+
it "replaces a transitive dependency requirement" do
16+
install_gemfile <<-G
17+
source "https://gem.repo1"
18+
override "myrack", version: "= 1.0.0"
19+
gem "myrack_middleware"
20+
G
21+
22+
expect(the_bundle).to include_gems "myrack 1.0.0", "myrack_middleware 1.0"
23+
end
24+
25+
it "replaces the requirement even when the Gemfile pins a different version" do
26+
install_gemfile <<-G
27+
source "https://gem.repo1"
28+
override "myrack", version: "= 0.9.1"
29+
gem "myrack", "= 1.0.0"
30+
G
31+
32+
expect(the_bundle).to include_gems "myrack 0.9.1"
33+
end
34+
end
35+
end

spec/support/windows_tag_group.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,7 @@ module WindowsTagGroup
190190
"spec/install/gems/no_build_extension_spec.rb",
191191
"spec/install/gems/no_install_plugin_spec.rb",
192192
"spec/bundler/override_spec.rb",
193+
"spec/install/gemfile/override_spec.rb",
193194
],
194195
}.freeze
195196
end

0 commit comments

Comments
 (0)