diff options
| -rw-r--r-- | lib/bundler/source/rubygems/remote.rb | 14 | ||||
| -rw-r--r-- | spec/bundler/install/global_cache_spec.rb | 41 |
2 files changed, 50 insertions, 5 deletions
diff --git a/lib/bundler/source/rubygems/remote.rb b/lib/bundler/source/rubygems/remote.rb index 9c5c06de24..ed55912a99 100644 --- a/lib/bundler/source/rubygems/remote.rb +++ b/lib/bundler/source/rubygems/remote.rb @@ -16,6 +16,9 @@ module Bundler @anonymized_uri = remove_auth(@uri).freeze end + MAX_CACHE_SLUG_HOST_SIZE = 255 - 1 - 32 # 255 minus dot minus MD5 length + private_constant :MAX_CACHE_SLUG_HOST_SIZE + # @return [String] A slug suitable for use as a cache key for this # remote. # @@ -28,10 +31,15 @@ module Bundler host = cache_uri.to_s.start_with?("file://") ? nil : cache_uri.host uri_parts = [host, cache_uri.user, cache_uri.port, cache_uri.path] - uri_digest = SharedHelpers.digest(:MD5).hexdigest(uri_parts.compact.join(".")) + uri_parts.compact! + uri_digest = SharedHelpers.digest(:MD5).hexdigest(uri_parts.join(".")) + + uri_parts.pop + host_parts = uri_parts.join(".") + return uri_digest if host_parts.empty? - uri_parts[-1] = uri_digest - uri_parts.compact.join(".") + shortened_host_parts = host_parts[0...MAX_CACHE_SLUG_HOST_SIZE] + [shortened_host_parts, uri_digest].join(".") end end diff --git a/spec/bundler/install/global_cache_spec.rb b/spec/bundler/install/global_cache_spec.rb index a4431bff8b..130c841ce9 100644 --- a/spec/bundler/install/global_cache_spec.rb +++ b/spec/bundler/install/global_cache_spec.rb @@ -7,12 +7,16 @@ RSpec.describe "global gem caching" do let(:source) { "http://localgemserver.test" } let(:source2) { "http://gemserver.example.org" } + def cache_base + home(".bundle", "cache", "gems") + end + def source_global_cache(*segments) - home(".bundle", "cache", "gems", "localgemserver.test.80.dd34752a738ee965a2a4298dc16db6c5", *segments) + cache_base.join("localgemserver.test.80.dd34752a738ee965a2a4298dc16db6c5", *segments) end def source2_global_cache(*segments) - home(".bundle", "cache", "gems", "gemserver.example.org.80.1ae1663619ffe0a3c9d97712f44c705b", *segments) + cache_base.join("gemserver.example.org.80.1ae1663619ffe0a3c9d97712f44c705b", *segments) end it "caches gems into the global cache on download" do @@ -49,6 +53,39 @@ RSpec.describe "global gem caching" do expect(err).to include("Gem::Package::FormatError: package metadata is missing in #{source_global_cache("myrack-1.0.0.gem")}") end + it "uses a shorter path for the cache to not hit filesystem limits" do + install_gemfile <<-G, artifice: "compact_index", verbose: true + source "http://#{"a" * 255}.test" + gem "myrack" + G + + expect(the_bundle).to include_gems "myrack 1.0.0" + source_segment = "a" * 222 + ".a3cb26de2edfce9f509a65c611d99c4b" + source_cache = cache_base.join(source_segment) + cached_gem = source_cache.join("myrack-1.0.0.gem") + expect(cached_gem).to exist + ensure + # We cleanup dummy files created by this spec manually because due to a + # Ruby on Windows bug, `FileUtils.rm_rf` (run in our global after hook) + # cannot traverse directories with such long names. So we delete + # everything explicitly to workaround the bug. An alternative workaround + # would be to shell out to `rm -rf`. That also works fine, but I went with + # the more verbose and explicit approach. This whole ensure block can be + # removed once/if https://bugs.ruby-lang.org/issues/21177 is fixed, and + # once the fix propagates to all supported rubies. + File.delete cached_gem + Dir.rmdir source_cache + + File.delete compact_index_cache_path.join(source_segment, "info", "myrack") + Dir.rmdir compact_index_cache_path.join(source_segment, "info") + File.delete compact_index_cache_path.join(source_segment, "info-etags", "myrack-92f3313ce5721296f14445c3a6b9c073") + Dir.rmdir compact_index_cache_path.join(source_segment, "info-etags") + Dir.rmdir compact_index_cache_path.join(source_segment, "info-special-characters") + File.delete compact_index_cache_path.join(source_segment, "versions") + File.delete compact_index_cache_path.join(source_segment, "versions.etag") + Dir.rmdir compact_index_cache_path.join(source_segment) + end + describe "when the same gem from different sources is installed" do it "should use the appropriate one from the global cache" do bundle "config path.system true" |
