Homebrew's Ruby and Bash startup cost is most noticeable on common API-backed
commands, so add a tightly gated Rust frontend experiment for search, info,
list, and the essential mutating commands. The goal is to make iteration on a
faster CLI possible without changing the default user experience or taking on
the risk of reimplementing all of FormulaInstaller in Rust on day one.
Keep the risk contained by only enabling the Rust path on supported Tier 1
default-prefix installs when both HOMEBREW_DEVELOPER and
HOMEBREW_EXPERIMENTAL_RUST_FRONTEND are set, and by continuing to delegate
complex install, upgrade, uninstall, and update behaviour back to the existing
Homebrew frontend for v1 correctness. That lets us measure the frontend win
first and only move more logic out of Ruby when profiling proves it is worth
the complexity.
Build brew-rs through vendor-install and run Rust subtree tasks through
portable Ruby's rake so local development, first-run bootstrapping, and CI all
use the same path instead of bespoke scripts. Add integration coverage, a
dedicated workflow, hyperfine benchmarks, Dependabot support, and Rust-specific
docs so the experiment is easy to validate, benchmark, and evolve.
When a tap formula has no URL, `determine_active_spec` raises
`FormulaSpecificationError`. `Formula.all` already rescues
`FormulaUnavailableError` and `FormulaUnreadableError` to prevent
a single broken formula from crashing commands like `brew search
--eval-all --desc`, but `FormulaSpecificationError` was missing
from the rescue clause.
Closes#21794
Under some e.g. AI sandboxes HOMEBREW_CACHE is not accessible but
the current working directory's `tmp` is instead. In those cases,
print a warning and automatically copy and use the other cache.
generate_formula_struct_hash works on a dup'd copy of the input,
so the original hash is never modified. Check the returned struct's
head_dependencies and stable_dependencies accessors instead.
Include urls.stable.url in the test hash so generate_formula_struct_hash
can build a valid stable_url_args tuple for Sorbet. Accept Rylan12's
suggestion to add a comment explaining the head_dependencies fallback.
When `dependencies_hash` generates the API JSON, it omits
`head_dependencies` when they equal stable deps (to save space).
`FormulaStructGenerator` treated this absence as "no dependencies,"
breaking HEAD installs that inherit stable dependencies.
Fall back to the stable dependency hash when `head_dependencies`
is nil.
Fixes#21760
- move brew, cask, tap, and extension package types to single implementation classes and files
- remove legacy checker, dumper, and installer wrappers plus the old bundle helper seams they kept alive
- simplify checker and package type dispatch, and clean up extension package-manager caching and typing
We should be able to safely re-enable this cop, as the https://github.com/rubocop/rubocop/pull/14767 PR was included in rubocop `1.84.0` and we are beyond that.
CC @MikeMcQuaid - unless we're waiting for an update somewhere else?
The recent refactoring (eac1886, 3b43ae9, cd65e94) unified each
bundle package type into a single class, but the specs were still
split across separate dumper, installer, and checker files. This
made it harder to see the full test surface for a given type and
kept the test layout out of sync with the implementation it covers.
Merge the per-concern specs into one file per package type
(e.g. cargo_spec.rb replaces cargo_dumper_spec.rb and
cargo_installer_spec.rb), update requires and class references to
target the unified classes, and organise the combined examples
under "dumping", "installing", and "checking" describe blocks.
`brew livecheck` surfaces the skip reason or message in its output
(e.g., "deprecated", "skipped - Legacy version") but `brew bump`
effectively ignores the `:status` and `:messages` values from
`Livecheck::SkipConditions` and only prints "skipped" instead.
Sometimes the reason can be inferred from parenthetical annotations
(e.g., "(deprecated)" after the current version) but explicit output
like "skipped - deprecated" is easier to read when skimming. Omitting
a skip message from a `livecheck` block is only done to produce a
predictable "skipped" string that can be used for comparison but we
can handle that in a more robust way.
A related issue we're now facing is that deprecated packages are
producing an "unable to get versions" message rather than "skipped".
This adds noise and makes it more challenging to identify real
livecheck failures in bump output.
This addresses these issues by modifying bump to print the skip
`:status` and `:messages` values in the output. The way I've handled
this, bump will also print error messages. In the process, this adds
a `message?` method to check whether a value is a message string,
replacing existing conditions that insufficiently check whether a
value is a message using strict comparisons like `x != "skipped"` or
`x != "unable to get versions"` and ignoring the possibility of error
strings.
This is still an imperfect way of identifying message strings but it
should be an improvement over the status quo. In the future, it may be
better to store message strings as something other than a
`Cask::DSL::Version` object, so we can distinguish messages from
versions without targeting a specific string pattern.
- Move `brew`, `cask`, and `tap` into single implementation files while keeping the existing checker, dumper, and installer entrypoints as compatibility requires for the current tests and callers.
- Keep the shared bundle checker, dumper, and installer flows generic over registered package types and extensions, and preserve the existing App check output when `--no-upgrade` is used.
- Move the remaining non-`brew`/`cask`/`tap` bundle types onto the single-file extension path so `mas`, `vscode`, `cargo`, and `flatpak` keep their DSL, dump, check, install, and cleanup behavior in one place while shared bundle callers infer flags and selection from the registered extensions.
- Keep the existing checker, dumper, and installer entrypoint files as compatibility requires and preserve the current check, dump, and cleanup ordering so the existing bundle specs continue to exercise the same public constants and command behavior.
- Use .blank? instead of .nil? for tab_deps early return
- Remove unnecessary is_a?(Hash) guard (consistent with runtime_dependencies)
- Use .blank? instead of bare truthiness for full_name check
- Revert test to assert positive behavior with proper tab data
- Update comment to reflect nil-or-empty semantics