- ### Problem
If you have a `version` in your config file (this feature was
introduced in #6817), then running any `bundle` command will
make Bundler re-exec and ultimately run the `bundle` binstub twice.
### Details
When the `bundle` binstub gets executed, a `require "bundler"` is
evaluated. RubyGems tries to require the `bundler.rb` file from
the right `bundler` gem (in the event where you have multiple
bundler versions in your system).
RubyGems will prioritize a bundler version based on a few
heurisitics.
https://github.com/ruby/rubygems/blob/b50c40c92abb00bb172f1579356cc73c242b1849/lib/rubygems/bundler_version_finder.rb#L19-L21
This prioritize logic doesn't take into account the bundler version
a user has specific in this config. So what happens is:
1. User execute the `bundle` binstub
2. `require 'bundler'` is evaluated.
3. RubyGems prioritize activating the bundler version specified
in the Gemfile.lock
4. The CLI starts, and [Auto switch kicks in](https://github.com/ruby/rubygems/blob/b50c40c92abb00bb172f1579356cc73c242b1849/bundler/lib/bundler/cli.rb#L81). Bundler detects that
user specifed a version in its config and the current Bundler
version doesn't match.
5. Bundler exit and re-exec with the right bundler version.
### Solution
This patch introduce two fixes. First, it reads the bundler config
file and check for the local config first and then the global
config. This is because the local has precedence over global.
Second, the prioritization takes into account the version in config
and let RubyGems activate the right version in order to prevent
re-exec moments later.
Finally, I also want to fix this problem because its a step toward
fixing https://github.com/ruby/rubygems/issues/8106. I'll open
a follow up patch to explain.
https://github.com/ruby/rubygems/commit/d6e0f43133
- Fix https://github.com/ruby/rubygems/issues/9238
- ### Problem
This is an issue that bites gem maintainers from time to time, with
the most recent one in https://github.com/minitest/minitest/issues/1040#issuecomment-3679370619
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.
https://github.com/ruby/rubygems/commit/f298e2c68e
The reason this logic for different methods branches in the class instead of internally was to be eagerly aggressive about runtime performance. This code is currently only used once for the document where it's invoked ~N times (where N is number of lines):
```ruby
module SyntaxSuggest
class CleanDocument
# ...
def join_trailing_slash!
trailing_groups = @document.select(&:trailing_slash?).map do |code_line|
take_while_including(code_line.index..) { |x| x.trailing_slash? }
end
join_groups(trailing_groups)
self
end
```
Since this is not currently a hot-spot I think merging the branches and using a case statement is a reasonable tradeoff and avoids the need to do specific version testing.
An alternative idea was presented in #241 of behavior-based testing for branch logic (which I would prefer), however, calling the code triggered requiring a `DelegateClass` when the `syntax_suggest/api` is being required.
https://github.com/ruby/syntax_suggest/commit/ab122c455f
You're supposed to return the first argument.
```rb
# Before
[[:stmts_new], [:rescue_mod, nil, nil], [:stmts_add, nil, nil], [:program, nil]]
# After
[[:stmts_new], [:rescue_mod, "1", "2"], [:stmts_add, nil, "1"], [:program, nil]]
```
The correct result would be:
`[[:rescue_mod, "1", "2"], [:stmts_new], [:stmts_add, nil, "1"], [:program, nil]]`
But the order depends on the prism AST so it seems very difficult to match.
https://github.com/ruby/prism/commit/94e0107729
This is everything that `irb` uses. It works in their test-suite, but there are 20 failures when using the shim that I haven't looked into at all.
`parse` is not used by `irb`. `scan` is, and it's basically `parse` but also including errors. `irb` doesn't seem to care about the errors, so I didn't implement that.
https://github.com/ruby/prism/commit/2c5826b39f
This patch silences the "this won't work in the next version of Ruby"
warning displayed when irb is autoloaded via `binding.irb`.
main.rb:1: warning: irb used to be loaded from the standard library, but is not part of the default gems since Ruby 4.0.0.
You can add irb to your Gemfile or gemspec to fix this error.
/.../irb.rb:9: warning: reline used to be loaded from the standard library, but is not part of the default gems since Ruby 4.0.0.
You can add reline to your Gemfile or gemspec to fix this error.
From: main.rb @ line 1 :
=> 1: binding.irb
/.../input-method.rb:284: warning: rdoc used to be loaded from the standard library, but is not part of the default gems since Ruby 4.0.0.
You can add rdoc to your Gemfile or gemspec to fix this error.
This warning is incorrect and misleading: users should not need to
include irb (and its dependencies) to their Gemfiles to use
`binding.irb`, even in future versions of Ruby. It is agreed that the
runtime takes care of that.
This patch fixes a problem where `binding.irb` (= force_activate('irb'))
fails under `bundle exec` when the Gemfile does not contain `irb` and
does contain a gem which is (1) not installed in GEM_HOME (2) sourced
using `path:`/`git:`.
The original approach constructing a temporary definition fails since
it does not set the equalivent of `path:`/`git:`.
Always reconstructing a definition from a Gemfile and applying lockfile
constraints should be a more robust approach.
[Bug #21723]
One per version seems excessive.
Do note that `rubocop-ast` used to require individual parser files. I wouldn't consider that to be part of the API since everything is autoloaded.
From a GitHub code search, I didn't find anyone else doing it like that.
https://github.com/ruby/prism/commit/458f622c34
Ripper exposes Ripper::Lexer:State in its output, which is a bit of a problem. To make this work, I basically copy-pasted the implementation.
I'm unsure if that is acceptable and added a test to make sure that these values never go out of sync.
I don't imagine them changing often, prism maps them 1:1 for its own usage.
This also fixed the shim by accident. `Ripper.lex` went to `Translation::Ripper.lex` when it should have been the original. Removing the need for the original resolves that issue.
https://github.com/ruby/prism/commit/2c0bea076d
When requiring a file like "benchmark/ips", the warning system would
incorrectly warn about the "benchmark" gem not being a default gem,
even when the user has "benchmark-ips" (a separate third-party gem)
in their Gemfile.
The fix checks if a hyphenated version of the require path exists in
the bundle specs before issuing a warning. For example, requiring
"benchmark/ips" now checks for both "benchmark" and "benchmark-ips"
in the Gemfile.
[Bug #21828]
I stumbled across a bundler bug that had me scratching my head for
awhile, because I hadn't experienced it before.
In some cases when changing the source in a gemfile from a
`Source::Gemspec` to either a `Source::Path` or `Source::Git` only the
parent gem will have it's gem replaced and updated and the child
components will retain the original version. This only happens if the gem
version of the `Source::Gemspec` and `Source::Git` are the same. It also
requires another gem to share a dependency with the one being updated.
For example if I have the following gemfile:
```
gem "rails", "~> 8.1.1"
gem "propshaft"
```
Rails has a component called `actionpack` which `propshaft` depends on.
If I change `rails` to point at a git source (or path source), only the
path for `rails` gets updated:
```
gem "rails", github: "rails/rails", branch: "8-1-stable"
gem "propshaft"
```
Because `actionpack` is a dependency of `propshaft`, it will remain in
the rubygems source in the lock file WHILE the other gems are correctly
pointing to the git source.
Gemfile.lock:
```
GIT
remote: https://github.com/rails/rails.git
revision: https://github.com/ruby/rubygems/commit/9439f463e0ef
branch: 8-1-stable
specs:
actioncable (8.1.1)
...
actionmailbox (8.1.1)
...
actionmailer (8.1.1)
...
actiontext (8.1.1)
...
activejob (8.1.1)
...
activemodel (8.1.1)
...
activerecord (8.1.1)
...
activestorage (8.1.1)
...
rails (8.1.1)
...
railties (8.1.1)
...
GEM
remote: https://rubygems.org/
specs:
action_text-trix (2.1.15)
railties
actionpack (8.1.1) <===== incorrectly left in Rubygems source
...
```
The gemfile will contain `actionpack` in the rubygems source, but will
be missing in the git source so the path will be incorrect. A bundle
show on Rails will point to the correct place:
```
$ bundle show rails
/Users/eileencodes/.gem/ruby/3.4.4/bundler/gems/rails-9439f463e0ef
```
but a bundle show on actionpack will be incorrect:
```
$ bundle show actionpack
/Users/eileencodes/.gem/ruby/3.4.4/gems/actionpack-8.1.1
```
This bug requires the following to reproduce:
1) A gem like Rails that contains components that are released as their
own standalone gem is added to the gemfile pointing to rubygems
2) A second gem is added that depends on one of the gems in the first
gem (like propshaft does on actionpack)
3) The Rails gem is updated to use a git source, pointing to the same
version that is being used by rubygems (ie 8.1.1)
4) `bundle` will only update the path for Rails component gems if no
other gem depends on it.
This incorrectly leaves Rails (or any gem like it) using two different
codepaths / gem source code.
https://github.com/ruby/rubygems/commit/dff76ba4f6
Previously: In #9218 a reproduction is shared where running `bundle clean` using a binstub (`bin/bundle`) results in bundler removing itself. This results in Ruby falling back to its default bundler version. This behavior seems to be present for as long as there has been a default version of bundler (Ruby 2.6+).
Now: Bundler will explicitly add its current version number to the specs to be preserved. This prevents `bundle clean` from removing the current bundler version.
close https://github.com/ruby/rubygems/pull/9218https://github.com/ruby/rubygems/commit/e3f0167ae4