Skip to content

fix(brew): define Homebrew's Language::* mixins in both shims - #13328

Draft
waynehoover wants to merge 3 commits into
jdx:mainfrom
waynehoover:fix/brew-shim-language-mixins
Draft

waynehoover wants to merge 3 commits into
jdx:mainfrom
waynehoover:fix/brew-shim-language-mixins

Conversation

@waynehoover

@waynehoover waynehoover commented Sep 17, 2026

Copy link
Copy Markdown
Contributor

The problem

A formula pulls one of Homebrew's Language::* mixins into its class body. qmk, for example:

class Qmk < Formula
  include Language::Python::Virtualenv

That is a constant reference, not a method call, so neither shim's method_missing DSL fallback covers it. The NameError aborts evaluation while the class body is still being read, on line 2:

Formula/qmk.rb:2:in '<class:Qmk>': uninitialized constant Qmk::Language (NameError)

Two consequences. Metadata extraction never reaches the url, version or depends_on declarations sitting below the include, so the formula cannot be resolved at all. And the source-build shim cannot get far enough to report what it does not support, so the user gets a bare NameError pointing at an include line instead of an explanation.

The fix

Define the namespace brew actually ships (Library/Homebrew/language/*.rb: Java, Node, Perl, PHP and Python, plus their Shebang and Virtualenv submodules) as empty modules in both shims.

Empty is the correct shape rather than a shortcut: these mixins contribute only install-time helpers. Nothing the metadata shim extracts depends on them, and in the build shim an actual call still fails loudly and specifically through the existing Formula#method_missing path:

Error: formula uses `virtualenv_install_with_resources (install-time helper)`, which mise's source-build shim does not support

That message is the one this shim is designed to produce for an unimplemented helper, and it replaces a NameError that named neither the feature nor the reason.

This follows the split already documented in shim.rb: unknown class-level DSL warns and continues, unknown install-time helpers fail loudly. A missing constant fell through both, which is the gap being closed.

Verification

Ran the metadata shim against all 253 tap formulae installed on this machine, before and after:

count
unchanged 251
newly extracting 2 (qmk 1.1.8, apfel-mcp 0.2.0)
newly broken 0

qmk now yields its version and all 17 dependencies. The build-shim half was verified separately by loading shim.rb's definitions, defining a formula shaped like qmk, and confirming the include evaluates and the helper call raises ShimUnsupportedError rather than NameError.

Scope

Same family as #13053 and #13163. This closes the Language::* constants only.

The other constant gap visible in that sweep is download strategies, which fails the same way and is not addressed here:

  • uninitialized constant CurlDownloadStrategy (acli, ecctl)
  • cannot load such file -- download_strategy from a tap's own require (kodehealth tap)

Happy to follow up with that one if the approach here looks right. It needs slightly more thought than empty modules, since using: already has real handling for resources.

Independent of #13327, which fixes version inference and touches a different part of the same file.

Summary by CodeRabbit

  • Bug Fixes

    • Improved compatibility when processing Homebrew formulas that reference language-specific mixins.
    • Formula metadata can now be evaluated without failing prematurely on these references; unsupported installation features continue to report clear errors.
    • Build processing now handles common Java, Node, Perl, PHP, and Python mixin references more reliably.
  • Tests

    • Added coverage verifying language mixin handling and consistent behavior across formula-processing paths.

A formula pulls a Language mixin into its class body. qmk, for example:

    class Qmk < Formula
      include Language::Python::Virtualenv

That is a constant reference rather than a method call, so neither
shim's method_missing DSL fallback covers it. The NameError aborts
evaluation while the class body is still running:

    Formula/qmk.rb:2:in '<class:Qmk>': uninitialized constant
    Qmk::Language (NameError)

Metadata extraction therefore never reaches the url, version or
depends_on declarations below the include, and the source-build shim
cannot get far enough to report what it does not support.

Define the namespace brew actually ships (Java, Node, Perl, PHP and
Python, plus their Shebang and Virtualenv submodules) as empty modules
in both shims. The mixins only contribute install-time helpers, so
empty is the correct shape: metadata extraction now succeeds, and an
actual call to one of those helpers still fails loudly and specifically
through Formula#method_missing:

    Error: formula uses `virtualenv_install_with_resources (install-time
    helper)`, which mise's source-build shim does not support

Verified against the 253 tap formulae installed locally: qmk and
apfel-mcp newly extract, 251 unchanged, 0 regressions.
@coderabbitai

coderabbitai Bot commented Sep 17, 2026

Copy link
Copy Markdown
Contributor

Review Change StackReview Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Central YAML (inherited), Organization UI (inherited)

Review profile: CHILL

Plan: Advanced

Run ID: 651637e7-a65a-4694-ae71-60d91173096b

📥 Commits

Reviewing files that changed from the base of the PR and between 2fff1c3 and e6032ac.

📒 Files selected for processing (1)
  • src/system/packages/brew/tap.rs

Included review availability: Your plan provides up to 10 included reviews per hour; 5 remain after this review.


📝 Walkthrough

Walkthrough

The Brew build and metadata shims now define matching empty Language::* modules. Formula class bodies can resolve these constants without NameError. Tests verify shim parity and metadata extraction for formulas using the mixins.

Changes

Brew Language namespace shims

Layer / File(s) Summary
Language namespace resolution
src/system/packages/brew/shim.rb, src/system/packages/brew/tap_formula_metadata.rb
Both paths define empty Language modules for Java, Node shebang, Perl shebang, PHP shebang, Python shebang, and Python virtualenv references.
Language namespace validation
src/system/packages/brew/tap.rs
Tests verify that both shim definitions match and that formulas using all supported mixin constants still expose their version and Python dependency.

Priority: ⬇️ Low

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Bug fix

Suggested reviewers: jdx

Merge Risk: ⚪ Minimal · up to e6032

The change consistently resolves the supported Language namespace constants while preserving intentional failures for unsupported install-time helpers.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 6 functions across 3 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely identifies the main change: defining Homebrew's Language::* mixins in both brew shims.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
  • Fix all pre-merge checks with AI

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@greptile-apps

greptile-apps Bot commented Sep 17, 2026

Copy link
Copy Markdown
Contributor

RetriggerConfidence Score: 5/5

The PR appears safe to merge, with the prior synchronization-test issue fully corrected and no new actionable defects identified.

Summary

This PR defines Homebrew’s supported Language::* mixin namespaces in both Ruby shims so formula class bodies can be evaluated without premature NameError failures.

  • Adds matching empty language-mixin modules to the metadata and source-build shims.
  • Adds metadata extraction coverage for formulas including every supported mixin.
  • Corrects the cross-shim synchronization test to compare the complete nested Language blocks.

Reviews (3) · Last reviewed commit: "test(brew): make the Language drift chec..."

Comment thread src/system/packages/brew/tap_formula_metadata.rb
@waynehoover

Copy link
Copy Markdown
Contributor Author

For wider context on where this fits: I opened #13330, which traces the whole chain for qmk end to end.

Short version, so it is clear what this PR does and does not buy: this closes the first of four gaps. qmk metadata now extracts, but installing it still needs a trailing-number stem parser for its hid_bootloader_cli dependency, and an actual virtualenv_install_with_resources implementation in shim.rb. The discussion has the verified detail and two questions about scope that are worth settling before I send more PRs.

@jdx
jdx marked this pull request as draft September 17, 2026 20:56
Two gaps, matching the two ways this can regress.

resolves_language_mixin_constants runs the metadata shim over a formula
that includes every Language mixin from its class body, and asserts the
url, version and depends_on declared below those includes are read. A
NameError on the first include would hide all of them.

language_mixin_definitions_match_across_shims asserts the two shims
define the same namespace. They each carry their own copy, and a mixin
that resolves while extracting metadata but not during a source build
would fail late, after the download, rather than at evaluation.
Comment thread src/system/packages/brew/tap.rs Outdated
The helper scanned for the first unindented `end`, which does span the
whole block today because every nested `end` is indented. That is a
property of the current formatting rather than of the structure, so
reindenting the block would silently narrow the comparison instead of
failing.

Track nesting depth instead, and trim each line so reindentation alone
is not reported as a difference. Also assert the extracted block still
contains the Perl, PHP, Python and Virtualenv definitions: two spans
truncated identically would compare equal while covering nothing.
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