diff options
| author | Abdelkader Boudih <terminale@gmail.com> | 2026-01-05 10:15:31 +0100 |
|---|---|---|
| committer | git <svn-admin@ruby-lang.org> | 2026-02-13 06:19:27 +0000 |
| commit | 7e20c950933821dc1ee51f0f1d5d41706206ea24 (patch) | |
| tree | 4410267f2a0683e2e85040bbdb4c035b002a4377 | |
| parent | 00440871dbe648cf7f8e2ebc2f01d3b1e0024cd6 (diff) | |
[ruby/rubygems] fix(bundler): only preload git sources for requested groups
Skip fetching git sources for excluded groups (--without). This is
important for production builds where development git dependencies
may be private repos without access, or should not be included in
Docker images.
https://github.com/ruby/rubygems/commit/d034ee10bb
| -rw-r--r-- | lib/bundler/definition.rb | 19 | ||||
| -rw-r--r-- | lib/bundler/source/rubygems_aggregate.rb | 5 | ||||
| -rw-r--r-- | lib/bundler/source_map.rb | 8 | ||||
| -rw-r--r-- | spec/bundler/install/git_spec.rb | 28 |
4 files changed, 54 insertions, 6 deletions
diff --git a/lib/bundler/definition.rb b/lib/bundler/definition.rb index 3cf9fbe8bf..4c0c337535 100644 --- a/lib/bundler/definition.rb +++ b/lib/bundler/definition.rb @@ -1125,11 +1125,24 @@ module Bundler end def preload_git_sources - sources.git_sources.each {|source| preload_git_source_worker.enq(source) } + needed_git_sources.each {|source| preload_git_source_worker.enq(source) } ensure preload_git_source_worker.stop end + # Git sources needed for the requested groups (excludes sources only used by --without groups) + def needed_git_sources + needed_deps = dependencies_for(requested_groups) + sources.git_sources.select do |source| + needed_deps.any? {|d| d.source == source } + end + end + + # Git sources that should be excluded (only used by --without groups) + def excluded_git_sources + sources.git_sources - needed_git_sources + end + def find_source_requirements if Gem.ruby_version >= Gem::Version.new("3.3") # Ruby 3.2 has a bug that incorrectly triggers a circular dependency warning. This version will continue to @@ -1141,10 +1154,10 @@ module Bundler # specs will be available later when the resolver knows where to # look for that gemspec (or its dependencies) source_requirements = if precompute_source_requirements_for_indirect_dependencies? - all_requirements = source_map.all_requirements + all_requirements = source_map.all_requirements(excluded_git_sources) { default: default_source }.merge(all_requirements) else - { default: Source::RubygemsAggregate.new(sources, source_map) }.merge(source_map.direct_requirements) + { default: Source::RubygemsAggregate.new(sources, source_map, excluded_git_sources) }.merge(source_map.direct_requirements) end source_requirements.merge!(source_map.locked_requirements) if nothing_changed? metadata_dependencies.each do |dep| diff --git a/lib/bundler/source/rubygems_aggregate.rb b/lib/bundler/source/rubygems_aggregate.rb index 99ef81ad54..8aeaa375fa 100644 --- a/lib/bundler/source/rubygems_aggregate.rb +++ b/lib/bundler/source/rubygems_aggregate.rb @@ -5,9 +5,10 @@ module Bundler class RubygemsAggregate attr_reader :source_map, :sources - def initialize(sources, source_map) + def initialize(sources, source_map, excluded_sources = []) @sources = sources @source_map = source_map + @excluded_sources = excluded_sources @index = build_index end @@ -31,6 +32,8 @@ module Bundler dependency_names = source_map.pinned_spec_names sources.all_sources.each do |source| + next if @excluded_sources.include?(source) + source.dependency_names = dependency_names - source_map.pinned_spec_names(source) idx.add_source source.specs dependency_names.concat(source.unmet_deps).uniq! diff --git a/lib/bundler/source_map.rb b/lib/bundler/source_map.rb index cb88caf1bd..513eb37f8b 100644 --- a/lib/bundler/source_map.rb +++ b/lib/bundler/source_map.rb @@ -14,10 +14,14 @@ module Bundler direct_requirements.reject {|_, source| source == skip }.keys end - def all_requirements + def all_requirements(excluded_sources = []) requirements = direct_requirements.dup - unmet_deps = sources.non_default_explicit_sources.map do |source| + explicit_sources = sources.non_default_explicit_sources.reject do |source| + excluded_sources.include?(source) + end + + unmet_deps = explicit_sources.map do |source| (source.spec_names - pinned_spec_names).each do |indirect_dependency_name| previous_source = requirements[indirect_dependency_name] if previous_source.nil? diff --git a/spec/bundler/install/git_spec.rb b/spec/bundler/install/git_spec.rb index aa707a0222..6ecf3574d7 100644 --- a/spec/bundler/install/git_spec.rb +++ b/spec/bundler/install/git_spec.rb @@ -290,4 +290,32 @@ RSpec.describe "bundle install" do end end end + + describe "with excluded groups" do + it "works if you exclude a group with a git gem", :ruby => ">= 3.3" do + build_git "production_gem", "1.0" + build_git "development_gem", "1.0" + + gemfile <<-G + source "https://gem.repo1" + + gem "production_gem", :git => "#{lib_path("production_gem-1.0")}" + + group :development do + gem "development_gem", :git => "#{lib_path("development_gem-1.0")}" + end + G + + # First install all groups to create lockfile + bundle :install + + # Set without and reinstall + bundle "config set --local without development" + bundle :install + + # Verify only production gem is available + expect(the_bundle).to include_gems("production_gem 1.0") + expect(the_bundle).not_to include_gems("development_gem 1.0") + end + end end |
