Skip to content

Look up gems for gem fetch through the compact index - #9796

Open
segiddins wants to merge 1 commit into
ruby:masterfrom
segiddins:segiddins/gem-fetch-through-the-compact-index
Open

Look up gems for gem fetch through the compact index#9796
segiddins wants to merge 1 commit into
ruby:masterfrom
segiddins:segiddins/gem-fetch-through-the-compact-index

Conversation

@segiddins

Copy link
Copy Markdown
Contributor

gem fetch looks gems up through Gem::SpecFetcher, which asks a source for its entire index -- the compact index versions file when the source serves one, 23MB of it for rubygems.org on a cold cache, and the Marshal index otherwise -- and then fetches a Marshal gemspec for every version that matches. gem install resolves through Gem::Resolver::BestSet, which reads only the info file of the gem it is looking for.

Look gems up through a BestSet instead, so gem fetch a reads /info/a rather than the whole index, and fetches only the gemspec of the version it downloads. Platform preference and the reporting of specs rejected for another platform are unchanged.

Gem::Source now requires rubygems/remote_fetcher, which it has always used without loading: until now every caller of #dependency_resolver_set had loaded Gem::SpecFetcher, which requires it, first.

What was the end-user or developer problem that led to this PR?

I have a private gem server that only serves the compact index, no marshal, and gem install was succeeding but gem fetch failed.

What is your fix for the problem, implemented in this PR?

Allow gem fetch to prefer the compact index over the full index, mirroring gem install behavior.

Make sure the following tasks are checked

`gem fetch` looks gems up through Gem::SpecFetcher, which asks a source for its
entire index -- the compact index `versions` file when the source serves one,
23MB of it for rubygems.org on a cold cache, and the Marshal index otherwise --
and then fetches a Marshal gemspec for every version that matches. `gem install`
resolves through Gem::Resolver::BestSet, which reads only the `info` file of the
gem it is looking for.

Look gems up through a BestSet instead, so `gem fetch a` reads `/info/a` rather
than the whole index, and fetches only the gemspec of the version it downloads.
Platform preference and the reporting of specs rejected for another platform are
unchanged.

Gem::Source uses Gem::RemoteFetcher without requiring it, relying on its callers
to have loaded it, and it cannot require it eagerly: Bundler loads
rubygems/source on boot, where pulling in net/http breaks bundles that do not
include its dependencies. Require it from the command instead, the way the
sources command already does.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@segiddins
segiddins force-pushed the segiddins/gem-fetch-through-the-compact-index branch from df4a1dc to 3996b60 Compare August 22, 2026 03:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant