Skip to content

autoremove: cross-check candidates against formula definitions#21725

Open
costajohnt wants to merge 1 commit intoHomebrew:mainfrom
costajohnt:fix/autoremove-reverse-dep-check
Open

autoremove: cross-check candidates against formula definitions#21725
costajohnt wants to merge 1 commit intoHomebrew:mainfrom
costajohnt:fix/autoremove-reverse-dep-check

Conversation

@costajohnt
Copy link
Contributor

@costajohnt costajohnt commented Mar 13, 2026

Fixes #21511

Problem

brew autoremove suggests removing formulae (e.g. libthai) that brew uninstall then refuses to remove because they're still needed by installed formulae (e.g. pango).

The root cause: removable_formulae uses installed_runtime_formula_dependencies to build its dependency graph, which reads from tab data (INSTALL_RECEIPT.json). When homebrew-core adds a new dependency to a formula (e.g. adding libthai to pango), the installed bottle's tab doesn't reflect this — the tab is written at install time and never updated.

#21519 fixed a name-comparison issue but the stale tab problem remains for users who haven't reinstalled affected bottles.

Approach

The suggested fix was to use the same dependency resolution as brew uninstall (InstalledDependents.find_some_installed_dependents). I tried this first, but discovered it doesn't work: InstalledDependents ultimately calls runtime_dependencies(read_from_tab: true), which reads from the same stale tab data. The uninstall command only catches the problem because missing_dependencies triggers linkage analysis as a secondary check — not because of the reverse dependency logic itself.

Instead, this PR cross-checks autoremove candidates against current formula definitions by calling runtime_formula_dependencies(read_from_tab: false, undeclared: false) on non-candidate (installed-on-request) formulae. This reads from .rb formula files, which are always current after brew update. If any non-candidate's formula definition lists a candidate as a dependency, that candidate is kept.

The check iterates until convergence to handle cascading dependencies (e.g. if formula A needs B and B needs C, both B and C are kept). Falls back gracefully on error.

Test plan

  • brew tests --only=utils/autoremove — all specs pass
  • brew style — no offenses
  • Local verification: simulated stale tab data for pango/weasyprint, confirmed libthai is incorrectly listed for removal without the fix and correctly excluded with it
  • CI passes

@costajohnt
Copy link
Contributor Author

BEFORE fix:
Screenshot 2026-03-12 at 6 34 01 PM

AFTER fix applied:
Screenshot 2026-03-12 at 6 34 17 PM

The forward dependency check in `removable_formulae` relies on tab data
(INSTALL_RECEIPT.json) which becomes stale when homebrew-core adds new
dependencies to a formula. Cross-check autoremove candidates against
current formula definitions by calling `runtime_formula_dependencies`
with `read_from_tab: false` on non-candidate formulae. The check
iterates until convergence to handle cascading dependencies and falls
back gracefully on error.

Fixes Homebrew#21511
@costajohnt costajohnt force-pushed the fix/autoremove-reverse-dep-check branch from 3b547b1 to 8696502 Compare March 13, 2026 02:31
@costajohnt costajohnt marked this pull request as ready for review March 13, 2026 02:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

brew cleanup says libthai can be removed, but at the same time it is needed by pango

1 participant