summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndre Arko <andre@arko.net>2013-10-05 19:22:38 -0700
committerAndre Arko <andre@arko.net>2013-10-05 19:22:38 -0700
commitaaad34184e4e15f3117dbca6c89dc50bfd34ecb5 (patch)
tree268072ae9de3dc1c875d017e2179caff9e414340
parent1f875b155d0d42ceadab933755a84dfde1f81d2d (diff)
downloadbundler-new-index.tar.gz
wtffffffffnew-index
-rw-r--r--lib/bundler/fetcher.rb188
1 files changed, 51 insertions, 137 deletions
diff --git a/lib/bundler/fetcher.rb b/lib/bundler/fetcher.rb
index e2a86aafde..fa2274f501 100644
--- a/lib/bundler/fetcher.rb
+++ b/lib/bundler/fetcher.rb
@@ -76,6 +76,46 @@ module Bundler
end
end
+ HTTP_ERRORS = [
+ Timeout::Error, EOFError, SocketError,
+ Errno::EINVAL, Errno::ECONNRESET, Errno::ETIMEDOUT, Errno::EAGAIN,
+ Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError, Net::ProtocolError,
+ Net::HTTP::Persistent::Error
+ ]
+
+ def get(uri, counter = 0)
+ raise HTTPError, "Too many redirects" if counter >= @redirect_limit
+
+ begin
+ Bundler.ui.debug "Fetching from: #{uri}"
+ req = Net::HTTP::Get.new uri.request_uri
+ req.basic_auth(uri.user, uri.password) if uri.user
+ response = connection.request(uri, req)
+ rescue OpenSSL::SSL::SSLError
+ raise CertificateFailureError.new(uri)
+ rescue *HTTP_ERRORS
+ raise HTTPError, "Network error while fetching #{uri}"
+ end
+
+ case response
+ when Net::HTTPRedirection
+ Bundler.ui.debug("HTTP Redirection")
+ new_uri = URI.parse(response["location"])
+ if new_uri.host == uri.host
+ new_uri.user = uri.user
+ new_uri.password = uri.password
+ end
+ fetch(new_uri, counter + 1)
+ when Net::HTTPSuccess
+ Bundler.ui.debug("HTTP Success")
+ response.body
+ when Net::HTTPRequestEntityTooLarge
+ raise FallbackError, response.body
+ else
+ raise HTTPError, "#{response.class}: #{response.body}"
+ end
+ end
+
end
attr_reader :remote_uri
@@ -152,81 +192,34 @@ module Bundler
paths.first
end
+
# return the specs in the bundler format as an index
def specs(gem_names, source)
- index = Index.new
- use_full_index = !gem_names || @remote_uri.scheme == "file" ||
- Bundler::Fetcher.disable_endpoint || !use_api
-
- if !use_full_index
- specs = fetch_remote_specs(gem_names)
+ if gem_names && use_api
+ # try the dependency index first
+ specs = Bundler::DepSpecs.new(source, remote_uri).specs(gem_names)
+ # then try the dependency api
+ specs ||= RemoteSpecs.new(source, remote_uri).specs(gem_names)
end
- if specs.nil?
- # API errors mean we should treat this as a non-API source
- @use_api = false
+ # if we need the full index, this isn't an API source
+ @use_api = false if specs.nil?
- specs = Bundler::Retry.new("source fetch").attempts do
- fetch_all_remote_specs
- end
- end
-
- specs[@remote_uri].each do |name, version, platform, dependencies|
- next if name == 'bundler'
- spec = nil
- if dependencies
- spec = EndpointSpecification.new(name, version, platform, dependencies)
- else
- spec = RemoteSpecification.new(name, version, platform, self)
- end
- spec.source = source
- spec.source_uri = @remote_uri
- index << spec
- end
-
- index
+ # finally, if we don't have any specs yet, grab the full index
+ specs || MarshalledSpecs.new(source, remote_uri, self).specs
rescue CertificateFailureError => e
Bundler.ui.info "" if gem_names && use_api # newline after dots
raise e
end
- # fetch index
- def fetch_remote_specs(gem_names, full_dependency_list = [], last_spec_list = [])
- query_list = gem_names - full_dependency_list
-
- # only display the message on the first run
- if Bundler.ui.debug?
- Bundler.ui.debug "Query List: #{query_list.inspect}"
- else
- Bundler.ui.info ".", false
- end
-
- return {@remote_uri => last_spec_list} if query_list.empty?
-
- remote_specs = Bundler::Retry.new("dependency api").attempts do
- fetch_dependency_remote_specs(query_list)
- end
-
- spec_list, deps_list = remote_specs
- returned_gems = spec_list.map {|spec| spec.first }.uniq
- fetch_remote_specs(deps_list, full_dependency_list + returned_gems, spec_list + last_spec_list)
- rescue HTTPError, MarshalError, GemspecError => e
- 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"
- @use_api = false
- return nil
- end
-
def use_api
return @use_api if defined?(@use_api)
if @remote_uri.scheme == "file" || Bundler::Fetcher.disable_endpoint
@use_api = false
- elsif fetch(dependency_api_uri)
+ else
@use_api = true
end
- rescue HTTPError
- @use_api = false
end
def inspect
@@ -235,85 +228,6 @@ module Bundler
private
- HTTP_ERRORS = [
- Timeout::Error, EOFError, SocketError,
- Errno::EINVAL, Errno::ECONNRESET, Errno::ETIMEDOUT, Errno::EAGAIN,
- Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError, Net::ProtocolError,
- Net::HTTP::Persistent::Error
- ]
-
- def fetch(uri, counter = 0)
- raise HTTPError, "Too many redirects" if counter >= @redirect_limit
-
- begin
- Bundler.ui.debug "Fetching from: #{uri}"
- req = Net::HTTP::Get.new uri.request_uri
- req.basic_auth(uri.user, uri.password) if uri.user
- response = connection.request(uri, req)
- rescue OpenSSL::SSL::SSLError
- raise CertificateFailureError.new(uri)
- rescue *HTTP_ERRORS
- raise HTTPError, "Network error while fetching #{uri}"
- end
-
- case response
- when Net::HTTPRedirection
- Bundler.ui.debug("HTTP Redirection")
- new_uri = URI.parse(response["location"])
- if new_uri.host == uri.host
- new_uri.user = uri.user
- new_uri.password = uri.password
- end
- fetch(new_uri, counter + 1)
- when Net::HTTPSuccess
- Bundler.ui.debug("HTTP Success")
- response.body
- when Net::HTTPRequestEntityTooLarge
- raise FallbackError, response.body
- else
- raise HTTPError, "#{response.class}: #{response.body}"
- end
- end
-
- def dependency_api_uri(gem_names = [])
- url = "#{@remote_uri}api/v1/dependencies"
- url << "?gems=#{URI.encode(gem_names.join(","))}" if gem_names.any?
- URI.parse(url)
- end
-
- # fetch from Gemcutter Dependency Endpoint API
- def fetch_dependency_remote_specs(gem_names)
- Bundler.ui.debug "Query Gemcutter Dependency Endpoint API: #{gem_names.join(',')}"
- marshalled_deps = fetch dependency_api_uri(gem_names)
- gem_list = Bundler.load_marshal(marshalled_deps)
- deps_list = []
-
- spec_list = gem_list.map do |s|
- dependencies = s[:dependencies].map do |name, requirement|
- dep = well_formed_dependency(name, requirement.split(", "))
- deps_list << dep.name
- dep
- end
-
- [s[:name], Gem::Version.new(s[:number]), s[:platform], dependencies]
- end
-
- [spec_list, deps_list.uniq]
- end
-
- # fetch from modern index: specs.4.8.gz
- def fetch_all_remote_specs
- Bundler.rubygems.sources = ["#{@remote_uri}"]
- Bundler.rubygems.fetch_all_remote_specs
- rescue Gem::RemoteFetcher::FetchError, OpenSSL::SSL::SSLError => e
- if e.message.match("certificate verify failed")
- raise CertificateFailureError.new(uri)
- else
- Bundler.ui.trace e
- raise HTTPError, "Could not fetch specs from #{uri}"
- end
- end
-
def well_formed_dependency(name, *requirements)
Gem::Dependency.new(name, *requirements)
rescue ArgumentError => e