-
-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Add global gem cache shared by RubyGems and Bundler #9230
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
Add opt-in support for a global .gem file cache at ~/.cache/gem/gems (respects XDG_CACHE_HOME). This allows sharing cached gems across all Ruby installations and between RubyGems and Bundler. Enable via: - Environment: RUBYGEMS_GLOBAL_GEM_CACHE=true - gemrc: global_gem_cache: true - Bundler: bundle config set global_gem_cache true When enabled, RubyGems checks the global cache before downloading and copies downloaded gems to the cache. Bundler's existing global_gem_cache setting now uses the same unified cache location.
tenderlove
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is mostly good, though I left a comment. It looks like you need to opt-in to using the global cache. I think we should make it opt-out, or possibly not configurable. I think that if people want the hold behavior, they could set XDG_CACHE_HOME to the old location.
For example:
$ XDG_CACHE_HOME=$(ruby -e'puts Gem.home') gem install blah
Open to other opinions though.
| end | ||
| end | ||
|
|
||
| install_cache_dir = File.join install_dir, "cache" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't we add code that influences the install_dir variable? Or change install_cache_dir variable to point at the gem cache path? It seems like this is the right place to do it. Then I think we can avoid the copy below.
Ah yes, this is true. We could probably make it opt-in for a bugfix release, then opt-out for a middle release or something. |
| return unless cache_slug = remote.cache_slug | ||
|
|
||
| Bundler.user_cache.join("gems", cache_slug) | ||
| Pathname.new(Gem.global_gem_cache_path).join(cache_slug) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this will break if someone updates Bundler but has an old Rubygems version
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We really need to combine RubyGems / Bundler so we can do refactoring like this more freely. 😫
Instead of checking global cache separately and copying after download, integrate global_gem_cache as the first option in cache_dir selection. This removes ~20 lines while achieving the same behavior. Suggested by Aaron Patterson.
Guard against missing Gem.global_gem_cache_path method when Bundler is used with an older RubyGems version that doesn't have the global cache feature. Falls back to the previous Bundler.user_cache location. Suggested by skipkayhil.
|
@tenderlove @skipkayhil thanks for the reviews! I just pushed up a couple more commits to try to simplify and to ensure that folks that were running older versions of Rubygems would be less likely to run into issues. |
The global gem cache is now at ~/.cache/gem/gems/ (XDG standard) instead of ~/.bundle/cache/gems/ to align with the shared RubyGems/Bundler cache implementation.
When running Bundler tests against system RubyGems (which doesn't have Gem.global_gem_cache_path), the test needs to use the fallback cache location (~/.bundle/cache/gems/) that Bundler uses in that case.
|
Sorry for the delay on this. Looks like it's waiting on a build to run. I've been pushing up and it seems someone periodically manually triggers? (Not sure if there's a way for it to auto-run on push or a way for me to easily trigger. No worries, it would just speed up the feedback loop.) |
What was the end-user or developer problem that led to this PR?
Attempts to implement #7249. I read about this issue in this recent blog post by @tenderlove.
I will admit that I am both new to this repo and that the code was primarily generated with Claude Code. However, I reviewed it (have a lot of Ruby experience) and it seems reasonable. Additionally, I had it write some automated tests and a script to test it out end-to-end. I am hoping this changeset could at least serve as a conversation starter to make sure the requirements are clear, and since it did not take long to implement, I have low attachment to it, so open to feedback.
What is your fix for the problem, implemented in this PR?
Add opt-in support for a global .gem file cache at ~/.cache/gem/gems (respects XDG_CACHE_HOME). This allows sharing cached gems across all Ruby installations and between RubyGems and Bundler.
Enable via:
When enabled, RubyGems checks the global cache before downloading and copies downloaded gems to the cache. Bundler's existing global_gem_cache setting now uses the same unified cache location.
Note: #7249 indicates that it's a placeholder for opting everyone in to this behavior for Bundler and Rubygems, but I thought that this might be better for the next version bump since it might have some unexpected behaviors for folks. I think it would be a small code change to make it opt-out, but might be more of a development challenge to do so IMO.
Make sure the following tasks are checked