brew/Library/Homebrew/cask/exceptions.rb
2020-11-13 12:26:36 +01:00

349 lines
7.6 KiB
Ruby

# typed: true
# frozen_string_literal: true
module Cask
# General cask error.
#
# @api private
class CaskError < RuntimeError; end
# Cask error containing multiple other errors.
#
# @api private
class MultipleCaskErrors < CaskError
extend T::Sig
def initialize(errors)
super()
@errors = errors
end
sig { returns(String) }
def to_s
<<~EOS
Problems with multiple casks:
#{@errors.map(&:to_s).join("\n")}
EOS
end
end
# Abstract cask error containing a cask token.
#
# @api private
class AbstractCaskErrorWithToken < CaskError
extend T::Sig
sig { returns(String) }
attr_reader :token
sig { returns(String) }
attr_reader :reason
def initialize(token, reason = nil)
super()
@token = token.to_s
@reason = reason.to_s
end
end
# Error when a cask is not installed.
#
# @api private
class CaskNotInstalledError < AbstractCaskErrorWithToken
extend T::Sig
sig { returns(String) }
def to_s
"Cask '#{token}' is not installed."
end
end
# Error when a cask conflicts with another cask.
#
# @api private
class CaskConflictError < AbstractCaskErrorWithToken
extend T::Sig
attr_reader :conflicting_cask
def initialize(token, conflicting_cask)
super(token)
@conflicting_cask = conflicting_cask
end
sig { returns(String) }
def to_s
"Cask '#{token}' conflicts with '#{conflicting_cask}'."
end
end
# Error when a cask is not available.
#
# @api private
class CaskUnavailableError < AbstractCaskErrorWithToken
extend T::Sig
sig { returns(String) }
def to_s
"Cask '#{token}' is unavailable#{reason.empty? ? "." : ": #{reason}"}"
end
end
# Error when a cask is unreadable.
#
# @api private
class CaskUnreadableError < CaskUnavailableError
extend T::Sig
sig { returns(String) }
def to_s
"Cask '#{token}' is unreadable#{reason.empty? ? "." : ": #{reason}"}"
end
end
# Error when a cask already exists.
#
# @api private
class CaskAlreadyCreatedError < AbstractCaskErrorWithToken
extend T::Sig
sig { returns(String) }
def to_s
%Q(Cask '#{token}' already exists. Run #{Formatter.identifier("brew cask edit #{token}")} to edit it.)
end
end
# Error when a cask is already installed.
#
# @api private
class CaskAlreadyInstalledError < AbstractCaskErrorWithToken
extend T::Sig
sig { returns(String) }
def to_s
<<~EOS
Cask '#{token}' is already installed.
To re-install #{token}, run:
#{Formatter.identifier("brew reinstall #{token}")}
EOS
end
end
# Error when a cask depends on X11.
#
# @api private
class CaskX11DependencyError < AbstractCaskErrorWithToken
extend T::Sig
sig { returns(String) }
def to_s
<<~EOS
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/")}
EOS
end
end
# Error when there is a cyclic cask dependency.
#
# @api private
class CaskCyclicDependencyError < AbstractCaskErrorWithToken
extend T::Sig
sig { returns(String) }
def to_s
"Cask '#{token}' includes cyclic dependencies on other Casks#{reason.empty? ? "." : ": #{reason}"}"
end
end
# Error when a cask depends on itself.
#
# @api private
class CaskSelfReferencingDependencyError < CaskCyclicDependencyError
extend T::Sig
sig { returns(String) }
def to_s
"Cask '#{token}' depends on itself."
end
end
# Error when no cask is specified.
#
# @api private
class CaskUnspecifiedError < CaskError
extend T::Sig
sig { returns(String) }
def to_s
"This command requires a Cask token."
end
end
# Error when a cask is invalid.
#
# @api private
class CaskInvalidError < AbstractCaskErrorWithToken
extend T::Sig
sig { returns(String) }
def to_s
"Cask '#{token}' definition is invalid#{reason.empty? ? "." : ": #{reason}"}"
end
end
# Error when a cask token does not match the file name.
#
# @api private
class CaskTokenMismatchError < CaskInvalidError
def initialize(token, header_token)
super(token, "Token '#{header_token}' in header line does not match the file name.")
end
end
# Error with a cask's checksum.
#
# @api private
class CaskSha256Error < AbstractCaskErrorWithToken
attr_reader :expected, :actual
def initialize(token, expected = nil, actual = nil)
super(token)
@expected = expected
@actual = actual
end
end
# Error when a cask's checksum is missing.
#
# @api private
class CaskSha256MissingError < CaskSha256Error
extend T::Sig
sig { returns(String) }
def to_s
<<~EOS
Cask '#{token}' requires a checksum:
#{Formatter.identifier("sha256 \"#{actual}\"")}
EOS
end
end
# Error when a cask's checksum does not match.
#
# @api private
class CaskSha256MismatchError < CaskSha256Error
extend T::Sig
attr_reader :path
def initialize(token, expected, actual, path)
super(token, expected, actual)
@path = path
end
sig { returns(String) }
def to_s
<<~EOS
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.
If the issue persists, visit:
#{Formatter.url("https://github.com/Homebrew/homebrew-cask/blob/HEAD/doc/reporting_bugs/checksum_does_not_match_error.md")}
EOS
end
end
# Error when a cask has no checksum and the `--require-sha` flag is passed.
#
# @api private
class CaskNoShasumError < CaskSha256Error
extend T::Sig
sig { returns(String) }
def to_s
<<~EOS
Cask '#{token}' does not have a sha256 checksum defined and was not installed.
This means you have the #{Formatter.identifier("--require-sha")} option set, perhaps in your HOMEBREW_CASK_OPTS.
EOS
end
end
# Error during quarantining of a file.
#
# @api private
class CaskQuarantineError < CaskError
extend T::Sig
attr_reader :path, :reason
def initialize(path, reason)
super()
@path = path
@reason = reason
end
sig { returns(String) }
def to_s
s = +"Failed to quarantine #{path}."
unless reason.empty?
s << " Here's the reason:\n"
s << Formatter.error(reason)
s << "\n" unless reason.end_with?("\n")
end
s.freeze
end
end
# Error while propagating quarantine information to subdirectories.
#
# @api private
class CaskQuarantinePropagationError < CaskQuarantineError
extend T::Sig
sig { returns(String) }
def to_s
s = +"Failed to quarantine one or more files within #{path}."
unless reason.empty?
s << " Here's the reason:\n"
s << Formatter.error(reason)
s << "\n" unless reason.end_with?("\n")
end
s.freeze
end
end
# Error while removing quarantine information.
#
# @api private
class CaskQuarantineReleaseError < CaskQuarantineError
extend T::Sig
sig { returns(String) }
def to_s
s = +"Failed to release #{path} from quarantine."
unless reason.empty?
s << " Here's the reason:\n"
s << Formatter.error(reason)
s << "\n" unless reason.end_with?("\n")
end
s.freeze
end
end
end