diff --git a/Library/Homebrew/cask/cask_loader.rb b/Library/Homebrew/cask/cask_loader.rb index d6dab183ca..fa7eed16ae 100644 --- a/Library/Homebrew/cask/cask_loader.rb +++ b/Library/Homebrew/cask/cask_loader.rb @@ -157,7 +157,7 @@ module Cask end def load(config:) - tap.install unless tap.installed? + raise TapCaskUnavailableError.new(tap, token) unless tap.installed? super end diff --git a/Library/Homebrew/cask/exceptions.rb b/Library/Homebrew/cask/exceptions.rb index 34cd2b62ab..8a2214e3c4 100644 --- a/Library/Homebrew/cask/exceptions.rb +++ b/Library/Homebrew/cask/exceptions.rb @@ -103,6 +103,27 @@ module Cask end end + # Error when a cask in a specific tap is not available. + # + # @api private + class TapCaskUnavailableError < CaskUnavailableError + extend T::Sig + + attr_reader :tap + + def initialize(tap, token) + super("#{tap}/#{token}") + @tap = tap + end + + sig { returns(String) } + def to_s + s = super + s += "\nPlease tap it and then try again: brew tap #{tap}" unless tap.installed? + s + end + end + # Error when a cask already exists. # # @api private diff --git a/Library/Homebrew/cli/named_args.rb b/Library/Homebrew/cli/named_args.rb index 128c376877..f8dd68b917 100644 --- a/Library/Homebrew/cli/named_args.rb +++ b/Library/Homebrew/cli/named_args.rb @@ -132,6 +132,12 @@ module Homebrew raise unreadable_error if unreadable_error.present? + user, repo, short_name = name.downcase.split("/", 3) + if repo.present? && short_name.present? + tap = Tap.fetch(user, repo) + raise TapFormulaOrCaskUnavailableError.new(tap, short_name) + end + raise FormulaOrCaskUnavailableError, name end private :load_formula_or_cask diff --git a/Library/Homebrew/exceptions.rb b/Library/Homebrew/exceptions.rb index 55b15062da..cadf8a5313 100644 --- a/Library/Homebrew/exceptions.rb +++ b/Library/Homebrew/exceptions.rb @@ -97,6 +97,25 @@ class FormulaOrCaskUnavailableError < RuntimeError end end +# Raised when a formula or cask in a specific tap is not available. +class TapFormulaOrCaskUnavailableError < FormulaOrCaskUnavailableError + extend T::Sig + + attr_reader :tap + + def initialize(tap, name) + super "#{tap}/#{name}" + @tap = tap + end + + sig { returns(String) } + def to_s + s = super + s += "\nPlease tap it and then try again: brew tap #{tap}" unless tap.installed? + s + end +end + # Raised when a formula is not available. class FormulaUnavailableError < FormulaOrCaskUnavailableError extend T::Sig diff --git a/Library/Homebrew/test/exceptions_spec.rb b/Library/Homebrew/test/exceptions_spec.rb index 5fd44a1271..dfa8e9b6bc 100644 --- a/Library/Homebrew/test/exceptions_spec.rb +++ b/Library/Homebrew/test/exceptions_spec.rb @@ -34,6 +34,14 @@ describe "Exception" do } end + describe TapFormulaOrCaskUnavailableError do + subject(:error) { described_class.new(tap, "foo") } + + let(:tap) { double(Tap, user: "u", repo: "r", to_s: "u/r", installed?: false) } + + its(:to_s) { is_expected.to match(%r{Please tap it and then try again: brew tap u/r}) } + end + describe FormulaUnavailableError do subject(:error) { described_class.new("foo") }