diff --git a/lib/bundler/endpoint_specification.rb b/lib/bundler/endpoint_specification.rb index 7c7ce107e205..5ef2d53eae35 100644 --- a/lib/bundler/endpoint_specification.rb +++ b/lib/bundler/endpoint_specification.rb @@ -153,8 +153,13 @@ def parse_metadata(data) next unless v case k.to_s when "checksum" + # Some registries send empty checksum values, treat them as if the + # checksum was not included at all + checksum = v.last + next unless checksum + begin - @checksum = Checksum.from_api(v.last, @spec_fetcher.uri) + @checksum = Checksum.from_api(checksum, @spec_fetcher.uri) rescue ArgumentError => e raise ArgumentError, "Invalid checksum for #{full_name}: #{e.message}" end diff --git a/spec/bundler/endpoint_specification_spec.rb b/spec/bundler/endpoint_specification_spec.rb index 4fbd59d48f23..690f25caa31c 100644 --- a/spec/bundler/endpoint_specification_spec.rb +++ b/spec/bundler/endpoint_specification_spec.rb @@ -71,6 +71,34 @@ end end + context "when the metadata has an empty checksum value" do + let(:metadata) { { "checksum" => [] } } + + it "leaves checksum as nil without raising" do + expect(subject.checksum).to be_nil + end + end + + context "when the metadata has a nil checksum value" do + let(:metadata) { { "checksum" => nil } } + + it "leaves checksum as nil without raising" do + expect(subject.checksum).to be_nil + end + end + + context "when the metadata has an invalid checksum value" do + let(:metadata) { { "checksum" => ["xyz"] } } + let(:spec_fetcher) { double(:spec_fetcher, uri: "https://rubygems.org") } + + it "raises an error mentioning the invalid checksum" do + expect { subject }.to raise_error( + Bundler::GemspecError, + a_string_including("Invalid checksum for foo-1.0.0") + ) + end + end + context "when the metadata has no created_at" do let(:metadata) { { "checksum" => ["abc"] } } let(:spec_fetcher) { double(:spec_fetcher, uri: "https://rubygems.org") } diff --git a/spec/install/gemfile/git_spec.rb b/spec/install/gemfile/git_spec.rb index a648344d600d..2b74aa849ac8 100644 --- a/spec/install/gemfile/git_spec.rb +++ b/spec/install/gemfile/git_spec.rb @@ -137,9 +137,12 @@ sha = git.ref_for("main", 11) spec_file = scoped_gem_path(bundled_app("vendor/dir[1]")).join("bundler/gems/foo-1.0-#{sha}/foo.gemspec") expect(spec_file).to exist - ruby_code = Gem::Specification.load(spec_file.to_s).to_ruby + # Serialize with the RubyGems that wrote the file, since `#to_ruby` + # output differs across RubyGems versions + ruby "print Gem::Specification.load(#{spec_file.to_s.dump}).to_ruby" + ruby_code = out file_code = File.read(spec_file) - expect(file_code).to eq(ruby_code) + expect(file_code.strip).to eq(ruby_code) end it "does not update the git source implicitly" do