Skip to content

Commit

Permalink
Simplify gem downloading inside bundler
Browse files Browse the repository at this point in the history
We can skip most stuff in `Gem::RemoteFetcher#download`, and use
`Gem::RemoteFetcher#update_cache_path` directly.

This has the benefit of allowing us to remove some workarounds to
support several rubygems versions, but also allows us to pass the target
folder where the gem should be downloaded directly and skip the logic
inside `Gem::RemoteFetcher#download` to infer the cache path. This will
be useful later to fix some issues with the `global_gem_cache` feature
flag.
  • Loading branch information
deivid-rodriguez committed Oct 21, 2021
1 parent 7e1316e commit 8fe74a7
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 19 deletions.
23 changes: 21 additions & 2 deletions bundler/lib/bundler/rubygems_integration.rb
Original file line number Diff line number Diff line change
Expand Up @@ -518,13 +518,32 @@ def fetch_all_remote_specs(remote)
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}>"
Expand Down
12 changes: 1 addition & 11 deletions bundler/lib/bundler/source/rubygems.rb
Original file line number Diff line number Diff line change
Expand Up @@ -521,17 +521,7 @@ def download_gem(spec, download_cache_path)
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
Expand Down
11 changes: 5 additions & 6 deletions bundler/spec/bundler/rubygems_integration_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,10 @@

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
Expand All @@ -59,9 +58,9 @@
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

Expand Down

0 comments on commit 8fe74a7

Please sign in to comment.