diff --git a/Library/Homebrew/cask/lib/hbc/cask_loader.rb b/Library/Homebrew/cask/lib/hbc/cask_loader.rb index a0c44d9b41..43fd9080da 100644 --- a/Library/Homebrew/cask/lib/hbc/cask_loader.rb +++ b/Library/Homebrew/cask/lib/hbc/cask_loader.rb @@ -32,9 +32,9 @@ module Hbc end def load - raise CaskError, "'#{@path}' does not exist." unless @path.exist? - raise CaskError, "'#{@path}' is not readable." unless @path.readable? - raise CaskError, "'#{@path}' is not a file." unless @path.file? + raise CaskUnavailableError.new(@token, "'#{@path}' does not exist.") unless @path.exist? + raise CaskUnavailableError.new(@token, "'#{@path}' is not readable.") unless @path.readable? + raise CaskUnavailableError.new(@token, "'#{@path}' is not a file.") unless @path.file? @content = IO.read(@path) @@ -45,7 +45,7 @@ module Hbc def cask(header_token, &block) if @token != header_token - raise CaskTokenDoesNotMatchError.new(@token, header_token) + raise CaskTokenMismatchError.new(@token, header_token) end Cask.new(header_token, sourcefile_path: @path, &block) @@ -57,10 +57,11 @@ module Hbc ref.to_s.match?(::URI.regexp) end + attr_reader :url + def initialize(url) - @url = url - uri = URI(url) - super Hbc.cache/File.basename(uri.path) + @url = URI(url) + super Hbc.cache/File.basename(@url.path) end def load @@ -71,7 +72,7 @@ module Hbc ohai "Downloading #{@url}." curl @url, "-o", @path rescue ErrorDuringExecution - raise CaskUnavailableError, @url + raise CaskUnavailableError.new(@token, "Failed to download #{Formatter.url(@url)}.") end super @@ -108,7 +109,7 @@ module Hbc end def load - raise CaskUnavailableError, @token + raise CaskUnavailableError.new(@token, "No Cask with this name exists.") end end diff --git a/Library/Homebrew/cask/lib/hbc/cli.rb b/Library/Homebrew/cask/lib/hbc/cli.rb index eec2788ec9..04a4149046 100644 --- a/Library/Homebrew/cask/lib/hbc/cli.rb +++ b/Library/Homebrew/cask/lib/hbc/cli.rb @@ -166,7 +166,7 @@ module Hbc Hbc.default_tap.install unless Hbc.default_tap.installed? Hbc.init if self.class.should_init?(command) self.class.run_command(command, *args) - rescue CaskError, CaskSha256MismatchError, ArgumentError, OptionParser::InvalidOption => e + rescue CaskError, ArgumentError, OptionParser::InvalidOption => e msg = e.message msg << e.backtrace.join("\n").prepend("\n") if ARGV.debug? onoe msg diff --git a/Library/Homebrew/cask/lib/hbc/cli/edit.rb b/Library/Homebrew/cask/lib/hbc/cli/edit.rb index dec0fe36ba..77238d209e 100644 --- a/Library/Homebrew/cask/lib/hbc/cli/edit.rb +++ b/Library/Homebrew/cask/lib/hbc/cli/edit.rb @@ -12,7 +12,7 @@ module Hbc cask_path = CaskLoader.path(cask_token) unless cask_path.exist? - raise CaskUnavailableError, %Q(#{cask_token}, run "brew cask create #{cask_token}" to create a new Cask) + raise CaskUnavailableError.new(cask_token, "Run #{Formatter.identifier("brew cask create #{cask_token}")} to create a new Cask.") end odebug "Opening editor for Cask #{cask_token}" diff --git a/Library/Homebrew/cask/lib/hbc/cli/install.rb b/Library/Homebrew/cask/lib/hbc/cli/install.rb index 4d0abc6775..4ac98d1deb 100644 --- a/Library/Homebrew/cask/lib/hbc/cli/install.rb +++ b/Library/Homebrew/cask/lib/hbc/cli/install.rb @@ -31,14 +31,8 @@ module Hbc rescue CaskAlreadyInstalledError => e opoo e.message count += 1 - rescue CaskAlreadyInstalledAutoUpdatesError => e - opoo e.message - count += 1 rescue CaskUnavailableError => e self.class.warn_unavailable_with_suggestion cask_token, e - rescue CaskNoShasumError => e - opoo e.message - count += 1 rescue CaskError => e onoe e.message end @@ -51,9 +45,9 @@ module Hbc exact_match, partial_matches = Search.search(cask_token) error_message = e.message if exact_match - error_message.concat(". Did you mean:\n#{exact_match}") + error_message.concat(" Did you mean:\n#{exact_match}") elsif !partial_matches.empty? - error_message.concat(". Did you mean one of:\n") + error_message.concat(" Did you mean one of:\n") .concat(Formatter.columns(partial_matches.take(20))) end onoe error_message diff --git a/Library/Homebrew/cask/lib/hbc/cli/reinstall.rb b/Library/Homebrew/cask/lib/hbc/cli/reinstall.rb index eb5f45c905..d90317892e 100644 --- a/Library/Homebrew/cask/lib/hbc/cli/reinstall.rb +++ b/Library/Homebrew/cask/lib/hbc/cli/reinstall.rb @@ -17,9 +17,8 @@ module Hbc count += 1 rescue CaskUnavailableError => e self.class.warn_unavailable_with_suggestion cask_token, e - rescue CaskNoShasumError => e - opoo e.message - count += 1 + rescue CaskError => e + onoe e.message end end diff --git a/Library/Homebrew/cask/lib/hbc/exceptions.rb b/Library/Homebrew/cask/lib/hbc/exceptions.rb index b9d305a9ba..d9e1b07dbf 100644 --- a/Library/Homebrew/cask/lib/hbc/exceptions.rb +++ b/Library/Homebrew/cask/lib/hbc/exceptions.rb @@ -3,59 +3,43 @@ module Hbc class AbstractCaskErrorWithToken < CaskError attr_reader :token + attr_reader :reason - def initialize(token) + def initialize(token, reason = nil) @token = token + @reason = reason.to_s end end class CaskNotInstalledError < AbstractCaskErrorWithToken def to_s - "#{token} is not installed" + "Cask '#{token}' is not installed." end end class CaskUnavailableError < AbstractCaskErrorWithToken def to_s - "No available Cask for #{token}" + "Cask '#{token}' is unavailable" << (reason.empty? ? "." : ": #{reason}") end end class CaskAlreadyCreatedError < AbstractCaskErrorWithToken def to_s - %Q(A Cask for #{token} already exists. Run "brew cask cat #{token}" to see it.) + %Q(Cask '#{token}' already exists. Run #{Formatter.identifier("brew cask cat #{token}")} to edit it.) end end class CaskAlreadyInstalledError < AbstractCaskErrorWithToken def to_s - s = <<-EOS.undent - A Cask for #{token} is already installed. - EOS - - s.concat("\n").concat(reinstall_message) - end - - private - - def reinstall_message <<-EOS.undent + Cask '#{token}' is already installed. + To re-install #{token}, run: - brew cask reinstall #{token} + #{Formatter.identifier("brew cask reinstall #{token}")} EOS end end - class CaskAlreadyInstalledAutoUpdatesError < CaskAlreadyInstalledError - def to_s - s = <<-EOS.undent - A Cask for #{token} is already installed and using auto-updates. - EOS - - s.concat("\n").concat(reinstall_message) - end - end - class CaskCommandFailedError < CaskError def initialize(cmd, stdout, stderr, status) @cmd = cmd @@ -84,8 +68,8 @@ module Hbc class CaskX11DependencyError < AbstractCaskErrorWithToken def to_s <<-EOS.undent - #{token} requires XQuartz/X11, which can be installed using Homebrew-Cask by running - brew cask install xquartz + Cask '#{token}' requires XQuartz/X11, which can be installed using Homebrew-Cask by running + #{Formatter.identifier("brew cask install xquartz")} or manually, by downloading the package from #{Formatter.url("https://www.xquartz.org/")} @@ -101,60 +85,67 @@ module Hbc class CaskUnspecifiedError < CaskError def to_s - "This command requires a Cask token" + "This command requires a Cask token." end end class CaskInvalidError < AbstractCaskErrorWithToken - attr_reader :submsg - def initialize(token, *submsg) - super(token) - @submsg = submsg.join(" ") - end - def to_s - "Cask '#{token}' definition is invalid#{": #{submsg}" unless submsg.empty?}" + "Cask '#{token}' definition is invalid" << (reason.empty? ? ".": ": #{reason}") end end - class CaskTokenDoesNotMatchError < CaskInvalidError + class CaskTokenMismatchError < CaskInvalidError def initialize(token, header_token) - super(token, "Bad header line: '#{header_token}' does not match file name") + super(token, "Token '#{header_token}' in header line does not match the file name.") end end - class CaskSha256MissingError < ArgumentError - end + class CaskSha256Error < AbstractCaskErrorWithToken + attr_reader :expected, :actual - class CaskSha256MismatchError < RuntimeError - attr_reader :path, :expected, :actual - def initialize(path, expected, actual) - @path = path + def initialize(token, expected = nil, actual = nil) + super(token) @expected = expected @actual = actual end + end + + class CaskSha256MissingError < CaskSha256Error + def to_s + <<-EOS.undent + Cask '#{token}' requires a checksum: + #{Formatter.identifier("sha256 '#{actual}'")} + EOS + end + end + + class CaskSha256MismatchError < CaskSha256Error + attr_reader :path + + def initialize(token, expected, actual, path) + super(token, expected, actual) + @path = path + end def to_s <<-EOS.undent - sha256 mismatch - Expected: #{expected} - Actual: #{actual} - File: #{path} + Checksum for Cask '#{token}' does not match. + + Expected: #{Formatter.success(expected.to_s)} + Actual: #{Formatter.error(actual.to_s)} + File: #{path} + To retry an incomplete download, remove the file above. EOS end end - class CaskNoShasumError < CaskError - attr_reader :token - def initialize(token) - @token = token - end - + class CaskNoShasumError < CaskSha256Error def to_s <<-EOS.undent Cask '#{token}' does not have a sha256 checksum defined and was not installed. - This means you have the "--require-sha" option set, perhaps in your HOMEBREW_CASK_OPTS. + This means you have the #{Formatter.identifier("--require-sha")} option set, perhaps in your HOMEBREW_CASK_OPTS. EOS end end diff --git a/Library/Homebrew/cask/lib/hbc/installer.rb b/Library/Homebrew/cask/lib/hbc/installer.rb index 7da9731e51..aa6d600f7f 100644 --- a/Library/Homebrew/cask/lib/hbc/installer.rb +++ b/Library/Homebrew/cask/lib/hbc/installer.rb @@ -94,7 +94,6 @@ module Hbc odebug "Hbc::Installer#install" if @cask.installed? && !force? && !@reinstall - raise CaskAlreadyInstalledAutoUpdatesError, @cask if @cask.auto_updates raise CaskAlreadyInstalledError, @cask end @@ -143,7 +142,7 @@ module Hbc def verify_has_sha odebug "Checking cask has checksum" return unless @cask.sha256 == :no_check - raise CaskNoShasumError, @cask + raise CaskNoShasumError, @cask.token end def verify diff --git a/Library/Homebrew/cask/lib/hbc/verify/checksum.rb b/Library/Homebrew/cask/lib/hbc/verify/checksum.rb index d079a44464..620703d313 100644 --- a/Library/Homebrew/cask/lib/hbc/verify/checksum.rb +++ b/Library/Homebrew/cask/lib/hbc/verify/checksum.rb @@ -33,13 +33,13 @@ module Hbc end def verify_checksum - raise CaskSha256MissingError, "sha256 required: sha256 '#{computed}'" if expected.nil? || expected.empty? + raise CaskSha256MissingError.new(cask.token, expected, computed) if expected.nil? || expected.empty? if expected == computed odebug "SHA256 checksums match" else ohai 'Note: running "brew update" may fix sha256 checksum errors' - raise CaskSha256MismatchError.new(downloaded_path, expected, computed) + raise CaskSha256MismatchError.new(cask.token, expected, computed, downloaded_path) end end end diff --git a/Library/Homebrew/test/cask/cli/install_spec.rb b/Library/Homebrew/test/cask/cli/install_spec.rb index b1b26c8675..0720d0d775 100644 --- a/Library/Homebrew/test/cask/cli/install_spec.rb +++ b/Library/Homebrew/test/cask/cli/install_spec.rb @@ -41,7 +41,7 @@ describe Hbc::CLI::Install, :cask do expect { Hbc::CLI::Install.run("local-transmission") - }.to output(/Warning: A Cask for local-transmission is already installed./).to_stderr + }.to output(/Warning: Cask 'local-transmission' is already installed./).to_stderr end it "allows double install with --force" do @@ -80,7 +80,7 @@ describe Hbc::CLI::Install, :cask do rescue Hbc::CaskError nil end - }.to output(/No available Cask for localcaffeine\. Did you mean:\nlocal-caffeine/).to_stderr + }.to output(/Cask 'localcaffeine' is unavailable\. Did you mean:\nlocal-caffeine/).to_stderr end it "returns multiple suggestions for a Cask fragment" do @@ -90,7 +90,7 @@ describe Hbc::CLI::Install, :cask do rescue Hbc::CaskError nil end - }.to output(/No available Cask for local-caf\. Did you mean one of:\nlocal-caffeine/).to_stderr + }.to output(/Cask 'local-caf' is unavailable\. Did you mean one of:\nlocal-caffeine/).to_stderr end describe "when no Cask is specified" do diff --git a/Library/Homebrew/test/cask/dsl_spec.rb b/Library/Homebrew/test/cask/dsl_spec.rb index 7eeabcf494..5849f581b0 100644 --- a/Library/Homebrew/test/cask/dsl_spec.rb +++ b/Library/Homebrew/test/cask/dsl_spec.rb @@ -57,7 +57,7 @@ describe Hbc::DSL, :cask do it "raises an error" do expect { cask - }.to raise_error(Hbc::CaskTokenDoesNotMatchError, /Bad header line:.*does not match file name/) + }.to raise_error(Hbc::CaskTokenMismatchError, /header line does not match the file name/) end end diff --git a/Library/Homebrew/test/cask/installer_spec.rb b/Library/Homebrew/test/cask/installer_spec.rb index a32f71cabe..8ef82c1d59 100644 --- a/Library/Homebrew/test/cask/installer_spec.rb +++ b/Library/Homebrew/test/cask/installer_spec.rb @@ -145,22 +145,6 @@ describe Hbc::Installer, :cask do expect(with_macosx_dir.staged_path.join("__MACOSX")).not_to be_a_directory end - it "installer method raises an exception when already-installed Casks which auto-update are attempted" do - with_auto_updates = Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/auto-updates.rb") - - expect(with_auto_updates).not_to be_installed - - installer = Hbc::Installer.new(with_auto_updates) - - shutup do - installer.install - end - - expect { - installer.install - }.to raise_error(Hbc::CaskAlreadyInstalledAutoUpdatesError) - end - it "allows already-installed Casks which auto-update to be installed if force is provided" do with_auto_updates = Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/auto-updates.rb") diff --git a/Library/Homebrew/test/cask/verify/checksum_spec.rb b/Library/Homebrew/test/cask/verify/checksum_spec.rb index 55c0e5f440..4b8543d2b4 100644 --- a/Library/Homebrew/test/cask/verify/checksum_spec.rb +++ b/Library/Homebrew/test/cask/verify/checksum_spec.rb @@ -1,5 +1,5 @@ describe Hbc::Verify::Checksum, :cask do - let(:cask) { double("cask") } + let(:cask) { double("cask", token: "cask") } let(:downloaded_path) { double("downloaded_path") } let(:verification) { described_class.new(cask, downloaded_path) }