diff options
| author | Hiroshi SHIBATA <hsbt@ruby-lang.org> | 2026-02-10 10:07:37 +0900 |
|---|---|---|
| committer | Takashi Kokubun <takashikkbn@gmail.com> | 2026-02-09 17:38:24 -0800 |
| commit | 91a4926c9a9cd12f43307a2c934766c000356f07 (patch) | |
| tree | d5c366208d6c2e9cb9570d41310e9fef618ecab1 | |
| parent | d5d3fb8b80e81426517bf150ebcab83be4ed996d (diff) | |
Merge RubyGems/Bundler 4.0.4
| -rw-r--r-- | lib/bundler/cli/add.rb | 10 | ||||
| -rw-r--r-- | lib/bundler/current_ruby.rb | 2 | ||||
| -rw-r--r-- | lib/bundler/definition.rb | 17 | ||||
| -rw-r--r-- | lib/bundler/rubygems_integration.rb | 2 | ||||
| -rw-r--r-- | lib/bundler/runtime.rb | 9 | ||||
| -rw-r--r-- | lib/bundler/version.rb | 2 | ||||
| -rw-r--r-- | lib/rubygems.rb | 2 | ||||
| -rw-r--r-- | lib/rubygems/commands/rebuild_command.rb | 1 | ||||
| -rw-r--r-- | lib/rubygems/installer.rb | 7 | ||||
| -rw-r--r-- | spec/bundler/bundler/current_ruby_spec.rb | 11 | ||||
| -rw-r--r-- | spec/bundler/commands/add_spec.rb | 34 | ||||
| -rw-r--r-- | spec/bundler/commands/clean_spec.rb | 37 | ||||
| -rw-r--r-- | spec/bundler/install/gemfile/sources_spec.rb | 116 | ||||
| -rw-r--r-- | spec/bundler/realworld/fixtures/tapioca/Gemfile.lock | 2 | ||||
| -rw-r--r-- | spec/bundler/realworld/fixtures/warbler/Gemfile.lock | 2 | ||||
| -rw-r--r-- | tool/bundler/dev_gems.rb.lock | 2 | ||||
| -rw-r--r-- | tool/bundler/rubocop_gems.rb.lock | 2 | ||||
| -rw-r--r-- | tool/bundler/standard_gems.rb.lock | 2 | ||||
| -rw-r--r-- | tool/bundler/test_gems.rb.lock | 2 |
19 files changed, 246 insertions, 16 deletions
diff --git a/lib/bundler/cli/add.rb b/lib/bundler/cli/add.rb index 12a681a816..9f17604096 100644 --- a/lib/bundler/cli/add.rb +++ b/lib/bundler/cli/add.rb @@ -36,6 +36,16 @@ module Bundler end def validate_options! + raise InvalidOption, "You cannot specify `--git` and `--github` at the same time." if options["git"] && options["github"] + + unless options["git"] || options["github"] + raise InvalidOption, "You cannot specify `--branch` unless `--git` or `--github` is specified." if options["branch"] + + raise InvalidOption, "You cannot specify `--ref` unless `--git` or `--github` is specified." if options["ref"] + end + + raise InvalidOption, "You cannot specify `--branch` and `--ref` at the same time." if options["branch"] && options["ref"] + raise InvalidOption, "You cannot specify `--strict` and `--optimistic` at the same time." if options[:strict] && options[:optimistic] # raise error when no gems are specified diff --git a/lib/bundler/current_ruby.rb b/lib/bundler/current_ruby.rb index ab6520a106..17c7655adb 100644 --- a/lib/bundler/current_ruby.rb +++ b/lib/bundler/current_ruby.rb @@ -11,7 +11,7 @@ module Bundler end class CurrentRuby - ALL_RUBY_VERSIONS = [*18..27, *30..34, 40].freeze + ALL_RUBY_VERSIONS = [*18..27, *30..34, *40..41].freeze KNOWN_MINOR_VERSIONS = ALL_RUBY_VERSIONS.map {|v| v.digits.reverse.join(".") }.freeze KNOWN_MAJOR_VERSIONS = ALL_RUBY_VERSIONS.map {|v| v.digits.last.to_s }.uniq.freeze PLATFORM_MAP = { diff --git a/lib/bundler/definition.rb b/lib/bundler/definition.rb index 2fa7d0d277..5ab577f504 100644 --- a/lib/bundler/definition.rb +++ b/lib/bundler/definition.rb @@ -1066,7 +1066,22 @@ module Bundler deps << dep if !replacement_source || lockfile_source.include?(replacement_source) || new_deps.include?(dep) else - replacement_source = sources.get(lockfile_source) + parent_dep = @dependencies.find do |d| + next unless d.source && d.source != lockfile_source + next if d.source.is_a?(Source::Gemspec) + + parent_locked_specs = @originally_locked_specs[d.name] + + parent_locked_specs.any? do |parent_spec| + parent_spec.runtime_dependencies.any? {|rd| rd.name == s.name } + end + end + + if parent_dep + replacement_source = parent_dep.source + else + replacement_source = sources.get(lockfile_source) + end end # Replace the locked dependency's source with the equivalent source from the Gemfile diff --git a/lib/bundler/rubygems_integration.rb b/lib/bundler/rubygems_integration.rb index d8f95cffb8..e04ef23259 100644 --- a/lib/bundler/rubygems_integration.rb +++ b/lib/bundler/rubygems_integration.rb @@ -432,7 +432,7 @@ module Bundler end def find_bundler(version) - find_name("bundler").find {|s| s.version.to_s == version } + find_name("bundler").find {|s| s.version.to_s == version.to_s } end def find_name(name) diff --git a/lib/bundler/runtime.rb b/lib/bundler/runtime.rb index 5eb827dcb2..5280e72aa2 100644 --- a/lib/bundler/runtime.rb +++ b/lib/bundler/runtime.rb @@ -174,7 +174,14 @@ module Bundler spec_cache_paths = [] spec_gemspec_paths = [] spec_extension_paths = [] - Bundler.rubygems.add_default_gems_to(specs).values.each do |spec| + specs_to_keep = Bundler.rubygems.add_default_gems_to(specs).values + + current_bundler = Bundler.rubygems.find_bundler(Bundler.gem_version) + if current_bundler + specs_to_keep << current_bundler + end + + specs_to_keep.each do |spec| spec_gem_paths << spec.full_gem_path # need to check here in case gems are nested like for the rails git repo md = %r{(.+bundler/gems/.+-[a-f0-9]{7,12})}.match(spec.full_gem_path) diff --git a/lib/bundler/version.rb b/lib/bundler/version.rb index 732b4a0563..8c039d16a0 100644 --- a/lib/bundler/version.rb +++ b/lib/bundler/version.rb @@ -1,7 +1,7 @@ # frozen_string_literal: false module Bundler - VERSION = "4.0.3".freeze + VERSION = "4.0.4".freeze def self.bundler_major_version @bundler_major_version ||= gem_version.segments.first diff --git a/lib/rubygems.rb b/lib/rubygems.rb index e99176fec0..9e90e608a5 100644 --- a/lib/rubygems.rb +++ b/lib/rubygems.rb @@ -9,7 +9,7 @@ require "rbconfig" module Gem - VERSION = "4.0.3" + VERSION = "4.0.4" end require_relative "rubygems/defaults" diff --git a/lib/rubygems/commands/rebuild_command.rb b/lib/rubygems/commands/rebuild_command.rb index 77a474ef1d..23b9d7b3ba 100644 --- a/lib/rubygems/commands/rebuild_command.rb +++ b/lib/rubygems/commands/rebuild_command.rb @@ -1,6 +1,5 @@ # frozen_string_literal: true -require "date" require "digest" require "fileutils" require "tmpdir" diff --git a/lib/rubygems/installer.rb b/lib/rubygems/installer.rb index 90aa25dc07..914e413677 100644 --- a/lib/rubygems/installer.rb +++ b/lib/rubygems/installer.rb @@ -943,7 +943,12 @@ class Gem::Installer end def build_jobs - @build_jobs ||= Etc.nprocessors + 1 + @build_jobs ||= begin + require "etc" + Etc.nprocessors + 1 + rescue LoadError + 1 + end end def rb_config diff --git a/spec/bundler/bundler/current_ruby_spec.rb b/spec/bundler/bundler/current_ruby_spec.rb index aa19a41407..79eb802aa5 100644 --- a/spec/bundler/bundler/current_ruby_spec.rb +++ b/spec/bundler/bundler/current_ruby_spec.rb @@ -23,6 +23,7 @@ RSpec.describe Bundler::CurrentRuby do ruby_33: Gem::Platform::RUBY, ruby_34: Gem::Platform::RUBY, ruby_40: Gem::Platform::RUBY, + ruby_41: Gem::Platform::RUBY, mri: Gem::Platform::RUBY, mri_18: Gem::Platform::RUBY, mri_19: Gem::Platform::RUBY, @@ -40,6 +41,7 @@ RSpec.describe Bundler::CurrentRuby do mri_33: Gem::Platform::RUBY, mri_34: Gem::Platform::RUBY, mri_40: Gem::Platform::RUBY, + mri_41: Gem::Platform::RUBY, rbx: Gem::Platform::RUBY, truffleruby: Gem::Platform::RUBY, jruby: Gem::Platform::JAVA, @@ -61,7 +63,8 @@ RSpec.describe Bundler::CurrentRuby do windows_32: Gem::Platform::WINDOWS, windows_33: Gem::Platform::WINDOWS, windows_34: Gem::Platform::WINDOWS, - windows_40: Gem::Platform::WINDOWS } + windows_40: Gem::Platform::WINDOWS, + windows_41: Gem::Platform::WINDOWS } end let(:deprecated) do @@ -82,6 +85,7 @@ RSpec.describe Bundler::CurrentRuby do mswin_33: Gem::Platform::MSWIN, mswin_34: Gem::Platform::MSWIN, mswin_40: Gem::Platform::MSWIN, + mswin_41: Gem::Platform::MSWIN, mswin64: Gem::Platform::MSWIN64, mswin64_19: Gem::Platform::MSWIN64, mswin64_20: Gem::Platform::MSWIN64, @@ -98,6 +102,7 @@ RSpec.describe Bundler::CurrentRuby do mswin64_33: Gem::Platform::MSWIN64, mswin64_34: Gem::Platform::MSWIN64, mswin64_40: Gem::Platform::MSWIN64, + mswin64_41: Gem::Platform::MSWIN64, mingw: Gem::Platform::UNIVERSAL_MINGW, mingw_18: Gem::Platform::UNIVERSAL_MINGW, mingw_19: Gem::Platform::UNIVERSAL_MINGW, @@ -115,6 +120,7 @@ RSpec.describe Bundler::CurrentRuby do mingw_33: Gem::Platform::UNIVERSAL_MINGW, mingw_34: Gem::Platform::UNIVERSAL_MINGW, mingw_40: Gem::Platform::UNIVERSAL_MINGW, + mingw_41: Gem::Platform::UNIVERSAL_MINGW, x64_mingw: Gem::Platform::UNIVERSAL_MINGW, x64_mingw_20: Gem::Platform::UNIVERSAL_MINGW, x64_mingw_21: Gem::Platform::UNIVERSAL_MINGW, @@ -129,7 +135,8 @@ RSpec.describe Bundler::CurrentRuby do x64_mingw_32: Gem::Platform::UNIVERSAL_MINGW, x64_mingw_33: Gem::Platform::UNIVERSAL_MINGW, x64_mingw_34: Gem::Platform::UNIVERSAL_MINGW, - x64_mingw_40: Gem::Platform::UNIVERSAL_MINGW } + x64_mingw_40: Gem::Platform::UNIVERSAL_MINGW, + x64_mingw_41: Gem::Platform::UNIVERSAL_MINGW } end # rubocop:enable Naming/VariableNumber diff --git a/spec/bundler/commands/add_spec.rb b/spec/bundler/commands/add_spec.rb index 00aa6415e1..ed98a914f3 100644 --- a/spec/bundler/commands/add_spec.rb +++ b/spec/bundler/commands/add_spec.rb @@ -236,6 +236,40 @@ RSpec.describe "bundle add" do end end + describe "with mismatched pair in --git/--github, --branch/--ref" do + describe "with --git and --github" do + it "throws error" do + bundle "add 'foo' --git x --github y", raise_on_error: false + + expect(err).to include("You cannot specify `--git` and `--github` at the same time.") + end + end + + describe "with --branch and --ref with --git" do + it "throws error" do + bundle "add 'foo' --branch x --ref y --git file://git", raise_on_error: false + + expect(err).to include("You cannot specify `--branch` and `--ref` at the same time.") + end + end + + describe "with --branch but without --git or --github" do + it "throws error" do + bundle "add 'foo' --branch x", raise_on_error: false + + expect(err).to include("You cannot specify `--branch` unless `--git` or `--github` is specified.") + end + end + + describe "with --ref but without --git or --github" do + it "throws error" do + bundle "add 'foo' --ref y", raise_on_error: false + + expect(err).to include("You cannot specify `--ref` unless `--git` or `--github` is specified.") + end + end + end + describe "with --skip-install" do it "adds gem to Gemfile but is not installed" do bundle "add foo --skip-install --version=2.0" diff --git a/spec/bundler/commands/clean_spec.rb b/spec/bundler/commands/clean_spec.rb index 6b678d0aa5..793aacf5c2 100644 --- a/spec/bundler/commands/clean_spec.rb +++ b/spec/bundler/commands/clean_spec.rb @@ -898,4 +898,41 @@ RSpec.describe "bundle clean" do expect(very_simple_binary_extensions_dir).to be_nil end + + it "does not remove the bundler version currently running" do + gemfile <<-G + source "https://gem.repo1" + + gem "myrack" + G + + bundle "config set path vendor/bundle" + bundle "install" + + version = Bundler.gem_version.to_s + # Simulate that the locked bundler version is installed in the bundle path + # by creating the gem directory and gemspec (as would happen after bundle install with that version) + Pathname(vendored_gems("cache/bundler-#{version}.gem")).tap do |path| + path.basename.mkpath + FileUtils.touch(path) + end + FileUtils.touch(vendored_gems("gems/bundler-#{version}")) + Pathname(vendored_gems("specifications/bundler-#{version}.gemspec")).tap do |path| + path.basename.mkpath + path.write(<<~GEMSPEC) + Gem::Specification.new do |s| + s.name = "bundler" + s.version = "#{version}" + s.authors = ["bundler team"] + s.summary = "The best way to manage your application's dependencies" + end + GEMSPEC + end + + should_have_gems "bundler-#{version}" + + bundle :clean + + should_have_gems "bundler-#{version}" + end end diff --git a/spec/bundler/install/gemfile/sources_spec.rb b/spec/bundler/install/gemfile/sources_spec.rb index c0b4d98f1c..90f87ed0c5 100644 --- a/spec/bundler/install/gemfile/sources_spec.rb +++ b/spec/bundler/install/gemfile/sources_spec.rb @@ -1079,4 +1079,120 @@ RSpec.describe "bundle install with gems on multiple sources" do expect(lockfile).to eq original_lockfile.gsub("bigdecimal (1.0.0)", "bigdecimal (3.3.1)") end end + + context "when switching a gem with components from rubygems to git source" do + before do + build_repo2 do + build_gem "rails", "7.0.0" do |s| + s.add_dependency "actionpack", "7.0.0" + s.add_dependency "activerecord", "7.0.0" + end + build_gem "actionpack", "7.0.0" + build_gem "activerecord", "7.0.0" + # propshaft also depends on actionpack, creating the conflict + build_gem "propshaft", "1.0.0" do |s| + s.add_dependency "actionpack", ">= 7.0.0" + end + end + + build_git "rails", "7.0.0", path: lib_path("rails") do |s| + s.add_dependency "actionpack", "7.0.0" + s.add_dependency "activerecord", "7.0.0" + end + + build_git "actionpack", "7.0.0", path: lib_path("rails") + build_git "activerecord", "7.0.0", path: lib_path("rails") + + install_gemfile <<-G + source "https://gem.repo2" + gem "rails", "7.0.0" + gem "propshaft" + G + end + + it "moves component gems to the git source in the lockfile" do + expect(lockfile).to include("remote: https://gem.repo2") + expect(lockfile).to include("rails (7.0.0)") + expect(lockfile).to include("actionpack (7.0.0)") + expect(lockfile).to include("activerecord (7.0.0)") + expect(lockfile).to include("propshaft (1.0.0)") + + gemfile <<-G + source "https://gem.repo2" + gem "rails", git: "#{lib_path("rails")}" + gem "propshaft" + G + + bundle "install" + + expect(lockfile).to include("remote: #{lib_path("rails")}") + expect(lockfile).to include("rails (7.0.0)") + expect(lockfile).to include("actionpack (7.0.0)") + expect(lockfile).to include("activerecord (7.0.0)") + + # Component gems should NOT remain in the GEM section + # Extract just the GEM section by splitting on GIT first, then GEM + gem_section = lockfile.split("GEM\n").last.split(/\n(PLATFORMS|DEPENDENCIES)/)[0] + expect(gem_section).not_to include("actionpack (7.0.0)") + expect(gem_section).not_to include("activerecord (7.0.0)") + end + end + + context "when switching a gem with components from rubygems to path source" do + before do + build_repo2 do + build_gem "rails", "7.0.0" do |s| + s.add_dependency "actionpack", "7.0.0" + s.add_dependency "activerecord", "7.0.0" + end + build_gem "actionpack", "7.0.0" + build_gem "activerecord", "7.0.0" + # propshaft also depends on actionpack, creating the conflict + build_gem "propshaft", "1.0.0" do |s| + s.add_dependency "actionpack", ">= 7.0.0" + end + end + + build_lib "rails", "7.0.0", path: lib_path("rails") do |s| + s.add_dependency "actionpack", "7.0.0" + s.add_dependency "activerecord", "7.0.0" + end + + build_lib "actionpack", "7.0.0", path: lib_path("rails") + build_lib "activerecord", "7.0.0", path: lib_path("rails") + + install_gemfile <<-G + source "https://gem.repo2" + gem "rails", "7.0.0" + gem "propshaft" + G + end + + it "moves component gems to the path source in the lockfile" do + expect(lockfile).to include("remote: https://gem.repo2") + expect(lockfile).to include("rails (7.0.0)") + expect(lockfile).to include("actionpack (7.0.0)") + expect(lockfile).to include("activerecord (7.0.0)") + expect(lockfile).to include("propshaft (1.0.0)") + + gemfile <<-G + source "https://gem.repo2" + gem "rails", path: "#{lib_path("rails")}" + gem "propshaft" + G + + bundle "install" + + expect(lockfile).to include("remote: #{lib_path("rails")}") + expect(lockfile).to include("rails (7.0.0)") + expect(lockfile).to include("actionpack (7.0.0)") + expect(lockfile).to include("activerecord (7.0.0)") + + # Component gems should NOT remain in the GEM section + # Extract just the GEM section by splitting appropriately + gem_section = lockfile.split("GEM\n").last.split(/\n(PLATFORMS|DEPENDENCIES)/)[0] + expect(gem_section).not_to include("actionpack (7.0.0)") + expect(gem_section).not_to include("activerecord (7.0.0)") + end + end end diff --git a/spec/bundler/realworld/fixtures/tapioca/Gemfile.lock b/spec/bundler/realworld/fixtures/tapioca/Gemfile.lock index 2db720a69f..1d4eae8ffe 100644 --- a/spec/bundler/realworld/fixtures/tapioca/Gemfile.lock +++ b/spec/bundler/realworld/fixtures/tapioca/Gemfile.lock @@ -46,4 +46,4 @@ DEPENDENCIES tapioca BUNDLED WITH - 4.0.3 + 4.0.4 diff --git a/spec/bundler/realworld/fixtures/warbler/Gemfile.lock b/spec/bundler/realworld/fixtures/warbler/Gemfile.lock index c37fbbb7ee..6eb02db3db 100644 --- a/spec/bundler/realworld/fixtures/warbler/Gemfile.lock +++ b/spec/bundler/realworld/fixtures/warbler/Gemfile.lock @@ -36,4 +36,4 @@ DEPENDENCIES warbler! BUNDLED WITH - 4.0.3 + 4.0.4 diff --git a/tool/bundler/dev_gems.rb.lock b/tool/bundler/dev_gems.rb.lock index fff9cfe70c..01317be72d 100644 --- a/tool/bundler/dev_gems.rb.lock +++ b/tool/bundler/dev_gems.rb.lock @@ -129,4 +129,4 @@ CHECKSUMS turbo_tests (2.2.5) sha256=3fa31497d12976d11ccc298add29107b92bda94a90d8a0a5783f06f05102509f BUNDLED WITH - 4.0.3 + 4.0.4 diff --git a/tool/bundler/rubocop_gems.rb.lock b/tool/bundler/rubocop_gems.rb.lock index 70704bfc38..a6d9fb125a 100644 --- a/tool/bundler/rubocop_gems.rb.lock +++ b/tool/bundler/rubocop_gems.rb.lock @@ -156,4 +156,4 @@ CHECKSUMS unicode-emoji (4.1.0) sha256=4997d2d5df1ed4252f4830a9b6e86f932e2013fbff2182a9ce9ccabda4f325a5 BUNDLED WITH - 4.0.3 + 4.0.4 diff --git a/tool/bundler/standard_gems.rb.lock b/tool/bundler/standard_gems.rb.lock index 669e5492a8..c4e2f1e784 100644 --- a/tool/bundler/standard_gems.rb.lock +++ b/tool/bundler/standard_gems.rb.lock @@ -176,4 +176,4 @@ CHECKSUMS unicode-emoji (4.1.0) sha256=4997d2d5df1ed4252f4830a9b6e86f932e2013fbff2182a9ce9ccabda4f325a5 BUNDLED WITH - 4.0.3 + 4.0.4 diff --git a/tool/bundler/test_gems.rb.lock b/tool/bundler/test_gems.rb.lock index d8f7d77122..46c12cfb60 100644 --- a/tool/bundler/test_gems.rb.lock +++ b/tool/bundler/test_gems.rb.lock @@ -103,4 +103,4 @@ CHECKSUMS tilt (2.6.1) sha256=35a99bba2adf7c1e362f5b48f9b581cce4edfba98117e34696dde6d308d84770 BUNDLED WITH - 4.0.3 + 4.0.4 |
