| Age | Commit message (Collapse) | Author |
|
https://github.com/ruby/did_you_mean/commit/0b35da6496
|
|
(https://github.com/ruby/rubygems/pull/9296)
Symlinks are not permitted by default for a Windows user. To use them, a switch called "Development Mode" in the system settings has to be enabled.
## What was the end-user or developer problem that led to this PR?
Ordinary users as well as administrators are unable per default to install gems using symlinks.
One such problematical gem is `haml-rails-3.0.0`.
It uses symlinks for [files and directories](https://github.com/haml/haml-rails/tree/9f4703ddff0644ba52529c5cf41c1624829b16a7/lib/generators/haml/scaffold/templates).
The resulting error message is not very helpful:
```
$ gem inst haml-rails
Fetching haml-rails-3.0.0.gem
ERROR: While executing gem ... (Gem::FilePermissionError)
You don't have write permissions for the directory. (Gem::FilePermissionError)
C:/ruby/lib/ruby/4.0.0/rubygems/installer.rb:308:in 'Gem::Installer#install'
C:/ruby/lib/ruby/4.0.0/rubygems/resolver/specification.rb:105:in 'Gem::Resolver::Specification#install'
C:/ruby/lib/ruby/4.0.0/rubygems/request_set.rb:192:in 'block in Gem::RequestSet#install'
C:/ruby/lib/ruby/4.0.0/rubygems/request_set.rb:183:in 'Array#each'
C:/ruby/lib/ruby/4.0.0/rubygems/request_set.rb:183:in 'Gem::RequestSet#install'
C:/ruby/lib/ruby/4.0.0/rubygems/commands/install_command.rb:207:in 'Gem::Commands::InstallCommand#install_gem'
C:/ruby/lib/ruby/4.0.0/rubygems/commands/install_command.rb:223:in 'block in Gem::Commands::InstallCommand#install_gems'
C:/ruby/lib/ruby/4.0.0/rubygems/commands/install_command.rb:216:in 'Array#each'
C:/ruby/lib/ruby/4.0.0/rubygems/commands/install_command.rb:216:in 'Gem::Commands::InstallCommand#install_gems'
C:/ruby/lib/ruby/4.0.0/rubygems/commands/install_command.rb:162:in 'Gem::Commands::InstallCommand#execute'
C:/ruby/lib/ruby/4.0.0/rubygems/command.rb:326:in 'Gem::Command#invoke_with_build_args'
C:/ruby/lib/ruby/4.0.0/rubygems/command_manager.rb:252:in 'Gem::CommandManager#invoke_command'
C:/ruby/lib/ruby/4.0.0/rubygems/command_manager.rb:193:in 'Gem::CommandManager#process_args'
C:/ruby/lib/ruby/4.0.0/rubygems/command_manager.rb:151:in 'Gem::CommandManager#run'
C:/ruby/lib/ruby/4.0.0/rubygems/gem_runner.rb:56:in 'Gem::GemRunner#run'
C:/ruby/bin/gem.cmd:20:in '<main>'
```
## What is your fix for the problem, implemented in this PR?
Instead of working around the situation in the affected gem or to skip symlinks completely, I think the better solution would be to make copies of the files in question. This would allow Windows users to install and use the gem smoothly.
The switch for the "Developer Mode" is available in the Windows registry under
`HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\AppModelUnlock`
entry
`AllowDevelopmentWithoutDevLicense`
https://github.com/ruby/rubygems/commit/ca6c5791fe
|
|
- ### Problem
Selecting a version for a given package is a extremelly hot path.
In a very large gemfile and a deep dependency tree (like the one
we have in our monolith at Shopify), this codepath is hit around 3.2
million times in total during the resolution phase.
### Context
When the resolution starts, Bundler fetch and turn every possible
versions of a gem that was ever released on Rubygems.org into a
possible candidate. We end up with a massive matrix of possibilites
that PubGrub has to go through. In the case of a large Gemfile
like we have, we end up with ~55,000 candidates.
Many of this candidate have conflicting dependencies requirements
and as pubgrub progress, it will continously ask over and over the
same things: "Return the possible candidates given this version
constraint" (`range.select_versions(@sorted_versions[package])`).
Since this path is called so frequently (sometimes more than 8000
times for a single candidate and the same constraint), the returned
value can be cached for faster access.
### Solution
Cache the selected versions for a given constraint in a hash.
The key being an array where the first element is the package we want
to resolve and the second element is the constraint. The associated
value is all possible candidates matching.
If the resolver end up not finding a candidate (in example you run
`bundle install --prefer-local`) then Bundler will allow finding
candidates on the remote. In this case we need to invalidate the
cache as otherwise the candidates from the remotes will not
be considered.
### Benchmark
This change has a huge impact on resolution time. Those measures
were taken on Shopify monolith by removing the lockfile and measuring
only resolution time (no network or external factors affect these
results.)
┌─────┬──────────┬───────────┬─────────┐
│ Run │ Original │ Optimized │ Speedup │
├─────┼──────────┼───────────┼─────────┤
│ 1 │ 19.20s │ 10.32s │ 46.3% │
├─────┼──────────┼───────────┼─────────┤
│ 2 │ 19.17s │ 10.46s │ 45.4% │
├─────┼──────────┼───────────┼─────────┤
│ 3 │ 18.95s │ 10.29s │ 45.7% │
├─────┼──────────┼───────────┼─────────┤
│ 4 │ 19.17s │ 10.37s │ 45.9% │
├─────┼──────────┼───────────┼─────────┤
│ 5 │ 19.26s │ 10.30s │ 46.5% │
├─────┼──────────┼───────────┼─────────┤
│ Avg │ 19.15s │ 10.35s │ 46.0% │
└─────┴──────────┴───────────┴─────────┘
https://github.com/ruby/rubygems/commit/a4f5973f95
|
|
- During resolution, Gem::Version are compared against each other.
Since comparing versions is a very hot path we can micro optimize
it to check the happy path first.
The speed gain on the overall resolution isn't significant but the
ips gain is quite substantial. The diff chunk is small so I figure
it's worth it anyway.
```ruby
a = Gem::Version.new("5.3.1")
b = Gem::Version.new("5.3.1")
Benchmark.ips do |x|
x.report("equal regular:") { a <=> c }
x.report("equal optimized:") { a <=> c }
x.hold!("equal_temp_results")
x.compare!(order: :baseline)
end
```
```
Warming up --------------------------------------
equal optimized: 1.268M i/100ms
Calculating -------------------------------------
equal optimized: 12.738M (± 1.5%) i/s (78.50 ns/i) - 64.680M in 5.078754s
Comparison:
equal regular:: 9866605.0 i/s
equal optimized:: 12738310.3 i/s - 1.29x faster
```
ruby 3.4.8 (2025-12-17 revision https://github.com/ruby/rubygems/commit/995b59f666) +PRISM [arm64-darwin25]
https://github.com/ruby/rubygems/commit/c940f7a547
|
|
concatenation
https://github.com/ruby/rubygems/commit/7c30560939
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
|
Instead of listing all dependencies from both gemspec and lockfile,
show only the ones that actually differ to make it easier to identify
the source of the discrepancy.
https://github.com/ruby/rubygems/commit/8c551a3621
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
|
When the lockfile dependencies don't match the gemspec, display both
sets of dependencies so users can easily identify which ones differ.
https://github.com/ruby/rubygems/commit/c90d7784f8
|
|
Bundler::Plugin::Index
https://github.com/ruby/rubygems/commit/dd50b93622
|
|
https://github.com/ruby/rubygems/commit/b63c5a77a8
|
|
runs when no specific command is provided.
https://github.com/ruby/rubygems/commit/67b6b4257e
|
|
- Disclaimer: I honestly wasn't able to understand the problem and why
this solution works. I don't have a windows machine and relying on
CI machines is a bit painful.
When introducing https://github.com/ruby/rubygems/pull/9414,
master CI started to fail only on windows 3.3.
I confirmed that running the failing spec in isolation multiple
times reproduce the problem consistently.
The error being either a segfault or a Bundler error along the line
of "Illformed requirement `~> false.1.3.pre`".
I triggered some CI with debugging output and the corruption
seem to happen when `version.release` is called. It somehow
modifies the previously defined variable `segments` (it's not
a mutation).
This is the debugging output I added https://github.com/Shopify/rubygems/commit/6a147a0f8fec000f9f59b2067ef25dd7e5d29637
and the associated CI run is at https://github.com/Shopify/rubygems/actions/runs/23465022092/job/68275229509#step:7:177
Pasting here in case the CI log get cleared:
```
segments variable is [0, 12, 3, "pre"]. Object ID is 25820
version.segments is [0, 12, 3, "pre"].
========
AFTER
========
Segments is [-1, 12, 3, "pre"]. Object ID is 25820
version.segments is [0, 12, 3, "pre"].
```
In this patch, I opted to reference the `version.segments` object
directly, again, I don't know why it fixes the issue.
https://github.com/ruby/rubygems/commit/532c9733aa
|
|
Signed-off-by: Takuya Noguchi <takninnovationresearch@gmail.com>
https://github.com/ruby/rubygems/commit/bc40cc6ef6
|
|
When we run `bundle exec` it'll look at `Bundler.settings[:gemfile]`
and respect the Gemfile setting. However, when we just require
`bundler/setup` or run `Bundle.setup`, it'll not look through that.
This should make this behaviour consistent.
More details can be found at:
https://gitlab.com/gitlab-org/gitlab/-/issues/339939#note_667461354
https://github.com/ruby/rubygems/commit/5e6333108b
|
|
|
|
They may not be part of `on_param` but ripper still calls `on_ident` for them
https://github.com/ruby/prism/commit/fb5303f2b8
|
|
`::X &&= 1` for example emitted `on_int` twice
https://github.com/ruby/prism/commit/44d064c2bc
|
|
https://github.com/ruby/prism/commit/894f395449
|
|
* Refactor bundled gem warning suppressor
Related to #16369
* Accept suggestion
Co-authored-by: Hiroshi SHIBATA <hsbt@ruby-lang.org>
---------
Co-authored-by: Hiroshi SHIBATA <hsbt@ruby-lang.org>
|
|
The latest RDoc contains https://github.com/ruby/rdoc/pull/1657, which
fixes install-doc failures on some platforms.
|
|
https://github.com/ruby/prism/commit/6f597d3ff7
|
|
* See https://github.com/ruby/prism/issues/3861
https://github.com/ruby/prism/commit/3f6014dc53
|
|
Take a method, unbound method, proc, or thread backtrace location.
This is our equivalent to RubyVM::AbstractSyntaxTree.of, and could
be leveraged in something like error highlight.
Note that this uses CRuby-specific APIs on CRuby, and falls back
to using location-based APIs when those aren't available.
https://github.com/ruby/prism/commit/02a93356a3
|
|
https://github.com/ruby/prism/commit/3cffc44510
|
|
- ### Problem
Comparing Gem::Version objects is slow. It's particularly a problem
because `Gem::Version#<=>` is called million of times during
resolution when using a real world Gemfile in a large application.
The comparison has to compare all segments between the two objects,
enter conditional branches and check lexicographical order when
version is a prerelease.
### Solution
I'd like to provide a fast path for the simple scenarios by turning
a version into an integer.
By "simple scenario" I mean version up to 4 segments which
represents the vast majority of the version scheme released by
maintainers.
For sake of simplicity and understability of the code I opted to not
include prelease version ("1.0.0.alpha") in the fast path.
We'd need to turn the "pre" string into a integer while keeping
lexicographical order (`1.0.0.beta` > `1.0.0.alpha`) and I felt
it wasn't worth the complexity.
Overall, this change makes comparing version up to 5x faster (when
one version is higher than the other)
There is no speed gain when 2 versions are the same as there is
already a fast path implemented.
Checking prerelease version is a bit slower now due to a `nil` check
we are doing.
### Benchmarks
```ruby
require "benchmark/ips"
a = Gem::Version.new("5.3.1")
b = Gem::Version.new("5.3.2")
c = Gem::Version.new("5.3.1")
d = Gem::Version.new("2.0.0.alpha")
Benchmark.ips do |x|
x.report("less than regular:") { a <=> b }
x.report("less than optimized:") { a <=> b }
x.hold!("lesser_than_temp_results")
x.compare!(order: :baseline)
end
Benchmark.ips do |x|
x.report("greater than regular:") { b <=> a }
x.report("greater than optimized:") { b <=> a }
x.hold!("greater_than_temp_results")
x.compare!(order: :baseline)
end
Benchmark.ips do |x|
x.report("equal regular:") { a <=> c }
x.report("equal optimized:") { a <=> c }
x.hold!("equal_temp_results")
x.compare!(order: :baseline)
end
Benchmark.ips do |x|
x.report("prerelase regular:") { a <=> d }
x.report("prerelease optimized:") { a <=> d }
x.hold!("prerelease_temp_results")
x.compare!(order: :baseline)
end
```
```
Warming up --------------------------------------
less than optimized: 1.352M i/100ms
Calculating -------------------------------------
less than optimized: 13.599M (± 0.8%) i/s (73.53 ns/i) - 68.947M in 5.070279s
Comparison:
less than regular:: 2622912.7 i/s
less than optimized:: 13599139.2 i/s - 5.18x faster
_________________________
Warming up --------------------------------------
greater than optimized:
1.355M i/100ms
Calculating -------------------------------------
greater than optimized:
13.581M (± 0.6%) i/s (73.63 ns/i) - 69.120M in 5.089497s
Comparison:
greater than regular:: 2637899.0 i/s
greater than optimized:: 13581319.7 i/s - 5.15x faster
_________________________
Warming up --------------------------------------
equal optimized: 1.360M i/100ms
Calculating -------------------------------------
equal optimized: 13.577M (± 0.7%) i/s (73.65 ns/i) - 68.010M in 5.009445s
Comparison:
equal regular:: 13885209.5 i/s
equal optimized:: 13576932.0 i/s - same-ish: difference falls within error
_________________________
Warming up --------------------------------------
prerelease optimized:
358.680k i/100ms
Calculating -------------------------------------
prerelease optimized:
3.595M (± 0.6%) i/s (278.17 ns/i) - 18.293M in 5.088687s
Comparison:
prerelase regular:: 4174692.2 i/s
prerelease optimized:: 3594907.8 i/s - 1.16x slower
```
https://github.com/ruby/rubygems/commit/6ef9f279d9
|
|
The method for marking something as deprecated is currently unused but seems fine leave as is.
https://github.com/ruby/prism/commit/5b523dfe6e
|
|
https://github.com/ruby/prism/commit/eb1d518736
|
|
https://github.com/ruby/prism/commit/b5683c8708
|
|
https://github.com/ruby/prism/commit/75eb63e102
|
|
https://github.com/ruby/prism/commit/f50c25b5c1
|
|
https://github.com/ruby/prism/commit/1c1e94849e
|
|
https://github.com/ruby/prism/commit/b66fbf9f85
|
|
https://github.com/ruby/prism/commit/06a944a08f
|
|
https://github.com/ruby/prism/commit/f02d270409
|
|
https://github.com/ruby/prism/commit/fb0d1369f4
|
|
https://github.com/ruby/prism/commit/ee6f320689
|
|
https://github.com/ruby/prism/commit/bbc2023d0b
|
|
https://github.com/ruby/prism/commit/10ebcaf908
|
|
https://github.com/ruby/prism/commit/7cb8b59590
|
|
https://github.com/ruby/prism/commit/035061c506
|
|
https://github.com/ruby/prism/commit/92b48ce940
|
|
https://github.com/ruby/prism/commit/88a247a486
|
|
https://github.com/ruby/prism/commit/1b594e10da
|
|
https://github.com/ruby/prism/commit/2b5298128e
|
|
https://github.com/ruby/prism/commit/a4a44cb14a
|
|
https://github.com/ruby/prism/commit/323f7f16f8
|
|
https://github.com/ruby/prism/commit/1e3ec12adc
|
|
https://github.com/ruby/prism/commit/01d575aa2f
|
|
https://github.com/ruby/prism/commit/400b217393
|
|
https://github.com/ruby/prism/commit/8ad880255d
|
|
https://github.com/ruby/prism/commit/2496b0105b
|