Repository navigation
bundle: preserve formula conflict handling - #24356
Conversation
- Keep formulae with declared conflicts out of batched installs so the existing installer can unlink conflicting formulae first. - Cover existing conflicts and conflicts introduced by a batch.
|
No actionable comments were generated in the recent review.
|
| Layer / File(s) | Summary |
|---|---|
Collect requested formula names Library/Homebrew/bundle/brew.rb, Library/Homebrew/bundle/cask.rb, Library/Homebrew/bundle/installer.rb, Library/Homebrew/test/bundle/cask_spec.rb |
Formula-name collection includes requested formulae and recursive dependencies, including formula dependencies of requested Casks. Cask specs cover nested Casks, dependency types, installed definitions, and unavailable Casks. |
Exclude conflicting formulas from batching Library/Homebrew/bundle/installer.rb, Library/Homebrew/test/bundle/installer_spec.rb |
The installer checks whether formula conflicts are installed or included in the requested formula names before it batches Brew entries. Specs cover conflict handling for direct, transitive optional, and Cask dependencies, and verify dependency expansion occurs once. |
Merge Risk: 
Minimal · up to bbe90
-
This change keeps conflicting formulae out of the install batch so that bundle can unlink the conflict first. No unresolved behavioral risk was found in the reviewed change.
Pre-merge checks: 
4
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.
MikeMcQuaid
left a comment
There was a problem hiding this comment.
Thanks, good idea, one question.
- Keep batch installation when conflicts are absent. - Check requested formula and cask dependency trees for conflicts. - Include optional dependencies to cover saved install options.
- Reuse `Cask.formula_dependencies` for batch conflict checks. - Share formula expansion and reuse loaded cask dependencies. - Preserve cleanup's installed-cask behaviour.
MikeMcQuaid
left a comment
There was a problem hiding this comment.
Thanks, getting there! Would be nice to slim the diff as much as possible here 🙇🏻
- Remove the blanket `args` check for unrelated entries. - Keep tests focused on batching and conflict resolution. - Exercise installed-state refresh through the test Cellar.
brew bundle installcan fail to restore packages from a Brewfile generated bybrew bundle dump. Batch installation skips unlinking conflicting formulae, so installation fails with a conflict error. This patch keeps a formula out of the batch when a conflicting formula is already installed, requested in the Brewfile or included in a requested package's dependency tree. Bundle then uses its existing individual installer to unlink the conflicting formula before installation.Conflict checks reuse Homebrew's formula and cask dependency traversal. Optional dependencies are included even when disabled, so some formulae may use individual installation unnecessarily. The expanded dependency list is reused across conflict checks.
Example 1: Install
moreutilswhen GNUparallelis linked./bin/brew bundle dumpproduced the following Brewfile withmoreutilslinked and GNUparallelinstalled but unlinked:The
moreutilspackage and GNUparallelpackage provide different executables namedparallel. The Brewfile requests that GNUparallelremain installed but unlinked (link: false), withbin/parallelpointing to the executable frommoreutils.The batch installer added in Homebrew/brew#23659 skips
Brew#resolve_conflicts!. With GNUparallelalready linked andmoreutilsabsent, Bundle tries to installmoreutilsbefore unlinking GNUparallel. The installation fails. Bundle then unlinks GNUparallel, leavingmoreutilsuninstalled andbin/parallelabsent.With the fix, Bundle runs the commands in the required order:
Reproduce with the same Brewfile entries in a disposable Homebrew installation, starting with
moreutilsand GNUparalleluninstalled:The recorded tests used the unedited dumped Brewfile. The initial state was restored before each run:
moreutilsparallelbin/parallelpoints toparallelexecutablemoreutilsexecutableBefore (exit 1):
After (exit 0):
Example 2: Install
ctagsandb2sumin one batchBatch installation is preserved when no conflicting formula is installed or present in the Brewfile's declared dependency tree. For example:
ctagsdeclares a conflict withuniversal-ctags, andb2sumdeclares a conflict withcoreutils. With all four formulae initially absent,./bin/brew bundle install --no-upgrade --file=./Brewfileinstalledctagsandb2sumin one call:Validation
./bin/brew lgtm --onlinepassed. The installer and cask specs passed with 90 examples. Tests cover installed conflicts, conflicts requested through aliases or formula and cask dependencies, including transitive optional dependencies. Tests also check that an unrelated entry's install arguments preserve batching, cask dependencies reuse loaded formulae and non-recursive cask queries retain their existing behaviour.For the
moreutilsreproduction,./bin/brew bundle check --no-upgrade --file="$brewfile_dir/Brewfile"and a second install passed. For thectagsandb2sumexample,./bin/brew bundle check --no-upgrade --file=./Brewfilepassed.brew benchmarkresults.brewcommands to reproduce the bug?brew lgtm(style, typechecking and tests) locally?Codex (GPT-6) helped investigate the bug, write the patch and regression tests, run the reproductions and benchmark and draft this description.