From 2fa9f3c0322570dfb1672b49bc1f3306ef595131 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Tue, 15 Dec 2020 08:32:54 +0900 Subject: [PATCH] Prepare to release rubygems-3.2.1 and bundler-2.2.1 --- lib/bundler.rb | 12 +- lib/bundler/cli.rb | 2 +- lib/bundler/cli/outdated.rb | 4 +- lib/bundler/definition.rb | 21 +--- lib/bundler/dependency.rb | 4 +- lib/bundler/lazy_specification.rb | 16 ++- lib/bundler/resolver.rb | 49 ++++---- lib/bundler/resolver/spec_group.rb | 14 +-- lib/bundler/rubygems_integration.rb | 1 - lib/bundler/stub_specification.rb | 2 - .../lib/net/http/persistent.rb | 9 +- lib/bundler/version.rb | 2 +- lib/rubygems.rb | 2 +- lib/rubygems/resolver/api_set.rb | 2 +- lib/rubygems/source.rb | 1 + spec/bundler/bundler/cli_spec.rb | 4 +- spec/bundler/bundler/definition_spec.rb | 40 +------ spec/bundler/commands/check_spec.rb | 9 +- spec/bundler/commands/exec_spec.rb | 43 +++++++ spec/bundler/commands/outdated_spec.rb | 11 ++ .../install/gemfile/specific_platform_spec.rb | 57 ++++++--- spec/bundler/install/gems/resolving_spec.rb | 6 +- spec/bundler/lock/lockfile_spec.rb | 4 +- spec/bundler/realworld/edgecases_spec.rb | 111 ++++++++++++++++++ spec/bundler/support/artifice/vcr.rb | 1 + spec/bundler/support/platforms.rb | 2 +- test/rubygems/test_gem_resolver_api_set.rb | 29 +++++ 27 files changed, 329 insertions(+), 129 deletions(-) diff --git a/lib/bundler.rb b/lib/bundler.rb index 0ddd2c7f88..7a01de5ddb 100644 --- a/lib/bundler.rb +++ b/lib/bundler.rb @@ -212,6 +212,15 @@ module Bundler end end + def locked_bundler_version + return nil unless defined?(@definition) && @definition + + locked_gems = definition.locked_gems + return nil unless locked_gems + + locked_gems.bundler_version + end + def ruby_scope "#{Bundler.rubygems.ruby_engine}/#{RbConfig::CONFIG["ruby_version"]}" end @@ -602,8 +611,9 @@ EOF reset_rubygems! end - def reset_settings! + def reset_settings_and_root! @settings = nil + @root = nil end def reset_paths! diff --git a/lib/bundler/cli.rb b/lib/bundler/cli.rb index e2dceb98d5..2f495d427d 100644 --- a/lib/bundler/cli.rb +++ b/lib/bundler/cli.rb @@ -57,7 +57,7 @@ module Bundler custom_gemfile = options[:gemfile] || Bundler.settings[:gemfile] if custom_gemfile && !custom_gemfile.empty? Bundler::SharedHelpers.set_env "BUNDLE_GEMFILE", File.expand_path(custom_gemfile) - Bundler.reset_settings! + Bundler.reset_settings_and_root! end Bundler.settings.set_command_option_if_given :retry, options[:retry] diff --git a/lib/bundler/cli/outdated.rb b/lib/bundler/cli/outdated.rb index b8d9be20b6..6a1789e235 100644 --- a/lib/bundler/cli/outdated.rb +++ b/lib/bundler/cli/outdated.rb @@ -76,6 +76,8 @@ module Bundler next unless gems.empty? || gems.include?(current_spec.name) active_spec = retrieve_active_spec(definition, current_spec) + next unless active_spec + next unless filter_options_patch.empty? || update_present_via_semver_portions(current_spec, active_spec, options) gem_outdated = Gem::Version.new(active_spec.version) > Gem::Version.new(current_spec.version) @@ -229,8 +231,6 @@ module Bundler end def update_present_via_semver_portions(current_spec, active_spec, options) - return false if active_spec.nil? - current_major = current_spec.version.segments.first active_major = active_spec.version.segments.first diff --git a/lib/bundler/definition.rb b/lib/bundler/definition.rb index 4cf4f76084..fdd093fbb3 100644 --- a/lib/bundler/definition.rb +++ b/lib/bundler/definition.rb @@ -269,7 +269,9 @@ module Bundler else # Run a resolve against the locally available gems Bundler.ui.debug("Found changes from the lockfile, re-resolving dependencies because #{change_reason}") - last_resolve.merge Resolver.resolve(expanded_dependencies, index, source_requirements, last_resolve, gem_version_promoter, additional_base_requirements_for_resolve, platforms) + platforms_for_resolve = platforms.one? {|p| generic(p) == Gem::Platform::RUBY } ? platforms : platforms.reject{|p| p == Gem::Platform::RUBY } + expanded_dependencies = expand_dependencies(dependencies + metadata_dependencies, @remote, platforms_for_resolve.map {|p| generic(p) }) + last_resolve.merge Resolver.resolve(expanded_dependencies, index, source_requirements, last_resolve, gem_version_promoter, additional_base_requirements_for_resolve, platforms_for_resolve) end # filter out gems that _can_ be installed on multiple platforms, but don't need @@ -548,11 +550,7 @@ module Bundler private def add_current_platform - current_platforms.each {|platform| add_platform(platform) } - end - - def current_platforms - [local_platform, generic_local_platform].uniq + add_platform(local_platform) end def change_reason @@ -847,14 +845,6 @@ module Bundler @locked_specs[dep].any? {|s| s.satisfies?(dep) && (!dep.source || s.source.include?(dep.source)) } end - # This list of dependencies is only used in #resolve, so it's OK to add - # the metadata dependencies here - def expanded_dependencies - @expanded_dependencies ||= begin - expand_dependencies(dependencies + metadata_dependencies, @remote) - end - end - def metadata_dependencies @metadata_dependencies ||= begin ruby_versions = ruby_version_requirements(@ruby_version) @@ -881,7 +871,8 @@ module Bundler end end - def expand_dependencies(dependencies, remote = false) + def expand_dependencies(dependencies, remote = false, platforms = nil) + platforms ||= @platforms deps = [] dependencies.each do |dep| dep = Dependency.new(dep, ">= 0") unless dep.respond_to?(:name) diff --git a/lib/bundler/dependency.rb b/lib/bundler/dependency.rb index 26e5f3d1a5..af07e8bc36 100644 --- a/lib/bundler/dependency.rb +++ b/lib/bundler/dependency.rb @@ -96,9 +96,11 @@ module Bundler def gem_platforms(valid_platforms) return valid_platforms if @platforms.empty? + valid_generic_platforms = valid_platforms.map {|p| [p, GemHelpers.generic(p)] }.to_h @gem_platforms ||= expanded_platforms.compact.uniq - valid_platforms & @gem_platforms + filtered_generic_platforms = valid_generic_platforms.values & @gem_platforms + valid_generic_platforms.select {|_, v| filtered_generic_platforms.include?(v) }.keys end def expanded_platforms diff --git a/lib/bundler/lazy_specification.rb b/lib/bundler/lazy_specification.rb index 22bf0f3f6f..7b1d28b0c3 100644 --- a/lib/bundler/lazy_specification.rb +++ b/lib/bundler/lazy_specification.rb @@ -82,7 +82,7 @@ module Bundler search_object = if source.is_a?(Source::Path) Dependency.new(name, version) else - self + ruby_platform_materializes_to_ruby_platform? ? self : Dependency.new(name, version) end platform_object = Gem::Platform.new(platform) candidates = source.specs.search(search_object) @@ -129,5 +129,19 @@ module Bundler @specification.send(method, *args, &blk) end + + # + # Bundler 2.2.0 was the first version that records the full resolution + # including platform specific gems in the lockfile, which means that if a + # gem with RUBY platform is recorded, the RUBY platform version of the gem + # should be installed. Previously bundler would record only generic versions + # in the lockfile and then install the most specific platform variant if + # available. + # + def ruby_platform_materializes_to_ruby_platform? + locked_bundler_version = Bundler.locked_bundler_version + + locked_bundler_version.nil? || Gem::Version.new(locked_bundler_version) >= Gem::Version.new("2.2.0") + end end end diff --git a/lib/bundler/resolver.rb b/lib/bundler/resolver.rb index 327c170fbe..4bbcbd1162 100644 --- a/lib/bundler/resolver.rb +++ b/lib/bundler/resolver.rb @@ -75,7 +75,7 @@ module Bundler return unless debug? debug_info = yield debug_info = debug_info.inspect unless debug_info.is_a?(String) - warn debug_info.split("\n").map {|s| "BUNDLER: " + " " * depth + s } + puts debug_info.split("\n").map {|s| "BUNDLER: " + " " * depth + s } end def debug? @@ -106,18 +106,19 @@ module Bundler specification.dependencies_for_activated_platforms end - def search_for(dependency) - platform = dependency.__platform - dependency = dependency.dep unless dependency.is_a? Gem::Dependency - search = @search_for[dependency] ||= begin + def search_for(dependency_proxy) + platform = dependency_proxy.__platform + dependency = dependency_proxy.dep + @search_for[dependency_proxy] ||= begin + name = dependency.name index = index_for(dependency) - results = index.search(dependency, @base[dependency.name]) + results = index.search(dependency, @base[name]) - if vertex = @base_dg.vertex_named(dependency.name) + if vertex = @base_dg.vertex_named(name) locked_requirement = vertex.payload.requirement end - if !@prerelease_specified[dependency.name] && (!@use_gvp || locked_requirement.nil?) + if !@prerelease_specified[name] && (!@use_gvp || locked_requirement.nil?) # Move prereleases to the beginning of the list, so they're considered # last during resolution. pre, results = results.partition {|spec| spec.version.prerelease? } @@ -145,31 +146,25 @@ module Bundler end # GVP handles major itself, but it's still a bit risky to trust it with it # until we get it settled with new behavior. For 2.x it can take over all cases. - if !@use_gvp + search = if !@use_gvp spec_groups else @gem_version_promoter.sort_versions(dependency, spec_groups) end - end - selected_sgs = [] - search.each do |sg| - next unless sg.for?(platform) - # Add a spec group for "non platform specific spec" as the fallback - # spec group. - sg_ruby = sg.copy_for(Gem::Platform::RUBY) - selected_sgs << sg_ruby if sg_ruby - sg_all_platforms = nil - all_platforms = @platforms + [platform] - self.class.sort_platforms(all_platforms).reverse_each do |other_platform| - if sg_all_platforms.nil? - sg_all_platforms = sg.copy_for(other_platform) - else - sg_all_platforms.activate_platform!(other_platform) - end + selected_sgs = [] + search.each do |sg| + next unless sg.for?(platform) + sg_all_platforms = sg.copy_for(self.class.sort_platforms(@platforms).reverse) + selected_sgs << sg_all_platforms + + next if sg_all_platforms.activated_platforms == [Gem::Platform::RUBY] + # Add a spec group for "non platform specific spec" as the fallback + # spec group. + sg_ruby = sg.copy_for([Gem::Platform::RUBY]) + selected_sgs.insert(-2, sg_ruby) if sg_ruby end - selected_sgs << sg_all_platforms + selected_sgs end - selected_sgs end def index_for(dependency) diff --git a/lib/bundler/resolver/spec_group.rb b/lib/bundler/resolver/spec_group.rb index 8b5759cfad..38dc175ff9 100644 --- a/lib/bundler/resolver/spec_group.rb +++ b/lib/bundler/resolver/spec_group.rb @@ -6,7 +6,7 @@ module Bundler include GemHelpers attr_accessor :name, :version, :source - attr_accessor :ignores_bundler_dependencies + attr_accessor :ignores_bundler_dependencies, :activated_platforms def initialize(all_specs) @all_specs = all_specs @@ -32,17 +32,13 @@ module Bundler end.compact.uniq end - def activate_platform!(platform) - return unless for?(platform) - return if @activated_platforms.include?(platform) - @activated_platforms << platform - end + def copy_for(platforms) + platforms.select! {|p| for?(p) } + return unless platforms.any? - def copy_for(platform) copied_sg = self.class.new(@all_specs) copied_sg.ignores_bundler_dependencies = @ignores_bundler_dependencies - return nil unless copied_sg.for?(platform) - copied_sg.activate_platform!(platform) + copied_sg.activated_platforms = platforms copied_sg end diff --git a/lib/bundler/rubygems_integration.rb b/lib/bundler/rubygems_integration.rb index 9125a24172..c577001043 100644 --- a/lib/bundler/rubygems_integration.rb +++ b/lib/bundler/rubygems_integration.rb @@ -565,7 +565,6 @@ module Bundler end def all_specs - require_relative "remote_specification" Gem::Specification.stubs.map do |stub| StubSpecification.from_stub(stub) end diff --git a/lib/bundler/stub_specification.rb b/lib/bundler/stub_specification.rb index a45e28b8a7..2456d268da 100644 --- a/lib/bundler/stub_specification.rb +++ b/lib/bundler/stub_specification.rb @@ -1,7 +1,5 @@ # frozen_string_literal: true -require_relative "remote_specification" - module Bundler class StubSpecification < RemoteSpecification def self.from_stub(stub) diff --git a/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent.rb b/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent.rb index d0ab956faf..beff6d658b 100644 --- a/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent.rb +++ b/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent.rb @@ -159,7 +159,14 @@ class Bundler::Persistent::Net::HTTP::Persistent # limits (typically windows). if Process.const_defined? :RLIMIT_NOFILE - DEFAULT_POOL_SIZE = Process.getrlimit(Process::RLIMIT_NOFILE).first / 4 + open_file_limits = Process.getrlimit(Process::RLIMIT_NOFILE) + + # Under JRuby on Windows Process responds to `getrlimit` but returns something that does not match docs + if open_file_limits.respond_to?(:first) + DEFAULT_POOL_SIZE = open_file_limits.first / 4 + else + DEFAULT_POOL_SIZE = 256 + end else DEFAULT_POOL_SIZE = 256 end diff --git a/lib/bundler/version.rb b/lib/bundler/version.rb index c865621acb..b8b331d85e 100644 --- a/lib/bundler/version.rb +++ b/lib/bundler/version.rb @@ -1,7 +1,7 @@ # frozen_string_literal: false module Bundler - VERSION = "2.2.0".freeze + VERSION = "2.2.1".freeze def self.bundler_major_version @bundler_major_version ||= VERSION.split(".").first.to_i diff --git a/lib/rubygems.rb b/lib/rubygems.rb index e6a3c63c60..7596585482 100644 --- a/lib/rubygems.rb +++ b/lib/rubygems.rb @@ -8,7 +8,7 @@ require 'rbconfig' module Gem - VERSION = "3.2.0".freeze + VERSION = "3.2.1".freeze end # Must be first since it unloads the prelude from 1.9.2 diff --git a/lib/rubygems/resolver/api_set.rb b/lib/rubygems/resolver/api_set.rb index 19c59a315b..cafcd5b472 100644 --- a/lib/rubygems/resolver/api_set.rb +++ b/lib/rubygems/resolver/api_set.rb @@ -52,7 +52,7 @@ class Gem::Resolver::APISet < Gem::Resolver::Set end versions(req.name).each do |ver| - if req.dependency.match? req.name, ver[:number] + if req.dependency.match? req.name, ver[:number], @prerelease res << Gem::Resolver::APISpecification.new(self, ver) end end diff --git a/lib/rubygems/source.rb b/lib/rubygems/source.rb index 891cc3e644..a2848112e7 100644 --- a/lib/rubygems/source.rb +++ b/lib/rubygems/source.rb @@ -148,6 +148,7 @@ class Gem::Source spec = Gem::Util.inflate spec if update_cache? + require "fileutils" FileUtils.mkdir_p cache_dir File.open local_spec, 'wb' do |io| diff --git a/spec/bundler/bundler/cli_spec.rb b/spec/bundler/bundler/cli_spec.rb index dc7d4a50aa..ccf957d6df 100644 --- a/spec/bundler/bundler/cli_spec.rb +++ b/spec/bundler/bundler/cli_spec.rb @@ -7,10 +7,10 @@ using Module.new { # non-tty. refine Spec::Helpers do def out - super.gsub(/.[\b]/, '') + super.gsub(/.[\b]/, "") end end -} +} if RUBY_VERSION >= "2.4" RSpec.describe "bundle executable" do it "returns non-zero exit status when passed unrecognized options" do diff --git a/spec/bundler/bundler/definition_spec.rb b/spec/bundler/bundler/definition_spec.rb index d0ebb37933..dcdde75315 100644 --- a/spec/bundler/bundler/definition_spec.rb +++ b/spec/bundler/bundler/definition_spec.rb @@ -34,45 +34,7 @@ RSpec.describe Bundler::Definition do end describe "detects changes" do - it "for a path gem with changes", :bundler => "< 3" do - build_lib "foo", "1.0", :path => lib_path("foo") - - install_gemfile <<-G - source "#{file_uri_for(gem_repo1)}" - gem "foo", :path => "#{lib_path("foo")}" - G - - build_lib "foo", "1.0", :path => lib_path("foo") do |s| - s.add_dependency "rack", "1.0" - end - - bundle :install, :env => { "DEBUG" => "1" } - - expect(out).to match(/re-resolving dependencies/) - lockfile_should_be <<-G - PATH - remote: #{lib_path("foo")} - specs: - foo (1.0) - rack (= 1.0) - - GEM - remote: #{file_uri_for(gem_repo1)}/ - specs: - rack (1.0.0) - - PLATFORMS - #{lockfile_platforms} - - DEPENDENCIES - foo! - - BUNDLED WITH - #{Bundler::VERSION} - G - end - - it "for a path gem with changes", :bundler => "3" do + it "for a path gem with changes" do build_lib "foo", "1.0", :path => lib_path("foo") install_gemfile <<-G diff --git a/spec/bundler/commands/check_spec.rb b/spec/bundler/commands/check_spec.rb index 5a746591b3..fdf3bc7d51 100644 --- a/spec/bundler/commands/check_spec.rb +++ b/spec/bundler/commands/check_spec.rb @@ -311,6 +311,8 @@ RSpec.describe "bundle check" do end before do + bundle "config set --local path vendor/bundle" + install_gemfile <<-G source "#{file_uri_for(gem_repo1)}" gem "rack" @@ -336,9 +338,10 @@ RSpec.describe "bundle check" do context "is older" do it "does not change the lock" do - lockfile lock_with("1.10.1") - bundle :check, :raise_on_error => false - lockfile_should_be lock_with("1.10.1") + system_gems "bundler-1.18.0" + lockfile lock_with("1.18.0") + bundle :check + lockfile_should_be lock_with("1.18.0") end end end diff --git a/spec/bundler/commands/exec_spec.rb b/spec/bundler/commands/exec_spec.rb index 4c34964053..85f8ceef62 100644 --- a/spec/bundler/commands/exec_spec.rb +++ b/spec/bundler/commands/exec_spec.rb @@ -938,6 +938,49 @@ __FILE__: #{path.to_s.inspect} end end + context "when gemfile and path are configured", :ruby_repo do + before do + skip "https://github.com/rubygems/rubygems/issues/3351" if Gem.win_platform? + + build_repo2 do + build_gem "rails", "6.1.0" do |s| + s.executables = "rails" + end + end + + bundle "config set path vendor/bundle" + bundle "config set gemfile gemfiles/rack_6_1.gemfile" + + create_file(bundled_app("gemfiles/rack_6_1.gemfile"), <<~RUBY) + source "#{file_uri_for(gem_repo2)}" + + gem "rails", "6.1.0" + RUBY + + # A Gemfile needs to be in the root to trick bundler's root resolution + create_file(bundled_app("Gemfile")) + + bundle "install" + end + + it "can still find gems after a nested subprocess" do + script = bundled_app("bin/myscript") + + create_file(script, <<~RUBY) + #!#{Gem.ruby} + + puts `bundle exec rails` + RUBY + + script.chmod(0o777) + + bundle "exec #{script}" + + expect(err).to be_empty + expect(out).to eq("6.1.0") + end + end + context "with a system gem that shadows a default gem" do let(:openssl_version) { "99.9.9" } let(:expected) { ruby "gem 'openssl', '< 999999'; require 'openssl'; puts OpenSSL::VERSION", :artifice => nil, :raise_on_error => false } diff --git a/spec/bundler/commands/outdated_spec.rb b/spec/bundler/commands/outdated_spec.rb index 1faee23f26..0ee8bd425a 100644 --- a/spec/bundler/commands/outdated_spec.rb +++ b/spec/bundler/commands/outdated_spec.rb @@ -429,6 +429,17 @@ RSpec.describe "bundle outdated" do expect(out).to end_with(expected_output) end + it "doesn't crash when some deps unused on the current platform" do + install_gemfile <<-G + source "#{file_uri_for(gem_repo2)}" + gem "activesupport", platforms: [:ruby_22] + G + + bundle :outdated, filter_strict_option => true + + expect(out).to end_with("Bundle up to date!") + end + it "only reports gem dependencies when they can actually be updated" do install_gemfile <<-G source "#{file_uri_for(gem_repo2)}" diff --git a/spec/bundler/install/gemfile/specific_platform_spec.rb b/spec/bundler/install/gemfile/specific_platform_spec.rb index 82492e78cb..d85c670b64 100644 --- a/spec/bundler/install/gemfile/specific_platform_spec.rb +++ b/spec/bundler/install/gemfile/specific_platform_spec.rb @@ -9,36 +9,67 @@ RSpec.describe "bundle install with specific platforms" do context "when on a darwin machine" do before { simulate_platform "x86_64-darwin-15" } - it "locks to both the specific darwin platform and ruby" do + it "locks to the specific darwin platform" do setup_multiplatform_gem install_gemfile(google_protobuf) allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile) - expect(the_bundle.locked_gems.platforms).to eq([pl("ruby"), pl("x86_64-darwin-15")]) + expect(the_bundle.locked_gems.platforms).to eq([pl("x86_64-darwin-15")]) expect(the_bundle).to include_gem("google-protobuf 3.0.0.alpha.5.0.5.1 universal-darwin") expect(the_bundle.locked_gems.specs.map(&:full_name)).to eq(%w[ - google-protobuf-3.0.0.alpha.5.0.5.1 google-protobuf-3.0.0.alpha.5.0.5.1-universal-darwin ]) end - it "caches both the universal-darwin and ruby gems when --all-platforms is passed and properly picks them up on further bundler invocations" do + it "understands that a non-plaform specific gem in a old lockfile doesn't necessarily mean installing the non-specific variant" do + setup_multiplatform_gem + + system_gems "bundler-2.1.4" + + # Consistent location to install and look for gems + bundle "config set --local path vendor/bundle", :env => { "BUNDLER_VERSION" => "2.1.4" } + + install_gemfile(google_protobuf, :env => { "BUNDLER_VERSION" => "2.1.4" }) + + # simulate lockfile created with old bundler, which only locks for ruby platform + lockfile <<-L + GEM + remote: #{file_uri_for(gem_repo2)}/ + specs: + google-protobuf (3.0.0.alpha.5.0.5.1) + + PLATFORMS + ruby + + DEPENDENCIES + google-protobuf + + BUNDLED WITH + 2.1.4 + L + + # force strict usage of the lock file by setting frozen mode + bundle "config set --local frozen true", :env => { "BUNDLER_VERSION" => "2.1.4" } + + # make sure the platform that got actually installed with the old bundler is used + expect(the_bundle).to include_gem("google-protobuf 3.0.0.alpha.5.0.5.1 universal-darwin") + end + + it "caches the universal-darwin gem when --all-platforms is passed and properly picks it up on further bundler invocations" do setup_multiplatform_gem gemfile(google_protobuf) bundle "cache --all-platforms" - expect([cached_gem("google-protobuf-3.0.0.alpha.5.0.5.1"), cached_gem("google-protobuf-3.0.0.alpha.5.0.5.1-universal-darwin")]). - to all(exist) + expect(cached_gem("google-protobuf-3.0.0.alpha.5.0.5.1-universal-darwin")).to exist bundle "install --verbose" expect(err).to be_empty end - it "caches both the universal-darwin and ruby gems when cache_all_platforms is configured and properly picks them up on further bundler invocations" do + it "caches the universal-darwin gem when cache_all_platforms is configured and properly picks it up on further bundler invocations" do setup_multiplatform_gem gemfile(google_protobuf) bundle "config set --local cache_all_platforms true" bundle "cache" - expect([cached_gem("google-protobuf-3.0.0.alpha.5.0.5.1"), cached_gem("google-protobuf-3.0.0.alpha.5.0.5.1-universal-darwin")]). - to all(exist) + expect(cached_gem("google-protobuf-3.0.0.alpha.5.0.5.1-universal-darwin")).to exist bundle "install --verbose" expect(err).to be_empty @@ -87,10 +118,9 @@ RSpec.describe "bundle install with specific platforms" do G allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile) - expect(the_bundle.locked_gems.platforms).to eq([pl("ruby"), pl("x86_64-darwin-15")]) + expect(the_bundle.locked_gems.platforms).to eq([pl("x86_64-darwin-15")]) expect(the_bundle).to include_gems("facter 2.4.6 universal-darwin", "CFPropertyList 1.0") expect(the_bundle.locked_gems.specs.map(&:full_name)).to eq(["CFPropertyList-1.0", - "facter-2.4.6", "facter-2.4.6-universal-darwin"]) end @@ -104,9 +134,8 @@ RSpec.describe "bundle install with specific platforms" do install_gemfile(google_protobuf) bundle "lock --add-platform=#{x64_mingw}" - expect(the_bundle.locked_gems.platforms).to eq([rb, x64_mingw, pl("x86_64-darwin-15")]) + expect(the_bundle.locked_gems.platforms).to eq([x64_mingw, pl("x86_64-darwin-15")]) expect(the_bundle.locked_gems.specs.map(&:full_name)).to eq(%w[ - google-protobuf-3.0.0.alpha.5.0.5.1 google-protobuf-3.0.0.alpha.5.0.5.1-universal-darwin google-protobuf-3.0.0.alpha.5.0.5.1-x64-mingw32 ]) @@ -117,7 +146,7 @@ RSpec.describe "bundle install with specific platforms" do install_gemfile(google_protobuf) bundle "lock --add-platform=#{java}" - expect(the_bundle.locked_gems.platforms).to eq([java, rb, pl("x86_64-darwin-15")]) + expect(the_bundle.locked_gems.platforms).to eq([java, pl("x86_64-darwin-15")]) expect(the_bundle.locked_gems.specs.map(&:full_name)).to eq(%w[ google-protobuf-3.0.0.alpha.5.0.5.1 google-protobuf-3.0.0.alpha.5.0.5.1-universal-darwin diff --git a/spec/bundler/install/gems/resolving_spec.rb b/spec/bundler/install/gems/resolving_spec.rb index 1c01ce588b..4384a731cd 100644 --- a/spec/bundler/install/gems/resolving_spec.rb +++ b/spec/bundler/install/gems/resolving_spec.rb @@ -116,7 +116,7 @@ RSpec.describe "bundle install with install-time dependencies" do bundle :install, :env => { "BUNDLER_DEBUG_RESOLVER" => "1" } - expect(err).to include("BUNDLER: Starting resolution") + expect(out).to include("BUNDLER: Starting resolution") end end @@ -130,7 +130,7 @@ RSpec.describe "bundle install with install-time dependencies" do bundle :install, :env => { "DEBUG_RESOLVER" => "1" } - expect(err).to include("BUNDLER: Starting resolution") + expect(out).to include("BUNDLER: Starting resolution") end end @@ -147,7 +147,7 @@ RSpec.describe "bundle install with install-time dependencies" do activated_groups = "net_b (1.0) (ruby)" activated_groups += ", net_b (1.0) (#{local_platforms.join(", ")})" if local_platforms.any? && local_platforms != ["ruby"] - expect(err).to include(" net_b"). + expect(out).to include(" net_b"). and include("BUNDLER: Starting resolution"). and include("BUNDLER: Finished resolution"). and include("Attempting to activate [#{activated_groups}]") diff --git a/spec/bundler/lock/lockfile_spec.rb b/spec/bundler/lock/lockfile_spec.rb index 941cbd13e0..0d340b070e 100644 --- a/spec/bundler/lock/lockfile_spec.rb +++ b/spec/bundler/lock/lockfile_spec.rb @@ -981,7 +981,7 @@ RSpec.describe "the lockfile format" do G end - it "persists the spec's platform and specific platform to the lockfile" do + it "persists the spec's specific platform to the lockfile" do build_repo2 do build_gem "platform_specific", "1.0" do |s| s.platform = Gem::Platform.new("universal-java-16") @@ -999,11 +999,9 @@ RSpec.describe "the lockfile format" do GEM remote: #{file_uri_for(gem_repo2)}/ specs: - platform_specific (1.0-java) platform_specific (1.0-universal-java-16) PLATFORMS - java universal-java-16 DEPENDENCIES diff --git a/spec/bundler/realworld/edgecases_spec.rb b/spec/bundler/realworld/edgecases_spec.rb index e5600bb1c1..0f19cc7842 100644 --- a/spec/bundler/realworld/edgecases_spec.rb +++ b/spec/bundler/realworld/edgecases_spec.rb @@ -345,4 +345,115 @@ RSpec.describe "real world edgecases", :realworld => true, :sometimes => true do expect(err).to include("You have one or more invalid gemspecs that need to be fixed.") expect(err).to include("resque-scheduler 2.2.0 has an invalid gemspec") end + + it "doesn't hang on big gemfile" do + skip "Only for ruby 2.7.2" if RUBY_VERSION != "2.7.2" + + gemfile <<~G + # frozen_string_literal: true + + source "https://rubygems.org" + + ruby "2.7.2" + + gem "rails" + gem "pg", ">= 0.18", "< 2.0" + gem "goldiloader" + gem "awesome_nested_set" + gem "circuitbox" + gem "passenger" + gem "globalid" + gem "rack-cors" + gem "rails-pg-extras" + gem "linear_regression_trend" + gem "rack-protection" + gem "pundit" + gem "remote_ip_proxy_scrubber" + gem "bcrypt" + gem "searchkick" + gem "excon" + gem "faraday_middleware-aws-sigv4" + gem "typhoeus" + gem "sidekiq" + gem "sidekiq-undertaker" + gem "sidekiq-cron" + gem "storext" + gem "appsignal" + gem "fcm" + gem "business_time" + gem "tzinfo" + gem "holidays" + gem "bigdecimal" + gem "progress_bar" + gem "redis" + gem "hiredis" + gem "state_machines" + gem "state_machines-audit_trail" + gem "state_machines-activerecord" + gem "interactor" + gem "ar_transaction_changes" + gem "redis-rails" + gem "seed_migration" + gem "lograge" + gem "graphiql-rails", group: :development + gem "graphql" + gem "pusher" + gem "rbnacl" + gem "jwt" + gem "json-schema" + gem "discard" + gem "money" + gem "strip_attributes" + gem "validates_email_format_of" + gem "audited" + gem "concurrent-ruby" + gem "with_advisory_lock" + + group :test do + gem "rspec-sidekiq" + gem "simplecov", require: false + end + + group :development, :test do + gem "byebug", platform: :mri + gem "guard" + gem "guard-bundler" + gem "guard-rspec" + gem "rb-fsevent" + gem "rspec_junit_formatter" + gem "rspec-collection_matchers" + gem "rspec-rails" + gem "rspec-retry" + gem "state_machines-rspec" + gem "dotenv-rails" + gem "database_cleaner-active_record" + gem "database_cleaner-redis" + gem "timecop" + end + + gem "factory_bot_rails" + gem "faker" + + group :development do + gem "listen" + gem "sql_queries_count" + gem "rubocop" + gem "rubocop-performance" + gem "rubocop-rspec" + gem "rubocop-rails" + gem "brakeman" + gem "bundler-audit" + gem "solargraph" + gem "annotate" + end + G + + bundle :lock, :env => { "DEBUG_RESOLVER" => "1" } + + if Bundler.feature_flag.bundler_3_mode? + expect(out).to include("BUNDLER: Finished resolution (2492 steps)") + else + expect(out).to include("BUNDLER: Finished resolution (2722 steps)") + end + end end diff --git a/spec/bundler/support/artifice/vcr.rb b/spec/bundler/support/artifice/vcr.rb index 19670287b3..bd13a338b4 100644 --- a/spec/bundler/support/artifice/vcr.rb +++ b/spec/bundler/support/artifice/vcr.rb @@ -56,6 +56,7 @@ class BundlerVCRHTTP < Net::HTTP response = http.request_without_vcr(request, body, &response_block) @recording = false unless @recording + require "fileutils" FileUtils.mkdir_p(File.dirname(request_path)) binwrite(request_path, request_to_string(request)) binwrite(response_path, response_to_string(response)) diff --git a/spec/bundler/support/platforms.rb b/spec/bundler/support/platforms.rb index ab203919e7..0cb7f7cd29 100644 --- a/spec/bundler/support/platforms.rb +++ b/spec/bundler/support/platforms.rb @@ -94,7 +94,7 @@ module Spec end def local_platforms - [local, specific_local_platform].uniq + [specific_local_platform] end end end diff --git a/test/rubygems/test_gem_resolver_api_set.rb b/test/rubygems/test_gem_resolver_api_set.rb index 4b545b1b9a..8a838c761b 100644 --- a/test/rubygems/test_gem_resolver_api_set.rb +++ b/test/rubygems/test_gem_resolver_api_set.rb @@ -55,6 +55,35 @@ class TestGemResolverAPISet < Gem::TestCase assert_equal expected, set.find_all(a_dep) end + def test_find_all_prereleases + spec_fetcher + + data = [ + { :name => 'a', + :number => '1', + :platform => 'ruby', + :dependencies => [] }, + { :name => 'a', + :number => '2.a', + :platform => 'ruby', + :dependencies => [] }, + ] + + @fetcher.data["#{@dep_uri}?gems=a"] = Marshal.dump data + + set = @DR::APISet.new @dep_uri + set.prerelease = true + + a_dep = @DR::DependencyRequest.new dep('a'), nil + + expected = [ + @DR::APISpecification.new(set, data.first), + @DR::APISpecification.new(set, data.last), + ] + + assert_equal expected, set.find_all(a_dep) + end + def test_find_all_cache spec_fetcher