diff --git a/lib/bundler/rubygems_integration.rb b/lib/bundler/rubygems_integration.rb index 70366c4d48..effb88c1cd 100644 --- a/lib/bundler/rubygems_integration.rb +++ b/lib/bundler/rubygems_integration.rb @@ -506,13 +506,32 @@ module Bundler specs.concat(pres) end - def download_gem(spec, uri, path) + def download_gem(spec, uri, cache_dir) require "rubygems/remote_fetcher" uri = Bundler.settings.mirror_for(uri) fetcher = gem_remote_fetcher fetcher.headers = { "X-Gemfile-Source" => spec.remote.original_uri.to_s } if spec.remote.original_uri Bundler::Retry.new("download gem from #{uri}").attempts do - fetcher.download(spec, uri, path) + gem_file_name = spec.file_name + local_gem_path = File.join cache_dir, gem_file_name + return if File.exist? local_gem_path + + begin + remote_gem_path = uri + "gems/#{gem_file_name}" + remote_gem_path = remote_gem_path.to_s if provides?("< 3.2.0.rc.1") + + SharedHelpers.filesystem_access(local_gem_path) do + fetcher.cache_update_path remote_gem_path, local_gem_path + end + rescue Gem::RemoteFetcher::FetchError + raise if spec.original_platform == spec.platform + + original_gem_file_name = "#{spec.original_name}.gem" + raise if gem_file_name == original_gem_file_name + + gem_file_name = original_gem_file_name + retry + end end rescue Gem::RemoteFetcher::FetchError => e raise Bundler::HTTPError, "Could not download gem from #{uri} due to underlying error <#{e.message}>" diff --git a/lib/bundler/source/rubygems.rb b/lib/bundler/source/rubygems.rb index 12b7a941f1..ae77f41753 100644 --- a/lib/bundler/source/rubygems.rb +++ b/lib/bundler/source/rubygems.rb @@ -521,17 +521,7 @@ module Bundler else uri = spec.remote.uri Bundler.ui.confirm("Fetching #{version_message(spec)}") - rubygems_local_path = Bundler.rubygems.download_gem(spec, uri, File.dirname(download_cache_path)) - - # older rubygems return varying file:// variants depending on version - rubygems_local_path = rubygems_local_path.gsub(/\Afile:/, "") unless Bundler.rubygems.provides?(">= 3.2.0.rc.2") - rubygems_local_path = rubygems_local_path.gsub(%r{\A//}, "") if Bundler.rubygems.provides?("< 3.1.0") - - if rubygems_local_path != local_path - SharedHelpers.filesystem_access(local_path) do - FileUtils.mv(rubygems_local_path, local_path) - end - end + Bundler.rubygems.download_gem(spec, uri, download_cache_path) cache_globally(spec, local_path) end end diff --git a/spec/bundler/bundler/rubygems_integration_spec.rb b/spec/bundler/bundler/rubygems_integration_spec.rb index a48c6410f3..94abf70ddd 100644 --- a/spec/bundler/bundler/rubygems_integration_spec.rb +++ b/spec/bundler/bundler/rubygems_integration_spec.rb @@ -43,11 +43,10 @@ RSpec.describe Bundler::RubygemsIntegration do describe "#download_gem" do let(:bundler_retry) { double(Bundler::Retry) } - let(:uri) { Bundler::URI.parse("https://foo.bar") } - let(:path) { Gem.path.first } + let(:uri) { Bundler::URI.parse("https://foo.bar") } + let(:cache_dir) { "#{Gem.path.first}/cache" } let(:spec) do - spec = Bundler::RemoteSpecification.new("Foo", Gem::Version.new("2.5.2"), - Gem::Platform::RUBY, nil) + spec = Gem::Specification.new("Foo", Gem::Version.new("2.5.2")) spec.remote = Bundler::Source::Rubygems::Remote.new(uri.to_s) spec end @@ -59,9 +58,9 @@ RSpec.describe Bundler::RubygemsIntegration do expect(Bundler::Retry).to receive(:new).with("download gem from #{uri}/"). and_return(bundler_retry) expect(bundler_retry).to receive(:attempts).and_yield - expect(fetcher).to receive(:download).with(spec, uri, path) + expect(fetcher).to receive(:cache_update_path) - Bundler.rubygems.download_gem(spec, uri, path) + Bundler.rubygems.download_gem(spec, uri, cache_dir) end end