Make Cask commands fail early if a Cask is not found.

This commit is contained in:
Markus Reiter 2017-09-11 08:37:15 +02:00
parent f3ec40d696
commit ef67b77d95
21 changed files with 72 additions and 117 deletions

View File

@ -116,6 +116,22 @@ module Hbc
end end
end end
class FromInstanceLoader
attr_reader :cask
def self.can_load?(ref)
ref.is_a?(Cask)
end
def initialize(cask)
@cask = cask
end
def load
cask
end
end
class NullLoader < FromPathLoader class NullLoader < FromPathLoader
def self.can_load?(*) def self.can_load?(*)
true true
@ -149,6 +165,7 @@ module Hbc
def self.for(ref) def self.for(ref)
[ [
FromInstanceLoader,
FromURILoader, FromURILoader,
FromTapLoader, FromTapLoader,
FromTapPathLoader, FromTapPathLoader,

View File

@ -42,41 +42,32 @@ module Hbc
@args = process_arguments(*args) @args = process_arguments(*args)
end end
def self.warn_unavailable_with_suggestion(cask_token, e)
exact_match, partial_matches = Search.search(cask_token)
error_message = e.message
if exact_match
error_message.concat(" Did you mean:\n#{exact_match}")
elsif !partial_matches.empty?
error_message.concat(" Did you mean one of:\n")
.concat(Formatter.columns(partial_matches.take(20)))
end
onoe error_message
end
private private
def casks(alternative: -> { [] }) def casks(alternative: -> { [] })
return to_enum(:casks, alternative: alternative) unless block_given? return @casks if defined?(@casks)
count = 0
casks = args.empty? ? alternative.call : args casks = args.empty? ? alternative.call : args
@casks = casks.map { |cask| CaskLoader.load(cask) }
rescue CaskUnavailableError => e
reason = [e.reason, suggestion_message(e.token)].join(" ")
raise e.class.new(e.token, reason)
end
casks.each do |cask_or_token| def suggestion_message(cask_token)
begin exact_match, partial_matches = Search.search(cask_token)
yield cask_or_token.respond_to?(:token) ? cask_or_token : CaskLoader.load(cask_or_token)
count += 1 if exact_match.nil? && partial_matches.count == 1
rescue CaskUnavailableError => e exact_match = partial_matches.first
cask_token = cask_or_token
self.class.warn_unavailable_with_suggestion cask_token, e
rescue CaskError => e
onoe e.message
end
end end
return :empty if casks.length.zero? if exact_match
(count == casks.length) ? :complete : :incomplete "Did you mean “#{exact_match}”?"
elsif !partial_matches.empty?
"Did you mean one of these?\n"
.concat(Formatter.columns(partial_matches.take(20)))
else
""
end
end end
end end
end end

View File

@ -7,10 +7,6 @@ module Hbc
end end
def run def run
raise CaskError, "Cat incomplete." if cat_casks == :incomplete
end
def cat_casks
casks.each do |cask| casks.each do |cask|
puts File.open(cask.sourcefile_path, &:read) puts File.open(cask.sourcefile_path, &:read)
end end

View File

@ -4,21 +4,18 @@ module Hbc
def initialize(*) def initialize(*)
super super
raise CaskUnspecifiedError if args.empty? raise CaskUnspecifiedError if args.empty?
raise ArgumentError, "Only one Cask can be created at a time." if args.count > 1 raise ArgumentError, "Only one Cask can be edited at a time." if args.count > 1
end end
def run def run
cask_token = args.first cask = casks.first
cask_path = begin cask_path = cask.sourcefile_path
CaskLoader.load(cask_token).sourcefile_path odebug "Opening editor for Cask #{cask.token}"
rescue CaskUnavailableError => e
reason = e.reason.empty? ? "" : "#{e.reason} "
reason.concat("Run #{Formatter.identifier("brew cask create #{e.token}")} to create a new Cask.")
raise e.class.new(e.token, reason)
end
odebug "Opening editor for Cask #{cask_token}"
exec_editor cask_path exec_editor cask_path
rescue CaskUnavailableError => e
reason = e.reason.empty? ? "" : "#{e.reason} "
reason.concat("Run #{Formatter.identifier("brew cask create #{e.token}")} to create a new Cask.")
raise e.class.new(e.token, reason)
end end
def self.help def self.help

View File

@ -9,10 +9,6 @@ module Hbc
end end
def run def run
raise CaskError, "Fetch incomplete." if fetch_casks == :incomplete
end
def fetch_casks
casks.each do |cask| casks.each do |cask|
ohai "Downloading external files for Cask #{cask}" ohai "Downloading external files for Cask #{cask}"
downloaded_path = Download.new(cask, force: force?).perform downloaded_path = Download.new(cask, force: force?).perform

View File

@ -10,10 +10,6 @@ module Hbc
end end
def run def run
raise CaskError, "Install incomplete." if install_casks == :incomplete
end
def install_casks
casks.each do |cask| casks.each do |cask|
begin begin
Installer.new(cask, binaries: binaries?, Installer.new(cask, binaries: binaries?,

View File

@ -12,7 +12,7 @@ module Hbc
if args.all? { |t| t =~ %r{^https?://} && t !~ /\.rb$/ } if args.all? { |t| t =~ %r{^https?://} && t !~ /\.rb$/ }
self.class.appcask_checkpoint_for_url(args) self.class.appcask_checkpoint_for_url(args)
else else
self.class.appcask_checkpoint(args, calculate?) self.class.appcask_checkpoint(load_casks, calculate?)
end end
end end
@ -23,33 +23,27 @@ module Hbc
end end
end end
def self.appcask_checkpoint(cask_tokens, calculate) def self.appcask_checkpoint(casks, calculate)
count = 0 casks.each do |cask|
cask_tokens.each do |cask_token|
cask = CaskLoader.load(cask_token)
if cask.appcast.nil? if cask.appcast.nil?
opoo "Cask '#{cask}' is missing an `appcast` stanza." opoo "Cask '#{cask}' is missing an `appcast` stanza."
else else
if calculate checkpoint = if calculate
result = cask.appcast.calculate_checkpoint result = cask.appcast.calculate_checkpoint
result[:checkpoint]
checkpoint = result[:checkpoint]
else else
checkpoint = cask.appcast.checkpoint cask.appcast.checkpoint
end end
if checkpoint.nil? if calculate && checkpoint.nil?
onoe "Could not retrieve `appcast` checkpoint for cask '#{cask}': #{result[:command_result].stderr}" onoe "Could not retrieve `appcast` checkpoint for cask '#{cask}': #{result[:command_result].stderr}"
elsif casks.count > 1
puts "#{checkpoint} #{cask}"
else else
puts((cask_tokens.count > 1) ? "#{checkpoint} #{cask}" : checkpoint) puts checkpoint
count += 1
end end
end end
end end
count == cask_tokens.count
end end
def self.help def self.help

View File

@ -7,10 +7,6 @@ module Hbc
end end
def run def run
raise CaskError, "Dump incomplete." if dump_casks == :incomplete
end
def dump_casks
casks.each(&:dumpcask) casks.each(&:dumpcask)
end end

View File

@ -46,12 +46,6 @@ module Hbc
end end
def run def run
return unless print_stanzas == :incomplete
exit 1 if quiet?
raise CaskError, "Print incomplete."
end
def print_stanzas
if ARTIFACTS.include?(stanza) if ARTIFACTS.include?(stanza)
artifact_name = stanza artifact_name = stanza
@stanza = :artifacts @stanza = :artifacts

View File

@ -10,8 +10,7 @@ module Hbc
end) end)
def run def run
retval = args.any? ? list : list_installed args.any? ? list : list_installed
raise CaskError, "Listing incomplete." if retval == :incomplete
end end
def list def list
@ -46,8 +45,6 @@ module Hbc
elsif !installed_casks.empty? elsif !installed_casks.empty?
puts Formatter.columns(installed_casks.map(&:to_s)) puts Formatter.columns(installed_casks.map(&:to_s))
end end
installed_casks.empty? ? :empty : :complete
end end
def self.format_versioned(cask) def self.format_versioned(cask)

View File

@ -1,7 +1,7 @@
module Hbc module Hbc
class CLI class CLI
class Reinstall < Install class Reinstall < Install
def install_casks def run
casks.each do |cask| casks.each do |cask|
Installer.new(cask, binaries: binaries?, Installer.new(cask, binaries: binaries?,
verbose: verbose?, verbose: verbose?,

View File

@ -9,10 +9,6 @@ module Hbc
end end
def run def run
raise CaskError, "Uninstall incomplete." if uninstall_casks == :incomplete
end
def uninstall_casks
casks.each do |cask| casks.each do |cask|
odebug "Uninstalling Cask #{cask}" odebug "Uninstalling Cask #{cask}"

View File

@ -9,10 +9,6 @@ module Hbc
end end
def run def run
raise CaskError, "Zap incomplete." if zap_casks == :incomplete
end
def zap_casks
casks.each do |cask| casks.each do |cask|
odebug "Zapping Cask #{cask}" odebug "Zapping Cask #{cask}"
Installer.new(cask, verbose: verbose?, force: force?).zap Installer.new(cask, verbose: verbose?, force: force?).zap

View File

@ -1,8 +1,10 @@
describe Hbc::CLI::Audit, :cask do describe Hbc::CLI::Audit, :cask do
let(:cask) { double("cask", token: nil) } let(:cask) { Hbc::Cask.new(nil) }
describe "selection of Casks to audit" do describe "selection of Casks to audit" do
it "audits all Casks if no tokens are given" do it "audits all Casks if no tokens are given" do
expect(cask).to be_a Hbc::Cask
allow(Hbc).to receive(:all).and_return([cask, cask]) allow(Hbc).to receive(:all).and_return([cask, cask])
expect(Hbc::Auditor).to receive(:audit).twice.and_return(true) expect(Hbc::Auditor).to receive(:audit).twice.and_return(true)

View File

@ -35,8 +35,7 @@ describe Hbc::CLI::Cat, :cask do
it "raises an exception when the Cask does not exist" do it "raises an exception when the Cask does not exist" do
expect { Hbc::CLI::Cat.run("notacask") } expect { Hbc::CLI::Cat.run("notacask") }
.to output(/is unavailable/).to_stderr .to raise_error(Hbc::CaskUnavailableError, /is unavailable/)
.and raise_error(Hbc::CaskError, "Cat incomplete.")
end end
describe "when no Cask is specified" do describe "when no Cask is specified" do

View File

@ -39,7 +39,7 @@ describe Hbc::CLI::Create, :cask do
it "raises an exception when more than one Cask is given" do it "raises an exception when more than one Cask is given" do
expect { expect {
described_class.run("additional-cask", "another-cask") described_class.run("additional-cask", "another-cask")
}.to raise_error(/Only one Cask can be created at a time./) }.to raise_error(/Only one Cask can be created at a time\./)
end end
it "raises an exception when the Cask already exists" do it "raises an exception when the Cask already exists" do

View File

@ -12,7 +12,7 @@ describe Hbc::CLI::Edit, :cask do
it "raises an error when given more than one argument" do it "raises an error when given more than one argument" do
expect { expect {
described_class.new("local-caffeine", "local-transmission") described_class.new("local-caffeine", "local-transmission")
}.to raise_error(/Only one Cask can be created at a time./) }.to raise_error(/Only one Cask can be edited at a time\./)
end end
it "raises an exception when the Cask doesnt exist" do it "raises an exception when the Cask doesnt exist" do

View File

@ -42,7 +42,7 @@ describe Hbc::CLI::Fetch, :cask do
it "properly handles Casks that are not present" do it "properly handles Casks that are not present" do
expect { expect {
Hbc::CLI::Fetch.run("notacask") Hbc::CLI::Fetch.run("notacask")
}.to raise_error(Hbc::CaskError, "Fetch incomplete.") }.to raise_error(Hbc::CaskUnavailableError)
end end
describe "when no Cask is specified" do describe "when no Cask is specified" do

View File

@ -56,27 +56,19 @@ describe Hbc::CLI::Install, :cask do
it "properly handles Casks that are not present" do it "properly handles Casks that are not present" do
expect { expect {
Hbc::CLI::Install.run("notacask") Hbc::CLI::Install.run("notacask")
}.to raise_error(Hbc::CaskError, "Install incomplete.") }.to raise_error(Hbc::CaskUnavailableError)
end end
it "returns a suggestion for a misspelled Cask" do it "returns a suggestion for a misspelled Cask" do
expect { expect {
begin Hbc::CLI::Install.run("localcaffeine")
Hbc::CLI::Install.run("localcaffeine") }.to raise_error(Hbc::CaskUnavailableError, /Cask 'localcaffeine' is unavailable: No Cask with this name exists\. Did you mean “local-caffeine”?/)
rescue Hbc::CaskError
nil
end
}.to output(/Cask 'localcaffeine' is unavailable: No Cask with this name exists\. 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
expect { expect {
begin Hbc::CLI::Install.run("local")
Hbc::CLI::Install.run("local-caf") }.to raise_error(Hbc::CaskUnavailableError, /Cask 'local' is unavailable: No Cask with this name exists\. Did you mean one of these\?\nlocal-caffeine\nlocal-transmission/)
rescue Hbc::CaskError
nil
end
}.to output(/Cask 'local-caf' is unavailable: No Cask with this name exists\. 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

View File

@ -16,14 +16,12 @@ describe Hbc::CLI::Uninstall, :cask do
it "shows an error when a bad Cask is provided" do it "shows an error when a bad Cask is provided" do
expect { Hbc::CLI::Uninstall.run("notacask") } expect { Hbc::CLI::Uninstall.run("notacask") }
.to output(/is unavailable/).to_stderr .to raise_error(Hbc::CaskUnavailableError, /is unavailable/)
.and raise_error(Hbc::CaskError, "Uninstall incomplete.")
end end
it "shows an error when a Cask is provided that's not installed" do it "shows an error when a Cask is provided that's not installed" do
expect { Hbc::CLI::Uninstall.run("local-caffeine") } expect { Hbc::CLI::Uninstall.run("local-caffeine") }
.to output(/is not installed/).to_stderr .to raise_error(Hbc::CaskNotInstalledError, /is not installed/)
.and raise_error(Hbc::CaskError, "Uninstall incomplete.")
end end
it "tries anyway on a non-present Cask when --force is given" do it "tries anyway on a non-present Cask when --force is given" do
@ -76,8 +74,7 @@ describe Hbc::CLI::Uninstall, :cask do
Hbc.appdir.join("MyFancyApp.app").rmtree Hbc.appdir.join("MyFancyApp.app").rmtree
expect { Hbc::CLI::Uninstall.run("with-uninstall-script-app") } expect { Hbc::CLI::Uninstall.run("with-uninstall-script-app") }
.to output(/does not exist/).to_stderr .to raise_error(Hbc::CaskError, /uninstall script .* does not exist/)
.and raise_error(Hbc::CaskError, "Uninstall incomplete.")
expect(cask).to be_installed expect(cask).to be_installed

View File

@ -1,8 +1,7 @@
describe Hbc::CLI::Zap, :cask do describe Hbc::CLI::Zap, :cask do
it "shows an error when a bad Cask is provided" do it "shows an error when a bad Cask is provided" do
expect { Hbc::CLI::Zap.run("notacask") } expect { Hbc::CLI::Zap.run("notacask") }
.to output(/is unavailable/).to_stderr .to raise_error(Hbc::CaskUnavailableError, /is unavailable/)
.and raise_error(Hbc::CaskError, "Zap incomplete.")
end end
it "can zap and unlink multiple Casks at once" do it "can zap and unlink multiple Casks at once" do