diff options
-rw-r--r-- | lib/bundler.rb | 2 | ||||
-rw-r--r-- | lib/bundler/installer/parallel_installer.rb | 4 | ||||
-rw-r--r-- | lib/bundler/plugin/api.rb | 3 | ||||
-rw-r--r-- | lib/bundler/retry.rb | 5 | ||||
-rw-r--r-- | lib/bundler/shared_helpers.rb | 21 | ||||
-rw-r--r-- | lib/bundler/source.rb | 4 | ||||
-rw-r--r-- | spec/bundler/retry_spec.rb | 4 | ||||
-rw-r--r-- | spec/commands/install_spec.rb | 4 | ||||
-rw-r--r-- | spec/install/gemfile_spec.rb | 2 | ||||
-rw-r--r-- | spec/realworld/mirror_probe_spec.rb | 16 | ||||
-rw-r--r-- | spec/runtime/inline_spec.rb | 8 | ||||
-rw-r--r-- | spec/support/artifice/fail.rb | 39 | ||||
-rw-r--r-- | spec/support/helpers.rb | 20 |
13 files changed, 85 insertions, 47 deletions
diff --git a/lib/bundler.rb b/lib/bundler.rb index 0dcaa03965..9b96075ca9 100644 --- a/lib/bundler.rb +++ b/lib/bundler.rb @@ -7,7 +7,6 @@ require "tmpdir" require "bundler/errors" require "bundler/environment_preserver" -require "bundler/gem_remote_fetcher" require "bundler/plugin" require "bundler/rubygems_ext" require "bundler/rubygems_integration" @@ -32,6 +31,7 @@ module Bundler autoload :FeatureFlag, "bundler/feature_flag" autoload :GemHelper, "bundler/gem_helper" autoload :GemHelpers, "bundler/gem_helpers" + autoload :GemRemoteFetcher, "bundler/gem_remote_fetcher" autoload :GemVersionPromoter, "bundler/gem_version_promoter" autoload :Graph, "bundler/graph" autoload :Index, "bundler/index" diff --git a/lib/bundler/installer/parallel_installer.rb b/lib/bundler/installer/parallel_installer.rb index 12f11bb5f0..c973233d99 100644 --- a/lib/bundler/installer/parallel_installer.rb +++ b/lib/bundler/installer/parallel_installer.rb @@ -88,6 +88,10 @@ module Bundler end def call + # Since `autoload` has the potential for threading issues on 1.8.7 + # TODO: remove in bundler 2.0 + require "bundler/gem_remote_fetcher" if RUBY_VERSION < "1.9" + enqueue_specs process_specs until @specs.all?(&:installed?) || @specs.any?(&:failed?) handle_error if @specs.any?(&:failed?) diff --git a/lib/bundler/plugin/api.rb b/lib/bundler/plugin/api.rb index bd7cef5382..a2d5cbb4ac 100644 --- a/lib/bundler/plugin/api.rb +++ b/lib/bundler/plugin/api.rb @@ -1,5 +1,4 @@ # frozen_string_literal: true -require "bundler/plugin/api/source" module Bundler # This is the interfacing class represents the API that we intend to provide @@ -24,6 +23,8 @@ module Bundler # and hooks). module Plugin class API + autoload :Source, "bundler/plugin/api/source" + # The plugins should declare that they handle a command through this helper. # # @param [String] command being handled by them diff --git a/lib/bundler/retry.rb b/lib/bundler/retry.rb index a7a72feed5..092fb866b3 100644 --- a/lib/bundler/retry.rb +++ b/lib/bundler/retry.rb @@ -43,7 +43,10 @@ module Bundler def fail_attempt(e) @failed = true - raise e if last_attempt? || @exceptions.any? {|k| e.is_a?(k) } + if last_attempt? || @exceptions.any? {|k| e.is_a?(k) } + Bundler.ui.info "" unless Bundler.ui.debug? + raise e + end return true unless name Bundler.ui.info "" unless Bundler.ui.debug? # Add new line incase dots preceded this Bundler.ui.warn "Retrying #{name} due to error (#{current_run.next}/#{total_runs}): #{e.class} #{e.message}", Bundler.ui.debug? diff --git a/lib/bundler/shared_helpers.rb b/lib/bundler/shared_helpers.rb index 62ade29e30..613609f25f 100644 --- a/lib/bundler/shared_helpers.rb +++ b/lib/bundler/shared_helpers.rb @@ -8,6 +8,7 @@ require "bundler/current_ruby" module Gem class Dependency + # This is only needed for RubyGems < 1.4 unless method_defined? :requirement def requirement version_requirements @@ -18,8 +19,6 @@ end module Bundler module SharedHelpers - attr_accessor :gem_loaded - def default_gemfile gemfile = find_gemfile raise GemfileNotFound, "Could not locate Gemfile" unless gemfile @@ -217,22 +216,20 @@ module Bundler def bundler_ruby_lib File.expand_path("../..", __FILE__) end - private :bundler_ruby_lib def clean_load_path # handle 1.9 where system gems are always on the load path - if defined?(::Gem) - me = File.expand_path("../../", __FILE__) - me = /^#{Regexp.escape(me)}/ + return unless defined?(::Gem) - loaded_gem_paths = Bundler.rubygems.loaded_gem_paths + bundler_lib = bundler_ruby_lib - $LOAD_PATH.reject! do |p| - next if File.expand_path(p) =~ me - loaded_gem_paths.delete(p) - end - $LOAD_PATH.uniq! + loaded_gem_paths = Bundler.rubygems.loaded_gem_paths + + $LOAD_PATH.reject! do |p| + next if File.expand_path(p).start_with?(bundler_lib) + loaded_gem_paths.delete(p) end + $LOAD_PATH.uniq! end def prints_major_deprecations? diff --git a/lib/bundler/source.rb b/lib/bundler/source.rb index 9d65d4613b..917e9106e0 100644 --- a/lib/bundler/source.rb +++ b/lib/bundler/source.rb @@ -34,5 +34,9 @@ module Bundler def include?(other) other == self end + + def inspect + "#<#{self.class}:0x#{object_id} #{self}>" + end end end diff --git a/spec/bundler/retry_spec.rb b/spec/bundler/retry_spec.rb index 665ba9f2df..7f5779a5ca 100644 --- a/spec/bundler/retry_spec.rb +++ b/spec/bundler/retry_spec.rb @@ -65,10 +65,10 @@ describe Bundler::Retry do end end - context "with debugging on" do + context "with debugging off" do it "print error message with newlines" do allow(Bundler.ui).to receive(:debug?).and_return(false) - expect(Bundler.ui).to receive(:info).with("") + expect(Bundler.ui).to receive(:info).with("").twice expect(Bundler.ui).to receive(:warn).with(failure_message, false) expect do diff --git a/spec/commands/install_spec.rb b/spec/commands/install_spec.rb index 457fec26cb..0d05766eeb 100644 --- a/spec/commands/install_spec.rb +++ b/spec/commands/install_spec.rb @@ -314,14 +314,14 @@ describe "bundle install with gem sources" do end it "gracefully handles error when rubygems server is unavailable" do - install_gemfile <<-G + install_gemfile <<-G, :artifice => nil source "file://#{gem_repo1}" source "http://localhost:9384" gem 'foo' G - bundle :install + bundle :install, :artifice => nil expect(out).to include("Could not fetch specs from http://localhost:9384/") expect(out).not_to include("file://") end diff --git a/spec/install/gemfile_spec.rb b/spec/install/gemfile_spec.rb index 03ae344987..f6602c0560 100644 --- a/spec/install/gemfile_spec.rb +++ b/spec/install/gemfile_spec.rb @@ -72,7 +72,7 @@ describe "bundle install" do simulate_ruby_version "2.3.0" do simulate_ruby_engine "jruby", "9.1.2.0" do install_gemfile! <<-G - source "https://rubygems.org" + source "file://#{gem_repo1}" ruby "2.3.0", :engine => :jruby, :engine_version => "9.1.2.0" G diff --git a/spec/realworld/mirror_probe_spec.rb b/spec/realworld/mirror_probe_spec.rb index 0fb93b8ab1..5a4a4a1b0a 100644 --- a/spec/realworld/mirror_probe_spec.rb +++ b/spec/realworld/mirror_probe_spec.rb @@ -79,6 +79,22 @@ describe "fetching dependencies with a not available mirror", :realworld => true expect(out).to include("Retrying fetcher due to error (4/4): Bundler::HTTPError Could not fetch specs from #{mirror}") expect(out).to include("Could not fetch specs from #{mirror}") end + + it "prints each error and warning on a new line" do + gemfile <<-G + source "#{original}" + gem 'weakling' + G + + bundle :install + + expect(out).to eq "Fetching source index from #{mirror}/ + +Retrying fetcher due to error (2/4): Bundler::HTTPError Could not fetch specs from #{mirror}/ +Retrying fetcher due to error (3/4): Bundler::HTTPError Could not fetch specs from #{mirror}/ +Retrying fetcher due to error (4/4): Bundler::HTTPError Could not fetch specs from #{mirror}/ +Could not fetch specs from #{mirror}/" + end end context "with a global mirror without a fallback timeout" do diff --git a/spec/runtime/inline_spec.rb b/spec/runtime/inline_spec.rb index 3b08e50e64..15f3723693 100644 --- a/spec/runtime/inline_spec.rb +++ b/spec/runtime/inline_spec.rb @@ -85,12 +85,14 @@ describe "bundler/inline#gemfile" do script <<-RUBY, :artifice => "endpoint" gemfile(true) do - source "https://rubygems.org" + source "https://notaserver.com" gem "activesupport", :require => true end RUBY expect(out).to include("Installing activesupport") + err.gsub! %r{.*lib/sinatra/base\.rb:\d+: warning: constant ::Fixnum is deprecated$}, "" + err.strip! expect(err).to lack_errors expect(exitstatus).to be_zero if exitstatus end @@ -104,7 +106,7 @@ describe "bundler/inline#gemfile" do end end gemfile(true, :ui => MyBundlerUI.new) do - source "https://rubygems.org" + source "https://notaserver.com" gem "activesupport", :require => true end RUBY @@ -196,7 +198,7 @@ describe "bundler/inline#gemfile" do it "installs inline gems when a Gemfile.lock is present" do gemfile <<-G - source "https://rubygems.org" + source "https://notaserver.com" gem "rake" G diff --git a/spec/support/artifice/fail.rb b/spec/support/artifice/fail.rb index 2ef009c7c8..1059c6df4e 100644 --- a/spec/support/artifice/fail.rb +++ b/spec/support/artifice/fail.rb @@ -1,20 +1,39 @@ # frozen_string_literal: true -require File.expand_path("../../path.rb", __FILE__) +require "net/http" +begin + require "net/https" +rescue LoadError + nil # net/https or openssl +end + +# We can't use artifice here because it uses rack -# Set up pretend http gem server with Artifice -$LOAD_PATH.unshift(*Dir[Spec::Path.base_system_gems.join("gems/{artifice,rack,tilt}-*/lib")].map(&:to_s)) -require "artifice" +module Artifice; end # for < 2.0, Net::HTTP::Persistent::SSLReuse -class Fail - def call(env) - raise(exception(env)) +class Fail < Net::HTTP + # Net::HTTP uses a @newimpl instance variable to decide whether + # to use a legacy implementation. Since we are subclassing + # Net::HTTP, we must set it + @newimpl = true + + def request(req, body = nil, &block) + raise(exception(req)) end - def exception(env) + # Ensure we don't start a connect here + def connect + end + + def exception(req) name = ENV.fetch("BUNDLER_SPEC_EXCEPTION") { "Errno::ENETUNREACH" } const = name.split("::").reduce(Object) {|mod, sym| mod.const_get(sym) } - const.new("host down: Bundler spec artifice fail! #{env["PATH_INFO"]}") + const.new("host down: Bundler spec artifice fail! #{req["PATH_INFO"]}") end end -Artifice.activate_with(Fail.new) + +# Replace Net::HTTP with our failing subclass +::Net.class_eval do + remove_const(:HTTP) + const_set(:HTTP, ::Fail) +end diff --git a/spec/support/helpers.rb b/spec/support/helpers.rb index 3ec5d368b9..3912ad068f 100644 --- a/spec/support/helpers.rb +++ b/spec/support/helpers.rb @@ -84,7 +84,7 @@ module Spec with_sudo = options.delete(:sudo) sudo = with_sudo == :preserve_env ? "sudo -E" : "sudo" if with_sudo - options["no-color"] = true unless options.key?("no-color") || cmd.to_s.start_with?("exec", "exe", "ex", "e", "conf") + options["no-color"] = true unless options.key?("no-color") || cmd.to_s =~ /\A(e|ex|exe|exec|conf|confi|config)(\s|\z)/ bundle_bin = options.delete("bundle_bin") || File.expand_path("../../../exe/bundle", __FILE__) @@ -93,7 +93,9 @@ module Spec end requires = options.delete(:requires) || [] - requires << File.expand_path("../artifice/" + options.delete(:artifice) + ".rb", __FILE__) if options.key?(:artifice) + if artifice = options.delete(:artifice) { "fail" unless RSpec.current_example.metadata[:realworld] } + requires << File.expand_path("../artifice/#{artifice}.rb", __FILE__) + end requires << "support/hax" requires_str = requires.map {|r| "-r#{r}" }.join(" ") @@ -119,18 +121,8 @@ module Spec end def bundle_ruby(options = {}) - options["no-color"] = true unless options.key?("no-color") - - bundle_bin = File.expand_path("../../../exe/bundle_ruby", __FILE__) - - requires = options.delete(:requires) || [] - requires << File.expand_path("../artifice/" + options.delete(:artifice) + ".rb", __FILE__) if options.key?(:artifice) - requires_str = requires.map {|r| "-r#{r}" }.join(" ") - - env = (options.delete(:env) || {}).map {|k, v| "#{k}='#{v}' " }.join - cmd = "#{env}#{Gem.ruby} -I#{lib} #{requires_str} #{bundle_bin}" - - sys_exec(cmd) {|i, o, thr| yield i, o, thr if block_given? } + options["bundle_bin"] = File.expand_path("../../../exe/bundle_ruby", __FILE__) + bundle("", options) end def ruby(ruby, options = {}) |