🔨 Refactor Cask exceptions.
This commit is contained in:
parent
054ed10cb1
commit
66ce575301
@ -32,9 +32,9 @@ module Hbc
|
|||||||
end
|
end
|
||||||
|
|
||||||
def load
|
def load
|
||||||
raise CaskError, "'#{@path}' does not exist." unless @path.exist?
|
raise CaskUnavailableError.new(@token, "'#{@path}' does not exist.") unless @path.exist?
|
||||||
raise CaskError, "'#{@path}' is not readable." unless @path.readable?
|
raise CaskUnavailableError.new(@token, "'#{@path}' is not readable.") unless @path.readable?
|
||||||
raise CaskError, "'#{@path}' is not a file." unless @path.file?
|
raise CaskUnavailableError.new(@token, "'#{@path}' is not a file.") unless @path.file?
|
||||||
|
|
||||||
@content = IO.read(@path)
|
@content = IO.read(@path)
|
||||||
|
|
||||||
@ -45,7 +45,7 @@ module Hbc
|
|||||||
|
|
||||||
def cask(header_token, &block)
|
def cask(header_token, &block)
|
||||||
if @token != header_token
|
if @token != header_token
|
||||||
raise CaskTokenDoesNotMatchError.new(@token, header_token)
|
raise CaskTokenMismatchError.new(@token, header_token)
|
||||||
end
|
end
|
||||||
|
|
||||||
Cask.new(header_token, sourcefile_path: @path, &block)
|
Cask.new(header_token, sourcefile_path: @path, &block)
|
||||||
@ -57,10 +57,11 @@ module Hbc
|
|||||||
ref.to_s.match?(::URI.regexp)
|
ref.to_s.match?(::URI.regexp)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
attr_reader :url
|
||||||
|
|
||||||
def initialize(url)
|
def initialize(url)
|
||||||
@url = url
|
@url = URI(url)
|
||||||
uri = URI(url)
|
super Hbc.cache/File.basename(@url.path)
|
||||||
super Hbc.cache/File.basename(uri.path)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def load
|
def load
|
||||||
@ -71,7 +72,7 @@ module Hbc
|
|||||||
ohai "Downloading #{@url}."
|
ohai "Downloading #{@url}."
|
||||||
curl @url, "-o", @path
|
curl @url, "-o", @path
|
||||||
rescue ErrorDuringExecution
|
rescue ErrorDuringExecution
|
||||||
raise CaskUnavailableError, @url
|
raise CaskUnavailableError.new(@token, "Failed to download #{Formatter.url(@url)}.")
|
||||||
end
|
end
|
||||||
|
|
||||||
super
|
super
|
||||||
@ -108,7 +109,7 @@ module Hbc
|
|||||||
end
|
end
|
||||||
|
|
||||||
def load
|
def load
|
||||||
raise CaskUnavailableError, @token
|
raise CaskUnavailableError.new(@token, "No Cask with this name exists.")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -166,7 +166,7 @@ module Hbc
|
|||||||
Hbc.default_tap.install unless Hbc.default_tap.installed?
|
Hbc.default_tap.install unless Hbc.default_tap.installed?
|
||||||
Hbc.init if self.class.should_init?(command)
|
Hbc.init if self.class.should_init?(command)
|
||||||
self.class.run_command(command, *args)
|
self.class.run_command(command, *args)
|
||||||
rescue CaskError, CaskSha256MismatchError, ArgumentError, OptionParser::InvalidOption => e
|
rescue CaskError, ArgumentError, OptionParser::InvalidOption => e
|
||||||
msg = e.message
|
msg = e.message
|
||||||
msg << e.backtrace.join("\n").prepend("\n") if ARGV.debug?
|
msg << e.backtrace.join("\n").prepend("\n") if ARGV.debug?
|
||||||
onoe msg
|
onoe msg
|
||||||
|
@ -12,7 +12,7 @@ module Hbc
|
|||||||
cask_path = CaskLoader.path(cask_token)
|
cask_path = CaskLoader.path(cask_token)
|
||||||
|
|
||||||
unless cask_path.exist?
|
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
|
end
|
||||||
|
|
||||||
odebug "Opening editor for Cask #{cask_token}"
|
odebug "Opening editor for Cask #{cask_token}"
|
||||||
|
@ -31,14 +31,8 @@ module Hbc
|
|||||||
rescue CaskAlreadyInstalledError => e
|
rescue CaskAlreadyInstalledError => e
|
||||||
opoo e.message
|
opoo e.message
|
||||||
count += 1
|
count += 1
|
||||||
rescue CaskAlreadyInstalledAutoUpdatesError => e
|
|
||||||
opoo e.message
|
|
||||||
count += 1
|
|
||||||
rescue CaskUnavailableError => e
|
rescue CaskUnavailableError => e
|
||||||
self.class.warn_unavailable_with_suggestion cask_token, e
|
self.class.warn_unavailable_with_suggestion cask_token, e
|
||||||
rescue CaskNoShasumError => e
|
|
||||||
opoo e.message
|
|
||||||
count += 1
|
|
||||||
rescue CaskError => e
|
rescue CaskError => e
|
||||||
onoe e.message
|
onoe e.message
|
||||||
end
|
end
|
||||||
@ -51,9 +45,9 @@ module Hbc
|
|||||||
exact_match, partial_matches = Search.search(cask_token)
|
exact_match, partial_matches = Search.search(cask_token)
|
||||||
error_message = e.message
|
error_message = e.message
|
||||||
if exact_match
|
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?
|
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)))
|
.concat(Formatter.columns(partial_matches.take(20)))
|
||||||
end
|
end
|
||||||
onoe error_message
|
onoe error_message
|
||||||
|
@ -17,9 +17,8 @@ module Hbc
|
|||||||
count += 1
|
count += 1
|
||||||
rescue CaskUnavailableError => e
|
rescue CaskUnavailableError => e
|
||||||
self.class.warn_unavailable_with_suggestion cask_token, e
|
self.class.warn_unavailable_with_suggestion cask_token, e
|
||||||
rescue CaskNoShasumError => e
|
rescue CaskError => e
|
||||||
opoo e.message
|
onoe e.message
|
||||||
count += 1
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -3,59 +3,43 @@ module Hbc
|
|||||||
|
|
||||||
class AbstractCaskErrorWithToken < CaskError
|
class AbstractCaskErrorWithToken < CaskError
|
||||||
attr_reader :token
|
attr_reader :token
|
||||||
|
attr_reader :reason
|
||||||
|
|
||||||
def initialize(token)
|
def initialize(token, reason = nil)
|
||||||
@token = token
|
@token = token
|
||||||
|
@reason = reason.to_s
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
class CaskNotInstalledError < AbstractCaskErrorWithToken
|
class CaskNotInstalledError < AbstractCaskErrorWithToken
|
||||||
def to_s
|
def to_s
|
||||||
"#{token} is not installed"
|
"Cask '#{token}' is not installed."
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
class CaskUnavailableError < AbstractCaskErrorWithToken
|
class CaskUnavailableError < AbstractCaskErrorWithToken
|
||||||
def to_s
|
def to_s
|
||||||
"No available Cask for #{token}"
|
"Cask '#{token}' is unavailable" << (reason.empty? ? "." : ": #{reason}")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
class CaskAlreadyCreatedError < AbstractCaskErrorWithToken
|
class CaskAlreadyCreatedError < AbstractCaskErrorWithToken
|
||||||
def to_s
|
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
|
||||||
end
|
end
|
||||||
|
|
||||||
class CaskAlreadyInstalledError < AbstractCaskErrorWithToken
|
class CaskAlreadyInstalledError < AbstractCaskErrorWithToken
|
||||||
def to_s
|
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
|
<<-EOS.undent
|
||||||
|
Cask '#{token}' is already installed.
|
||||||
|
|
||||||
To re-install #{token}, run:
|
To re-install #{token}, run:
|
||||||
brew cask reinstall #{token}
|
#{Formatter.identifier("brew cask reinstall #{token}")}
|
||||||
EOS
|
EOS
|
||||||
end
|
end
|
||||||
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
|
class CaskCommandFailedError < CaskError
|
||||||
def initialize(cmd, stdout, stderr, status)
|
def initialize(cmd, stdout, stderr, status)
|
||||||
@cmd = cmd
|
@cmd = cmd
|
||||||
@ -84,8 +68,8 @@ module Hbc
|
|||||||
class CaskX11DependencyError < AbstractCaskErrorWithToken
|
class CaskX11DependencyError < AbstractCaskErrorWithToken
|
||||||
def to_s
|
def to_s
|
||||||
<<-EOS.undent
|
<<-EOS.undent
|
||||||
#{token} requires XQuartz/X11, which can be installed using Homebrew-Cask by running
|
Cask '#{token}' requires XQuartz/X11, which can be installed using Homebrew-Cask by running
|
||||||
brew cask install xquartz
|
#{Formatter.identifier("brew cask install xquartz")}
|
||||||
|
|
||||||
or manually, by downloading the package from
|
or manually, by downloading the package from
|
||||||
#{Formatter.url("https://www.xquartz.org/")}
|
#{Formatter.url("https://www.xquartz.org/")}
|
||||||
@ -101,60 +85,67 @@ module Hbc
|
|||||||
|
|
||||||
class CaskUnspecifiedError < CaskError
|
class CaskUnspecifiedError < CaskError
|
||||||
def to_s
|
def to_s
|
||||||
"This command requires a Cask token"
|
"This command requires a Cask token."
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
class CaskInvalidError < AbstractCaskErrorWithToken
|
class CaskInvalidError < AbstractCaskErrorWithToken
|
||||||
attr_reader :submsg
|
|
||||||
def initialize(token, *submsg)
|
|
||||||
super(token)
|
|
||||||
@submsg = submsg.join(" ")
|
|
||||||
end
|
|
||||||
|
|
||||||
def to_s
|
def to_s
|
||||||
"Cask '#{token}' definition is invalid#{": #{submsg}" unless submsg.empty?}"
|
"Cask '#{token}' definition is invalid" << (reason.empty? ? ".": ": #{reason}")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
class CaskTokenDoesNotMatchError < CaskInvalidError
|
class CaskTokenMismatchError < CaskInvalidError
|
||||||
def initialize(token, header_token)
|
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
|
||||||
end
|
end
|
||||||
|
|
||||||
class CaskSha256MissingError < ArgumentError
|
class CaskSha256Error < AbstractCaskErrorWithToken
|
||||||
end
|
attr_reader :expected, :actual
|
||||||
|
|
||||||
class CaskSha256MismatchError < RuntimeError
|
def initialize(token, expected = nil, actual = nil)
|
||||||
attr_reader :path, :expected, :actual
|
super(token)
|
||||||
def initialize(path, expected, actual)
|
|
||||||
@path = path
|
|
||||||
@expected = expected
|
@expected = expected
|
||||||
@actual = actual
|
@actual = actual
|
||||||
end
|
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
|
def to_s
|
||||||
<<-EOS.undent
|
<<-EOS.undent
|
||||||
sha256 mismatch
|
Checksum for Cask '#{token}' does not match.
|
||||||
Expected: #{expected}
|
|
||||||
Actual: #{actual}
|
Expected: #{Formatter.success(expected.to_s)}
|
||||||
|
Actual: #{Formatter.error(actual.to_s)}
|
||||||
File: #{path}
|
File: #{path}
|
||||||
|
|
||||||
To retry an incomplete download, remove the file above.
|
To retry an incomplete download, remove the file above.
|
||||||
EOS
|
EOS
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
class CaskNoShasumError < CaskError
|
class CaskNoShasumError < CaskSha256Error
|
||||||
attr_reader :token
|
|
||||||
def initialize(token)
|
|
||||||
@token = token
|
|
||||||
end
|
|
||||||
|
|
||||||
def to_s
|
def to_s
|
||||||
<<-EOS.undent
|
<<-EOS.undent
|
||||||
Cask '#{token}' does not have a sha256 checksum defined and was not installed.
|
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
|
EOS
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -94,7 +94,6 @@ module Hbc
|
|||||||
odebug "Hbc::Installer#install"
|
odebug "Hbc::Installer#install"
|
||||||
|
|
||||||
if @cask.installed? && !force? && !@reinstall
|
if @cask.installed? && !force? && !@reinstall
|
||||||
raise CaskAlreadyInstalledAutoUpdatesError, @cask if @cask.auto_updates
|
|
||||||
raise CaskAlreadyInstalledError, @cask
|
raise CaskAlreadyInstalledError, @cask
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -143,7 +142,7 @@ module Hbc
|
|||||||
def verify_has_sha
|
def verify_has_sha
|
||||||
odebug "Checking cask has checksum"
|
odebug "Checking cask has checksum"
|
||||||
return unless @cask.sha256 == :no_check
|
return unless @cask.sha256 == :no_check
|
||||||
raise CaskNoShasumError, @cask
|
raise CaskNoShasumError, @cask.token
|
||||||
end
|
end
|
||||||
|
|
||||||
def verify
|
def verify
|
||||||
|
@ -33,13 +33,13 @@ module Hbc
|
|||||||
end
|
end
|
||||||
|
|
||||||
def verify_checksum
|
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
|
if expected == computed
|
||||||
odebug "SHA256 checksums match"
|
odebug "SHA256 checksums match"
|
||||||
else
|
else
|
||||||
ohai 'Note: running "brew update" may fix sha256 checksum errors'
|
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
|
end
|
||||||
end
|
end
|
||||||
|
@ -41,7 +41,7 @@ describe Hbc::CLI::Install, :cask do
|
|||||||
|
|
||||||
expect {
|
expect {
|
||||||
Hbc::CLI::Install.run("local-transmission")
|
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
|
end
|
||||||
|
|
||||||
it "allows double install with --force" do
|
it "allows double install with --force" do
|
||||||
@ -80,7 +80,7 @@ describe Hbc::CLI::Install, :cask do
|
|||||||
rescue Hbc::CaskError
|
rescue Hbc::CaskError
|
||||||
nil
|
nil
|
||||||
end
|
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
|
end
|
||||||
|
|
||||||
it "returns multiple suggestions for a Cask fragment" do
|
it "returns multiple suggestions for a Cask fragment" do
|
||||||
@ -90,7 +90,7 @@ describe Hbc::CLI::Install, :cask do
|
|||||||
rescue Hbc::CaskError
|
rescue Hbc::CaskError
|
||||||
nil
|
nil
|
||||||
end
|
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
|
end
|
||||||
|
|
||||||
describe "when no Cask is specified" do
|
describe "when no Cask is specified" do
|
||||||
|
@ -57,7 +57,7 @@ describe Hbc::DSL, :cask do
|
|||||||
it "raises an error" do
|
it "raises an error" do
|
||||||
expect {
|
expect {
|
||||||
cask
|
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
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -145,22 +145,6 @@ describe Hbc::Installer, :cask do
|
|||||||
expect(with_macosx_dir.staged_path.join("__MACOSX")).not_to be_a_directory
|
expect(with_macosx_dir.staged_path.join("__MACOSX")).not_to be_a_directory
|
||||||
end
|
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
|
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")
|
with_auto_updates = Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/auto-updates.rb")
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
describe Hbc::Verify::Checksum, :cask do
|
describe Hbc::Verify::Checksum, :cask do
|
||||||
let(:cask) { double("cask") }
|
let(:cask) { double("cask", token: "cask") }
|
||||||
let(:downloaded_path) { double("downloaded_path") }
|
let(:downloaded_path) { double("downloaded_path") }
|
||||||
let(:verification) { described_class.new(cask, downloaded_path) }
|
let(:verification) { described_class.new(cask, downloaded_path) }
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user