Adds a `brew deadcode` dev-cmd that finds and removes dead code identified
by Spoom, excluding test code so that definitions referenced only by their
specs are also treated as dead. Definitions documented with `# @api public`
or `# @api internal`, or defined with an `override` signature, are always
kept, since Spoom cannot see their dynamic, subclass or cross-tap (e.g.
homebrew-core) callers.
Removes the dead code it identified, restoring false positives (dynamically
dispatched diagnostic checks and cask stanza classes, TestRunnerFormula
platform predicates, livecheck skip conditions, TopologicalHash tsort
methods and YARD docstring plugin methods). homebrew-core-used helpers such
as kernel_major_version, deny_network_access!, require_root and
detected_python_shebang are restored and annotated `# @api internal`.
Test-only cache resets are relocated into the specs that need them.
Recent formula and cask DSLs need consistent ordering registrations, but
Cask ordering cannot be enforced until the tap has been migrated.
- register new Cask artifact and conditional stanzas in their intended order
- allow both completion layouts while retaining group boundaries
- leave formula component ordering to `ComponentsOrder`
- document the intended Cask stanza order before enforcing it
- Replace `addressable` and `public_suffix` with Ruby's `URI` while
retaining brewed-curl host detection.
- Inline JWS decoding and scoped warning filtering.
- Keep Base64 only as ruby-prof's on-demand transitive dependency.
- Remove unused Redcarpet and the largely unmaintained Pry backend.
- Defer heavy runtime gems until their functionality is needed.
- Resolve lazy type dependencies before Sorbet runtime checks.
Hyperfine (`--warmup 10 --runs 30`, repeated in both orders):
- `HOMEBREW_NO_AUTO_UPDATE=1 brew info --json=v2 jq`:
528.9 ms ± 21.1 ms on `origin/main` and 512.6 ms ± 16.2 ms
here, a 3% speedup.
The `r` and `wireshark` casks were renamed to `r-app` and
`wireshark-app` in Homebrew/homebrew-cask d20f5f8baba
("Differentiate lesser used casks from formulae"), so the
`on_<system>` example links in this section now 404.
Four LLVM and Clang formulae share macOS target configuration generation
for the active SDK and kernel versions.
- skip non-macOS installs and generated native configurations
- select the current or versioned Command Line Tools SDK
- emit compatible arm64, aarch64 and x86_64 target files
Annotate every method in the Formula Cookbook's "Service block methods"
table as `@api public` in `Service`, with documentation matching the
cookbook's descriptions, and add the missing `stop_timeout` row to the table.
Enforce a 1:1 correspondence between the table and the `service.rb`
annotations in the `Homebrew/PublicApiCookbook` cop, backed by a new
`SERVICE_COOKBOOK_METHODS` list, so the two cannot drift.
Claude-Session: https://claude.ai/code/session_011BgWRBydtdkvt8ocqH4nj9
Three glibc-family formulae share locale generation and timezone-link
setup with different rules for the legacy variants.
- derive requested locales while always providing the UTF-8 default
- invoke the installed `localedef` with normalised charmaps
- preserve host timezone links when their sources exist
Several binary formulae ship a gzipped executable that needs the same
guarded post-install expansion and mode handling.
- resolve serialised source and destination path bases
- skip absent payloads and replace stale expanded sources
- install each executable with an explicit literal permission mode
Eight GCC formulae share the same Linux runtime-link and specs
generation algorithm after installation.
- probe the active GCC and glibc runtime locations
- generate family-appropriate library, linker and header search paths
- keep the repeated algorithm behind one literal formula step
Some formula hooks only warn when a persistent path needs user attention
and do not need arbitrary post-install code.
- add a literal warning step shared with cask flight phases
- compose warnings with path guards instead of embedded conditions
- expand fixed context tokens in warning messages
Flight hooks repeatedly stop applications or helpers before mutating
their installed state.
- select processes by exact name or full command line
- serialise attempts, privilege and required-success policies
- preserve fixed user notices and final failure warnings
Many remaining hooks invoke one packaged or system executable and do not
need a Ruby block or shell command string.
- serialise literal arguments, environments, streams and directories
- resolve path bases, templates and guards through shared contexts
- make privilege, output and required-success policies explicit
- migrate GIO callers while retaining the shipped compatibility DSL
Command wrapper callers should declare the command users receive rather
than an implementation-specific staged script filename.
- treat the positional argument as the linked command name
- keep generated wrapper paths internal to the artifact
- reject names containing path components
- document command wrappers as the shim-script replacement
- Avoid false homepage audits when sites block automated requests
- Resume automated checks one year after a human browser check
- Do not suppress audits for future browser-check dates
- Reject browser-check metadata without a homepage URL
- Document the marker in the formula and cask cookbooks
Three core formulae adjust modes on persistent paths after installation
but do not need ownership changes or arbitrary Ruby.
- admit the existing `set_permissions` step in formula blocks
- keep `set_ownership` limited to cask blocks
- document and audit the formula capability explicitly
Most command wrappers only execute one binary with optional fixed
arguments or environment variables. Repeating their complete shell
content makes casks harder to audit and maintain.
- generate wrappers from `executable`, `args` and `env` options
- infer the linked target by removing the `.wrapper.sh` suffix
- retain `content` for wrappers which need custom shell logic
- The formulae.brew.sh env-config table was hard to interpret: unset
and explicitly-set-to-default runs were merged as "default events",
nothing showed what a variable's default was and variables brew
exports itself (`HOMEBREW_UPDATE_TO_TAG` in `cmd/update.sh`,
`HOMEBREW_EDITOR`/`HOMEBREW_DISPLAY` etc. copied from the user
environment in `bin/brew`) dominated the chart as fake user
configuration.
- Record `HOMEBREW_USER_SET_VARS` at `bin/brew` startup, after
`brew.env` files load but before any exports, so sampling and
`brew config` can tell deliberate configuration apart; sub-brews
inherit the list.
- Replace the `env_config_non_default` tag with a single
`env_config_state` tag (`unset`/`default`/`non_default`) computed
from user-set values only.
- Compute previously `default_text`-only defaults so explicitly-set
default values are ignored everywhere: `HOMEBREW_AUTO_UPDATE_SECS`
(mirroring `brew.sh`), `HOMEBREW_FORBID_PACKAGES_FROM_PATHS` (now
`boolean: :set`, matching its accessor), `HOMEBREW_PIP_INDEX_URL`
and `HOMEBREW_SSH_CONFIG_PATH`; generated accessors and
`non_default_variable?` call callable defaults and treat blank
booleans as unset like their accessors.
- `brew config` now only prints user-set non-default variables and
`Resource#determine_url_mirrors` only rewrites PyPI URLs for
non-default `$HOMEBREW_PIP_INDEX_URL` values.
- Sanitise `formula-analytics` results: only current variables and
valid states are accepted and the query requires the new tag,
which drops the contaminated data already collected.
- Stop excluding CI events from `command_run_options`: CI users are
normal users so CI-only usage should stay visible.
- Output `non_default_count`, `set_default_count`, `unset_count` and
`default_value` per variable in JSON, using the human
`default_text` summary for varying defaults via
`EnvConfig.default_description`, now shared with the manpage.
- Labelling any open Homebrew/brew issue or pull request with
`release blocker` now stops `brew release` and the `release.yml`
`workflow_dispatch` run before a release is created.
- `major/minor release blocker` only blocks releases whose version
ends in `.0`.
- Checking in the workflow as well as the command means releases
triggered directly from the GitHub UI are also blocked.
Casks have a `DeprecateDisable` `unreachable` reason that we use when
a website is unreachable (e.g., anti-bot protections make the asset
inaccessible). Formulae have similar reasons like `repo_archived`
but none of the existing reasons account for the situation where a
project is supported and maintained but it's not possible to reach the
server outside of a browser to download release assets. This adds the
`unreachable` reason to the `FORMULA_DEPRECATE_DISABLE_REASONS` hash,
so we can use it in formulae as well.
Some cask flight hooks only materialise a fixed helper before another
artifact or install step consumes it.
- write literal executable content as a serialisable cask artifact
- restrict generated paths to the staged cask and reject traversal
- order generated scripts before dependent installer artifacts
Many cask flight hooks only write a fixed launcher and link it into the
configured binary directory.
- generate executable wrapper content as a first-class cask artifact
- reuse binary linking, collision and uninstall behaviour
- serialise the stanza so cask JSON preserves its definition
- Fetch manifests from custom bottle domains before falling back to GHCR.
- Preserve full relocation and its once-per-invocation guidance when
usable metadata is still unavailable.
- Keep `HOMEBREW_BOTTLE_DOMAIN` supported while documenting
`HOMEBREW_ARTIFACT_DOMAIN` as the preferred transparent proxy.
Fixes#12759Fixes#23218Closes#23237