diff options
Diffstat (limited to 'lib/bundler/fetcher')
-rw-r--r-- | lib/bundler/fetcher/base.rb | 22 | ||||
-rw-r--r-- | lib/bundler/fetcher/compact_index.rb | 36 | ||||
-rw-r--r-- | lib/bundler/fetcher/dependency.rb | 10 | ||||
-rw-r--r-- | lib/bundler/fetcher/downloader.rb | 33 | ||||
-rw-r--r-- | lib/bundler/fetcher/gem_remote_fetcher.rb | 16 | ||||
-rw-r--r-- | lib/bundler/fetcher/index.rb | 5 |
6 files changed, 64 insertions, 58 deletions
diff --git a/lib/bundler/fetcher/base.rb b/lib/bundler/fetcher/base.rb index 16cc98273a..cfec2f8e94 100644 --- a/lib/bundler/fetcher/base.rb +++ b/lib/bundler/fetcher/base.rb @@ -6,12 +6,14 @@ module Bundler attr_reader :downloader attr_reader :display_uri attr_reader :remote + attr_reader :gem_remote_fetcher - def initialize(downloader, remote, display_uri) + def initialize(downloader, remote, display_uri, gem_remote_fetcher) raise "Abstract class" if self.class == Base @downloader = downloader @remote = remote @display_uri = display_uri + @gem_remote_fetcher = gem_remote_fetcher end def remote_uri @@ -19,14 +21,12 @@ module Bundler end def fetch_uri - @fetch_uri ||= begin - if remote_uri.host == "rubygems.org" - uri = remote_uri.dup - uri.host = "index.rubygems.org" - uri - else - remote_uri - end + @fetch_uri ||= if remote_uri.host == "rubygems.org" + uri = remote_uri.dup + uri.host = "index.rubygems.org" + uri + else + remote_uri end end @@ -40,9 +40,9 @@ module Bundler private - def log_specs(debug_msg) + def log_specs(&block) if Bundler.ui.debug? - Bundler.ui.debug debug_msg + Bundler.ui.debug yield else Bundler.ui.info ".", false end diff --git a/lib/bundler/fetcher/compact_index.rb b/lib/bundler/fetcher/compact_index.rb index b23176588f..db914839b1 100644 --- a/lib/bundler/fetcher/compact_index.rb +++ b/lib/bundler/fetcher/compact_index.rb @@ -12,17 +12,15 @@ module Bundler method = instance_method(method_name) undef_method(method_name) define_method(method_name) do |*args, &blk| - begin - method.bind(self).call(*args, &blk) - rescue NetworkDownError, CompactIndexClient::Updater::MisMatchedChecksumError => e - raise HTTPError, e.message - rescue AuthenticationRequiredError - # Fail since we got a 401 from the server. - raise - rescue HTTPError => e - Bundler.ui.trace(e) - nil - end + method.bind(self).call(*args, &blk) + rescue NetworkDownError, CompactIndexClient::Updater::MismatchedChecksumError => e + raise HTTPError, e.message + rescue AuthenticationRequiredError, BadAuthenticationError + # Fail since we got a 401 from the server. + raise + rescue HTTPError => e + Bundler.ui.trace(e) + nil end end @@ -37,21 +35,21 @@ module Bundler remaining_gems = gem_names.dup until remaining_gems.empty? - log_specs "Looking up gems #{remaining_gems.inspect}" + log_specs { "Looking up gems #{remaining_gems.inspect}" } deps = begin parallel_compact_index_client.dependencies(remaining_gems) rescue TooManyRequestsError - @bundle_worker.stop if @bundle_worker + @bundle_worker&.stop @bundle_worker = nil # reset it. Not sure if necessary serial_compact_index_client.dependencies(remaining_gems) end - next_gems = deps.map {|d| d[3].map(&:first).flatten(1) }.flatten(1).uniq + next_gems = deps.flat_map {|d| d[3].flat_map(&:first) }.uniq deps.each {|dep| gem_info << dep } complete_gems.concat(deps.map(&:first)).uniq! remaining_gems = next_gems - complete_gems end - @bundle_worker.stop if @bundle_worker + @bundle_worker&.stop @bundle_worker = nil # reset it. Not sure if necessary gem_info @@ -62,13 +60,9 @@ module Bundler Bundler.ui.debug("FIPS mode is enabled, bundler can't use the CompactIndex API") return nil end - if fetch_uri.scheme == "file" - Bundler.ui.debug("Using a local server, bundler won't use the CompactIndex API") - return false - end # Read info file checksums out of /versions, so we can know if gems are up to date compact_index_client.update_and_parse_checksums! - rescue CompactIndexClient::Updater::MisMatchedChecksumError => e + rescue CompactIndexClient::Updater::MismatchedChecksumError => e Bundler.ui.debug(e.message) nil end @@ -127,7 +121,7 @@ module Bundler rescue NetworkDownError => e raise unless Bundler.feature_flag.allow_offline_install? && headers["If-None-Match"] ui.warn "Using the cached data for the new index because of a network error: #{e}" - Net::HTTPNotModified.new(nil, nil, nil) + Gem::Net::HTTPNotModified.new(nil, nil, nil) end end end diff --git a/lib/bundler/fetcher/dependency.rb b/lib/bundler/fetcher/dependency.rb index c52c32fb5b..0b807c9a4b 100644 --- a/lib/bundler/fetcher/dependency.rb +++ b/lib/bundler/fetcher/dependency.rb @@ -24,7 +24,7 @@ module Bundler def specs(gem_names, full_dependency_list = [], last_spec_list = []) query_list = gem_names.uniq - full_dependency_list - log_specs "Query List: #{query_list.inspect}" + log_specs { "Query List: #{query_list.inspect}" } return last_spec_list if query_list.empty? @@ -34,14 +34,10 @@ module Bundler returned_gems = spec_list.map(&:first).uniq specs(deps_list, full_dependency_list + returned_gems, spec_list + last_spec_list) - rescue MarshalError + rescue MarshalError, HTTPError, GemspecError Bundler.ui.info "" unless Bundler.ui.debug? # new line now that the dots are over Bundler.ui.debug "could not fetch from the dependency API, trying the full index" nil - rescue HTTPError, GemspecError - Bundler.ui.info "" unless Bundler.ui.debug? # new line now that the dots are over - Bundler.ui.debug "could not fetch from the dependency API\nit's suggested to retry using the full index via `bundle install --full-index`" - nil end def dependency_specs(gem_names) @@ -55,7 +51,7 @@ module Bundler gem_list = [] gem_names.each_slice(Source::Rubygems::API_REQUEST_SIZE) do |names| marshalled_deps = downloader.fetch(dependency_api_uri(names)).body - gem_list.concat(Bundler.load_marshal(marshalled_deps)) + gem_list.concat(Bundler.safe_load_marshal(marshalled_deps)) end gem_list end diff --git a/lib/bundler/fetcher/downloader.rb b/lib/bundler/fetcher/downloader.rb index f2aad3a500..868b39b959 100644 --- a/lib/bundler/fetcher/downloader.rb +++ b/lib/bundler/fetcher/downloader.rb @@ -20,31 +20,35 @@ module Bundler Bundler.ui.debug("HTTP #{response.code} #{response.message} #{filtered_uri}") case response - when Net::HTTPSuccess, Net::HTTPNotModified + when Gem::Net::HTTPSuccess, Gem::Net::HTTPNotModified response - when Net::HTTPRedirection - new_uri = Bundler::URI.parse(response["location"]) + when Gem::Net::HTTPRedirection + new_uri = Gem::URI.parse(response["location"]) if new_uri.host == uri.host new_uri.user = uri.user new_uri.password = uri.password end fetch(new_uri, headers, counter + 1) - when Net::HTTPRequestedRangeNotSatisfiable + when Gem::Net::HTTPRequestedRangeNotSatisfiable new_headers = headers.dup new_headers.delete("Range") new_headers["Accept-Encoding"] = "gzip" fetch(uri, new_headers) - when Net::HTTPRequestEntityTooLarge + when Gem::Net::HTTPRequestEntityTooLarge raise FallbackError, response.body - when Net::HTTPTooManyRequests + when Gem::Net::HTTPTooManyRequests raise TooManyRequestsError, response.body - when Net::HTTPUnauthorized + when Gem::Net::HTTPUnauthorized raise BadAuthenticationError, uri.host if uri.userinfo raise AuthenticationRequiredError, uri.host - when Net::HTTPNotFound - raise FallbackError, "Net::HTTPNotFound: #{filtered_uri}" + when Gem::Net::HTTPForbidden + raise AuthenticationForbiddenError, uri.host + when Gem::Net::HTTPNotFound + raise FallbackError, "Gem::Net::HTTPNotFound: #{filtered_uri}" else - raise HTTPError, "#{response.class}#{": #{response.body}" unless response.body.empty?}" + message = "Gem::#{response.class.name.gsub(/\AGem::/, "")}" + message += ": #{response.body}" unless response.body.empty? + raise HTTPError, message end end @@ -54,21 +58,18 @@ module Bundler filtered_uri = URICredentialsFilter.credential_filtered_uri(uri) Bundler.ui.debug "HTTP GET #{filtered_uri}" - req = Net::HTTP::Get.new uri.request_uri, headers + req = Gem::Net::HTTP::Get.new uri.request_uri, headers if uri.user user = CGI.unescape(uri.user) password = uri.password ? CGI.unescape(uri.password) : nil req.basic_auth(user, password) end connection.request(uri, req) - rescue NoMethodError => e - raise unless ["undefined method", "use_ssl="].all? {|snippet| e.message.include? snippet } - raise LoadError.new("cannot load such file -- openssl") rescue OpenSSL::SSL::SSLError raise CertificateFailureError.new(uri) rescue *HTTP_ERRORS => e Bundler.ui.trace e - if e.is_a?(SocketError) || e.message =~ /host down:/ + if e.is_a?(SocketError) || e.message.to_s.include?("host down:") raise NetworkDownError, "Could not reach host #{uri.host}. Check your network " \ "connection and try again." else @@ -80,7 +81,7 @@ module Bundler private def validate_uri_scheme!(uri) - return if uri.scheme =~ /\Ahttps?\z/ + return if /\Ahttps?\z/.match?(uri.scheme) raise InvalidOption, "The request uri `#{uri}` has an invalid scheme (`#{uri.scheme}`). " \ "Did you mean `http` or `https`?" diff --git a/lib/bundler/fetcher/gem_remote_fetcher.rb b/lib/bundler/fetcher/gem_remote_fetcher.rb new file mode 100644 index 0000000000..3fc7b68263 --- /dev/null +++ b/lib/bundler/fetcher/gem_remote_fetcher.rb @@ -0,0 +1,16 @@ +# frozen_string_literal: true + +require "rubygems/remote_fetcher" + +module Bundler + class Fetcher + class GemRemoteFetcher < Gem::RemoteFetcher + def request(*args) + super do |req| + req.delete("User-Agent") if headers["User-Agent"] + yield req if block_given? + end + end + end + end +end diff --git a/lib/bundler/fetcher/index.rb b/lib/bundler/fetcher/index.rb index 6bb9fcc193..6e37e1e5d1 100644 --- a/lib/bundler/fetcher/index.rb +++ b/lib/bundler/fetcher/index.rb @@ -6,7 +6,7 @@ module Bundler class Fetcher class Index < Base def specs(_gem_names) - Bundler.rubygems.fetch_all_remote_specs(remote) + Bundler.rubygems.fetch_all_remote_specs(remote, gem_remote_fetcher) rescue Gem::RemoteFetcher::FetchError => e case e.message when /certificate verify failed/ @@ -15,8 +15,7 @@ module Bundler raise BadAuthenticationError, remote_uri if remote_uri.userinfo raise AuthenticationRequiredError, remote_uri when /403/ - raise BadAuthenticationError, remote_uri if remote_uri.userinfo - raise AuthenticationRequiredError, remote_uri + raise AuthenticationForbiddenError, remote_uri else raise HTTPError, "Could not fetch specs from #{display_uri} due to underlying error <#{e.message}>" end |