Skip to content

fix(install): resolve dependency-scoped bottle placeholders - #786

Merged
indaco merged 2 commits into
mainfrom
fix/dependency-scoped-placeholders
Jul 27, 2026
Merged

fix(install): resolve dependency-scoped bottle placeholders#786
indaco merged 2 commits into
mainfrom
fix/dependency-scoped-placeholders

Conversation

@indaco

@indaco indaco commented Jul 27, 2026

Copy link
Copy Markdown
Owner

Description

Some bottles reference a path inside another keg, not inside the prefix.
Relocation only substituted the prefix-derived tokens, so those references
shipped literally and the installed command failed at launch — behind an
install that reported success and a doctor run that reported the prefix
healthy. Maven was unusable out of the box; 291 formulas depend on a JDK,
71 of them on a pinned version.

The value can only be known where the formula is in scope, so the install
path resolves it from the declared dependencies and hands relocation one
extra substitution. Every command that materialises a keg does this —
install, upgrade, migrate and rollback each reach relocation by a different
route. Rollback has no parsed formula, so it reads the target version's own
shipped formula source rather than the database rows, which describe the
version being rolled away from.

The relocation cache version is bumped so kegs already cached with the
literal token are re-relocated instead of restored still broken.

doctor now also scans text files, and reports any Homebrew token rather
than the two malt substitutes. That is the check that would have caught
this class in the first place.

Related Issue

  • None

Notes for Reviewers

  • None

indaco added 2 commits July 27, 2026 01:14
Relocation substituted only the prefix-derived tokens, so a bottle whose
wrapper references a path inside another keg shipped that token literally
and was unusable at launch. That value cannot be derived from the prefix,
so the install path resolves it from the formula's declared dependencies
and passes one extra replacement down to the keg relocation.

The extra replacement is applied last: text replacements run as sequential
passes, and the path it substitutes must not be rewritten again by the
prefix rules.

Bumps the relocation logic version so cached kegs holding the literal
token are re-relocated rather than restored still broken.
The placeholder check only inspected Mach-O load commands for two tokens,
so a wrapper script that kept a relocation token read as healthy. That is
how a keg could install successfully, fail at launch, and still pass a
doctor run.

The scan now also covers text files and matches any Homebrew token rather
than the two malt substitutes: the patcher's verify gate must not fail an
install over a token it does not know, but doctor only warns, and an
unresolved token is exactly the finding worth surfacing.

The check keeps its existing id so scripted consumers are unaffected.
@indaco
indaco merged commit 95b5190 into main Jul 27, 2026
3 checks passed
@indaco
indaco deleted the fix/dependency-scoped-placeholders branch July 27, 2026 08:08
indaco added a commit that referenced this pull request Jul 27, 2026
* fix(install): resolve dependency-scoped bottle placeholders

Relocation substituted only the prefix-derived tokens, so a bottle whose
wrapper references a path inside another keg shipped that token literally
and was unusable at launch. That value cannot be derived from the prefix,
so the install path resolves it from the formula's declared dependencies
and passes one extra replacement down to the keg relocation.

The extra replacement is applied last: text replacements run as sequential
passes, and the path it substitutes must not be rewritten again by the
prefix rules.

Bumps the relocation logic version so cached kegs holding the literal
token are re-relocated rather than restored still broken.

* fix(doctor): report unsubstituted placeholders in text files

The placeholder check only inspected Mach-O load commands for two tokens,
so a wrapper script that kept a relocation token read as healthy. That is
how a keg could install successfully, fail at launch, and still pass a
doctor run.

The scan now also covers text files and matches any Homebrew token rather
than the two malt substitutes: the patcher's verify gate must not fail an
install over a token it does not know, but doctor only warns, and an
unresolved token is exactly the finding worth surfacing.

The check keeps its existing id so scripted consumers are unaffected.

(cherry picked from commit 95b5190)
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.

1 participant