fix(install): resolve dependency-scoped bottle placeholders - #786
Merged
Conversation
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
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)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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
doctorrun that reported the prefixhealthy. 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.
doctornow also scans text files, and reports any Homebrew token ratherthan the two malt substitutes. That is the check that would have caught
this class in the first place.
Related Issue
Notes for Reviewers