- After #23381, homebrew-core CI fails installing dependencies on
version-bump PRs: the bumped formula's stale bottle block derives
its manifest URL from the new version, whose bottle has not been
published yet, and `DownloadQueue#fetch` treats every bottle
manifest failure as fatal.
- Before that change the default ask-mode plan fetched manifests
synchronously via `Formula#fetch_bottle_tab`, which rescues
download errors so dependency resolution falls back to a full
install, and the installer's memoisation then kept the queue from
retrying the download.
- Add `DownloadQueue#fetch(allow_failures:)`: failed downloads are
still reported but neither raise nor mark the fetch or run as
failed. Use it for the metadata-only drains (`fetch_formulae`'s
bottle manifest waits, `brew install`'s ask-mode drain and
`brew upgrade`'s tab prefetch), restoring the synchronous path's
tolerance. Manifest failures in fetches that pour bottles remain
fatal.
- `brew install` only started network transfers after preinstall
checks and, in ask mode, fetched each bottle manifest serially
while computing the dry-run plan.
- Enqueue bottle manifests on the shared download queue right after
building formula installers in both ask and no-ask modes so
transfers overlap preinstall checks and dependant scanning and
manifests for multiple formulae download concurrently. Ask mode
drains them under a `Downloading bottle manifests` heading before
printing the plan; warm runs enqueue nothing and stay silent.
- Once downloads are confirmed (`--yes` installs, reinstall, upgrade
and other `Install.fetch_formulae` callers), also enqueue the
formula's own bottle in `FormulaInstaller#prelude_fetch`: the blob
URL needs neither the manifest nor dependency resolution, so both
transfer concurrently and staging joins the same queue cycle.
- Skip the `enqueue_fetch` requeue for bottles the prelude fetch
already enqueued so a completed early download is not reported a
second time.
- Give `DownloadQueue#fetch` `only:` and `heading:` so a heading is
always printed before any queue output and never for empty fetches:
dependency resolution inside `Install.fetch_formulae` waits on just
the bottle manifests it needs (under `Downloading bottle manifests`)
and the cask source pre-fetch on just its cask files, keeping other
in-flight downloads queued and unreported so bottles only ever
appear under the `Fetching downloads for:` heading, which now
prints lazily from the fetch that reports them (`brew upgrade`
enqueues before it knows that heading's contents). This replaces
`Install.show_combined_fetch_downloads_heading`, `brew upgrade`'s
manual manifest heading predicate and its dead
`show_downloads_heading` plumbing.
- Instrument `Install.perform_preinstall_checks_once` as a
`preinstall_checks` phase timing to keep the reordering visible.
- Archive-cold `brew install hello`: the first transfer starts at
~375ms instead of ~442ms, the bottle no longer waits for the
manifest round trip (~672ms before, ~375ms now) and `--yes` wall
time drops around 30%. Two-formula ask-mode installs drop one full
manifest round trip (~1240ms to ~1030ms).
- One malformed formula or cask (e.g. a bottle `root_url` that is an
invalid URI) raised while enqueueing downloads and aborted the whole
`brew upgrade` batch with an internal stack trace.
- Rescue anything raised by an individual formula's or cask's prelude
and enqueue steps so the offending package is reported and skipped,
the rest still proceed and the command exits nonzero.
Fixes https://github.com/Homebrew/brew/issues/23377.
- Make every statically-poked method public and call it directly,
keeping `public_send` only for dynamically-named public methods.
- Read and write state through public `attr_*` accessors instead of
instance variable reflection.
- Enable `Homebrew/NoSendInTests` and
`Homebrew/NoInstanceVariableAccessInTests` now the test suite is
clean, so neither pattern creeps back in.
- Keep rare justified disables, e.g. `Module#remove_const` is
private core Ruby and raw memoisation state has no accessor.
Group `brew upgrade --dry-run` dependencies into separate "Would install"
and "Would upgrade" sections aligned with format_upgrade_summary, and read
the installed version from the kegs so unlinked upgrades still show
"old -> new".
Also stop the first dependency in the "Installing dependencies for" line
from rendering bolder than the rest.
`pretty_install_status` already gates the upgradable status on
`installed && outdated`, so callers passing
`outdated: installed && formula.outdated?` duplicated the guard.
Pass `outdated: formula.outdated?` directly and let the method
combine it with `installed`.
The install dependency list is already a plain "would install" list,
so bolding the upgradable entries made them stand out inconsistently
from the fresh installs. Add a `bold:` option to `pretty_upgradable`
and `pretty_install_status` (defaulting to `true` to preserve `brew
info` styling) and pass `bold: false` from the install plans.
Show installed-but-outdated dependencies with the upgradable status
already used by `brew info`, so the install dependency list signals
an upgrade rather than looking like a fresh install.
- Start formula prelude fetches before dependant checks when no prompt can block.
- Share idempotent prelude-fetch queueing across install, reinstall and upgrade.
- Reuse the early queue later to avoid changing pour/link behaviour.
- keep `brew doctor` visibility while moving install-time hints to
non-fatal preinstall diagnostics
- document why explicit trust matters before the default changes in
Homebrew 6.0.0 or 5.2.0
- clean untrusted hosted-runner taps before test-bot setup so unrelated
runner state does not fail `brew doctor`
- Prevent `brew bundle install --cleanup` from removing packages unless
ask mode or an explicit force cleanup path is used.
- Share the ask confirmation helper with install, upgrade and bundle
cleanup flows so prompts behave consistently.
- Keep generated help and completions aligned with the safer cleanup
contract.
Signed-off-by: Patrick Linnane <patrick@linnane.io>
- Allow `brew --ask` prompts to proceed from `y` or `Y`.
- Abort from `n` or `N` without waiting for a newline.
- Treat Escape, Ctrl-D and Ctrl-C as quiet cancellation.
- Reprompt after other keys so users choose explicitly.
- Avoid splitting cask source fetches from combined upgrade fetches
- Keep language-specific caskfiles on a prefetch queue only when needed
- Hide `Downloading Cask files` unless that queue will fetch new files
- Set `HOMEBREW_ASK` before Ruby starts so `EnvConfig.ask?`
can stay generated.
- Let `HOMEBREW_NO_ASK` suppress environment defaults while
keeping explicit `--ask` authoritative.
- Document and enforce TTY-only confirmation prompts so
non-interactive runs keep moving.
- Use dry-run-style `--ask` plans for install and reinstall commands.
- Make single-package operations proceed without a prompt e.g. if you
`brew install foo` and there's no dependencies or dependents to install:
just install without the prompt.
- Keep prompting when dependencies or dependents change the plan.
- Reuse dry-run upgrade planning for `--ask` so users see
the same package list before choosing whether to continue.
- Suppress dependency and dependent dry-run sections when they
duplicate the final `outdated packages` summary.
- Include available formula bottle download sizes inline in the
dry-run package list.
- Keep `--ask` prompts default-no and ahead of downloads.
Replace all uses of installed_as_dependency with !installed_on_request.
Stop storing installed_as_dependency in new Tabs for both formulae and casks.
installed_on_request is now the single source of truth.
Fixes#21751
`Pathname#children.empty?` reads all directory entries into a Ruby Array
just to check whether any exist. `Pathname#empty?` (backed by
`Dir.empty?`) stops at the first entry, avoiding the full enumeration.
Microbenchmark (100,000 iterations, 11-entry Cellar keg directory):
dir.children.empty? : 3084ms
dir.empty? : 2136ms (~1.44x faster)
`Formula#latest_version_installed?` and the prefix-installed check in
install.rb are called for every formula when commands like
`brew deps --installed` enumerate installed formulae, so the savings
compound across the full set.
- cleanup various cases conditional on the download queue to always
use it, now it's default and has been for a while
- ensure that both casks and formulae are fetched at the same time
when possible to maximise concurrency
- generally DRY up the relevant download queue code
Move `disk_usage_readable_size_unit`, `disk_usage_readable`,
`number_readable`, and `redact_secrets` from `extend/kernel.rb` to
`utils/formatter.rb` as class methods. These methods are formatting
utilities that fit better in the Formatter module.
Update all call sites and move corresponding specs to formatter_spec.rb.
inherited_options feature was originally added to support cascading
`option :univeral` back in 793d6de6c3.
This is now dead code given `:universal` support was removed.
This reduces the surface area of our `Kernel` monkeypatch and removes
the need to `include Kernel` in a bunch of modules.
While we're here, also move `Kernel#require?` to `Homebrew` and fully
scope the calls to it.
Follow up on `DownloadQueue` for download concurrency on `brew fetch`
and `brew install` to also add support for `brew reinstall` and
`brew upgrade`.
This required a fair bit of refactoring to make this work so I've also
made `install.rb`, `reinstall.rb` and `upgrade.rb` `typed: strict` to
add some extra guardrails from Sorbet here.
Co-authored-by: Carlo Cabrera <github@carlo.cab>
Allowing using `HOMEBREW_DOWNLOAD_CONCURRENCY` to use the
`DownloadQueue` for `brew install` by downloading and extracting
bottles in parallel.
This requires some fixes in e.g. `Dependency` and `FormulaInstaller`
to be able to front-load all downloads and handle parallelisation of
bottle pouring.
Behaviour without `HOMEBREW_DOWNLOAD_CONCURRENCY` set should be
unchanged.
Attestations are not handled for now and the UI should be improved
before we roll this out to users.
Post-install upgrades are not yet parallelised.
Co-authored-by: Carlo Cabrera <github@carlo.cab>
- Because `name` is not a method on `FormulaInstaller`, instead
`formula` shows the name.
- Fixes issue 20199.
Before:
```
$ brew install -n hello
Error: undefined method 'name' for an instance of FormulaInstaller
Warning: Removed Sorbet lines from backtrace!
Rerun with `--verbose` to see the original backtrace
/opt/homebrew/Library/Homebrew/install.rb:330:in 'Array#map'
/opt/homebrew/Library/Homebrew/install.rb:330:in 'Homebrew::Install.install_formulae'
```
After:
```
$ brew install -n hello
==> Would install 1 formula:
hello
```