diff --git a/Library/Homebrew/cli/named_args.rb b/Library/Homebrew/cli/named_args.rb index cdbfc29276..7ab9fe1a0b 100644 --- a/Library/Homebrew/cli/named_args.rb +++ b/Library/Homebrew/cli/named_args.rb @@ -105,16 +105,30 @@ module Homebrew # Returns formulae and casks after validating that a tap is present for each of them. def to_formulae_and_casks_with_taps - to_formulae_and_casks.each do |formula_or_cask| - case formula_or_cask - when Formula - odie "Formula #{formula_or_cask.name} is not in a tap!" unless formula_or_cask.tap - when Cask::Cask - odie "Cask #{formula_or_cask.token} is not in a tap!" unless formula_or_cask.tap - else - raise ArgumentError, "Expected a formula or a cask: #{formula_or_cask}" + formulae_and_casks_with_taps, formulae_and_casks_without_taps = + to_formulae_and_casks.partition do |formula_or_cask| + case formula_or_cask + when Formula, Cask::Cask + formula_or_cask.tap&.installed? + else + # TODO: Refactor methods so that Sorbet can tell that this is unreachable. + raise ArgumentError, "Not a formula or cask: #{formula_or_cask.class}" + end end - end + + return formulae_and_casks_with_taps if formulae_and_casks_without_taps.blank? + + types = [] + types << "formulae" if formulae_and_casks_without_taps.any?(Formula) + types << "casks" if formulae_and_casks_without_taps.any?(Cask::Cask) + + odie <<~ERROR + These #{types.join(" and ")} are not in any locally installed taps! + + - #{formulae_and_casks_without_taps.sort_by(&:to_s).join("\n- ")} + + You may need to run `brew tap` to install additional taps. + ERROR end def to_formulae_and_casks_and_unavailable(only: parent&.only_formula_or_cask, method: nil)