Skip to content

Conversation

@Edouard-chin
Copy link
Contributor

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

Fix #9238

This is an issue that bites gem maintainers from time to time, with the most recent one in minitest/minitest#1040 (comment)

The issue is summarized as follow:

  1. A gem "X" has a feature in "lib/feature.rb"
  2. Maintainer wants to extract this feature into its own gem "Y"
  3. Maintainer cut a release of X without that new feature.
  4. Users install the new version of X and also install the new gem "Y" since the feature is now extracted.
  5. When a call to "require 'feature'" is encountered, RG will fail to load the right gem, resulting in a LoadError.

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

Details

Now that we have two gems (old version of X and new gem Y) with the same path, RubyGems will detect that feature.rb can be loaded from the old version of X, but if the new version of X had already been loaded, then RubyGems will raise due to versions conflicting.

require 'x' # Loads the new version of X without the feature which was extracted. 
require 'feature' # Rubygems see that the old version of X include that file and tries to activate the old X spec, resulting in a version conflict.

Solution

I propose that RubyGems fallback to a spec that's not yet loaded. We try to find a spec by its path and filter it out in case a spec with the same name has already been loaded.

Its worth to note that RubyGems already has a find_inactive_by_path but we can't use it. This method only checks if the spec object is active and doesn't look if other spec with the same name have been loaded. The new method we are introducing verifies this.

Make sure the following tasks are checked

- Fix ruby#9238
- ### Problem

  This is an issue that bites gem maintainers from time to time, with
  the most recent one in minitest/minitest#1040 (comment)

  The issue is summarized as follow:

  1) A gem "X" has a feature in "lib/feature.rb"
  2) Maintainer wants to extract this feature into its own gem "Y"
  3) Maintainer cut a release of X without that new feature.
  4) Users install the new version of X and also install the new
     gem "Y" since the feature is now extracted.
  5) When a call to "require 'feature'" is encountered, RG will
     fail to load the right gem, resulting in a `LoadError`.

  ### Details

  Now that we have two gems (old version of X and new gem Y) with
  the same path, RubyGems will detect that `feature.rb` can be loaded
  from the old version of X, but if the new version of X had already
  been loaded, then RubyGems will raise due to versions conflicting.

  ```ruby
  require 'x' # Loads the new version of X without the feature which was extracted.
  require 'feature' # Rubygems see that the old version of X include that file and tries to activate the spec.
  ```

  ### Solution

  I propose that RubyGems fallback to a spec that's not yet loaded.
  We try to find a spec by its path and filter it out in case a spec
  with the same name has already been loaded.

  Its worth to note that RubyGems already has a
  `find_inactive_by_path` but we can't use it. This method only checks
  if the spec object is active and doesn't look if other spec with the
  same name have been loaded. The new method we are introducing
  verifies this.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Troubles loading minitest-mock

2 participants