SpecGroup#merge compares the sources of candidates, which are nearly always the same object, and every comparison built the credential-less remote strings of both sides. This removes about 300,000 allocations from `bundle update` in the large scenario of tool/bench.
https://github.com/ruby/rubygems/commit/6c17f3b152
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
An override change made the lockfile count as needing resolution, so `bundle install` fetched the remote index and failed offline when the compact index cache was absent, and `Bundler.setup` re-resolved on boot. The section only needs to be regenerated, which #write_lock already does when the contents differ, and the frozen check still reports the change.
https://github.com/ruby/rubygems/commit/a616f3d1bb
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Time#utc_offset: use America/New_York, as musl parses "EST5EDT" as
a POSIX TZ string instead of loading the zoneinfo file.
* Time#zone: musl accepts "hello-foo" as a POSIX TZ string.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Process.setproctitle and $0 specs used `ps -ocommand= -p`, but busybox
ps does not support -o/-p.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
busybox is a multi-call binary which dispatches on argv[0], so it
cannot run as /bin/sh with an arbitrary argv[0] such as "argv_zero".
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
`bundle lock --add-checksums --add-platform arm64-darwin` wrote a
lockfile that listed arm64-darwin under PLATFORMS but carried none of
its platform-specific gems. `Definition#add_checksums` resolves the
bundle to fetch the checksums, and it ran before the platform options
were applied, so the resolution never saw the new platform.
This usually went unnoticed. `SpecSet#add_extra_platforms!` tries to
complete every platform the sources know about, and for most bundles
that added the darwin gems anyway. It stops working as soon as one gem
has a precompiled darwin build whose `required_ruby_version` excludes
the current Ruby (bcrypt_pbkdf 1.1.2 on Ruby 3.4): `complete_platform`
then gives up on darwin for every gem, and the lockfile ends up listing
a platform it has no gems for. Running `bundle lock` again does not
repair it, because the platform is already listed.
Apply `--add-checksums` after the platform changes have been recorded.
https://github.com/ruby/rubygems/commit/2f1d325fc2
Resolving through the full-index API lazily downloads individual
gemspecs from /quick/Marshal.4.8/*.gemspec.rz. `Fetcher#fetch_spec` made
that request bare:
Bundler.safe_load_marshal Bundler.rubygems.inflate(downloader.fetch(uri).body)
while `specs_with_retry`, in the same class, wraps its network call in
`Bundler::Retry`. So a single transient failure — a read timeout, say —
aborted the whole resolution, no matter what BUNDLE_RETRY was set to.
That is most painful without a lockfile, where a resolve can fetch a
great many gemspecs one at a time and any one of them can end it.
Wrap the download in the same `Bundler::Retry.new("fetcher", FAIL_ERRORS)`
the index path already uses. FAIL_ERRORS is what keeps this from retrying
things that will not change, such as authentication failures.
Only the download branch is wrapped. The file:// and cached-gemspec
branches do no network I/O, so retrying them would just repeat a local
failure.
Closes https://github.com/ruby/rubygems/pull/9817https://github.com/ruby/rubygems/commit/9578cf9e93
Gem.open_file_with_lock removed its lock file after releasing the lock.
Since flock locks the file itself rather than its path, a process that
was waiting on the old file could acquire it after it had been removed,
while a newly arriving process created a fresh lock file and locked it
immediately, so both ran at the same time.
Remove the lock file while still holding the lock, and after acquiring
it, check that the locked file is still the one at the lock path,
retrying otherwise.
https://github.com/ruby/rubygems/commit/9a93c235e7
Gems sourced from the same git repository share one cache directory.
Since git sources are preloaded in parallel, two workers could run git
fetch in that directory at the same time, and the fetches collided on
the shallow file and its lock, failing bundle install.
Group the sources by cache path and preload each group in a single job,
so sources sharing a cache run one after another while separate
repositories still run in parallel.
Fixes https://github.com/ruby/rubygems/pull/9946https://github.com/ruby/rubygems/commit/c20901e6a1
Override.from_lock accepted a line such as `"rake", version: "garbage"`, and the bad requirement only failed later as a Gem::Requirement::BadRequirementError outside the parser. Normalizing it while parsing turns it into a LockfileError that names the line.
https://github.com/ruby/rubygems/commit/4f594ea354
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Bundler now writes the Gemfile overrides to an OVERRIDES section, one
line per field, sorted, with normalized requirements. The lockfile
parser reads the section without evaluating it. A change to the
overrides now changes the lockfile, and a frozen install fails with a
summary of the added and deleted overrides.
OVERRIDES is a known section, but it is not in
SECTIONS_BY_VERSION_INTRODUCED. Thus Bundler also compares it for
lockfiles that are still bundled with an older Bundler.
Override targets, from: and to: must now be valid gem names.
https://github.com/ruby/rubygems/commit/72bcc33d07
With ipaddr 1.3, bracketed IPv6 addresses with a prefix length are
warned and will result in an error in future versions (likely ipaddr
1.4). Also, future versions of Ruby (likely 4.2) will bundle this
version.
The spec checks that the Kernel.require monkeypatch is still used, by
comparing the whole stdout. However, the script ended with an uncaught
LoadError for the non-existent "foo", and Ruby lazily loads
error_highlight, did_you_mean, and syntax_suggest when displaying an
error. If they are loaded through Kernel.require, the monkeypatch also
prints them and the spec fails, although that is unrelated to what the
spec checks. Rescue the LoadError so that no error is displayed.
https://github.com/ruby/rubygems/commit/5e1a0bd5af
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
`configure.bat --with-gnu-make` writes only `GNUmakefile`. The tests under `test/mkmf` failed to load with `Errno::ENOENT`, and `spec/default.mspec` lost `srcdir` and ran specs without `tool/runruby.rb`.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Method#syntax_tree & co. now parse with Ruby::Prism, the parser built
into the interpreter, instead of `require "prism"`. The returned
nodes always come from the parser that parsed the code, so the
"a prism gem other than the default gem is loaded" warning, the
Gem.loaded_specs check, and the ArgumentError rescue for a prism that
does not know the running Ruby's grammar are no longer needed.
The specs are updated to expect Ruby::Prism nodes.
[Bug #22379]
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Once rb_len_t widens this changes the `long *` output parameters of rb_range_beg_len(), rb_str_subpos(), rb_arithmetic_sequence_beg_len_step(), ruby_enc_find_basename() and ruby_enc_find_extname(), so extensions passing `long *` to them will need to be updated. The extension guides list these signatures verbatim and follow along.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
A server that answers 416 even after Range is dropped made Bundler::Fetcher::Downloader#fetch recurse until SystemStackError. Raise Bundler::HTTPError instead, as Gem::CompactIndexClient::HTTPFetcher does.
https://github.com/ruby/rubygems/commit/65835147fa
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Some gems depend on a gem that only one of their features loads, or on a gem that an API-compatible one can stand in for. `override "B", from: "A", to: nil` drops the dependency of A on B, and `to: "C"` makes A depend on C instead.
The lockfile keeps every dependency as published, the same way `version:` overrides leave it, and the completeness checks, the installer and the source lookup apply the override instead.
https://github.com/ruby/rubygems/pull/9517#issuecomment-5992001829https://github.com/ruby/rubygems/commit/231ecdf564
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Terminal devices picked by `find` can disappear while the specs run, and without a terminal on stdin `tty` prints "not a tty" to stdout, which became the path when `find` printed nothing. `File.lstat` matches how the specs check the type, so a symlinked /dev/null, as on Solaris, still falls back to the search.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
These examples break when a library on RUBYLIB takes precedence over the gem they rely on. ruby core puts its source and extension directories there, but the condition is about RUBYLIB, not about being ruby core.
https://github.com/ruby/rubygems/commit/3031023478
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Gem::ContentAddress is available in ruby core. What actually blocks these examples is that a prerelease Ruby never satisfies the ~> X.Y.0 pin of content-addressed gems, so they can still run on a release build.
https://github.com/ruby/rubygems/commit/8f3972f031
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Ruby built from source on macOS runs dsymutil on every extension, and the recursive glob matched both the .dSYM directory and the files inside it, so rm_r failed on entries it had already removed. This was the unknown failure that made the spec skipped in ruby core.
https://github.com/ruby/rubygems/commit/bee3cf9694
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A gem in a monorepo can need a sibling directory besides its own, and git takes several cone directories. Values that are not directory names now raise a Gemfile error instead of a TypeError from computing the install path.
https://github.com/ruby/rubygems/commit/9a2fae7b06
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
`git sparse-checkout set` only learned --cone in git 2.35. Older versions take it as a pattern and fall back to non-cone matching, which drops the top-level files a cone checkout keeps.
https://github.com/ruby/rubygems/commit/5c8945d7df
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>