Make Guard implementation of :task_has_failed simple.
This change makes sure that Guard implementation can just `throw :task_has_failed` without knowing whether the enclosing group has enabled :halt_on_fail. The problem with throw/catch is, that when you throw a :symbol, you'll have to catch it, otherwise you get a 'uncatched throw' error. When the Guard group has not enabled :halt_on_fail, we catch the throw when execute the supervised task.
This commit is contained in:
parent
e9ddb1c110
commit
e33f5df518
36
lib/guard.rb
36
lib/guard.rb
@ -192,14 +192,14 @@ module Guard
|
||||
# Loop through all groups and run the given task for each Guard.
|
||||
#
|
||||
# Stop the task run for the all Guards within a group if one Guard
|
||||
# throws `:task_has_failed` and the group has its `:halt_on_fail` option to `true`.
|
||||
# throws `:task_has_failed`.
|
||||
#
|
||||
# @param [Symbol] task the task to run
|
||||
# @param [Array<String>] files the list of files to pass to the task
|
||||
#
|
||||
def run_guard_task(task, files = nil)
|
||||
groups.each do |group|
|
||||
catch group.options[:halt_on_fail] == true ? :task_has_failed : :no_catch do
|
||||
catch :task_has_failed do
|
||||
guards(:group => group.name).each do |guard|
|
||||
if task == :run_on_change
|
||||
run_on_change_task(files, guard, task)
|
||||
@ -262,17 +262,22 @@ module Guard
|
||||
|
||||
# Run a Guard task, but remove the Guard when his work leads to a system failure.
|
||||
#
|
||||
# When the Group has `:halt_on_fail` disabled, we've to catch `:task_has_failed`
|
||||
# here in order to avoid an uncaught throw error.
|
||||
#
|
||||
# @param [Guard::Guard] guard the Guard to execute
|
||||
# @param [Symbol] task the task to run
|
||||
# @param [Array] args the arguments for the task
|
||||
# @raise [:task_has_failed] when task has failed
|
||||
#
|
||||
def run_supervised_task(guard, task, *args)
|
||||
guard.hook("#{ task }_begin", *args)
|
||||
result = guard.send(task, *args)
|
||||
guard.hook("#{ task }_end", result)
|
||||
catch guard_symbol(guard) do
|
||||
guard.hook("#{ task }_begin", *args)
|
||||
result = guard.send(task, *args)
|
||||
guard.hook("#{ task }_end", result)
|
||||
|
||||
result
|
||||
result
|
||||
end
|
||||
|
||||
rescue Exception => ex
|
||||
UI.error("#{ guard.class.name } failed to achieve its <#{ task.to_s }>, exception was:" +
|
||||
@ -284,6 +289,25 @@ module Guard
|
||||
ex
|
||||
end
|
||||
|
||||
# Get the symbol we have to catch when running a supervised task.
|
||||
# If we are within a Guard group that has the `:halt_on_fail`
|
||||
# option set, we do NOT catch it here, it will be catched at the
|
||||
# group level.
|
||||
#
|
||||
# @see .run_guard_task
|
||||
#
|
||||
# @param [Guard::Guard] guard the Guard to execute
|
||||
# @return [Symbol] the symbol to catch
|
||||
#
|
||||
def guard_symbol(guard)
|
||||
if guard.group.class == Symbol
|
||||
group = groups(guard.group)
|
||||
group.options[:halt_on_fail] ? :no_catch : :task_has_failed
|
||||
else
|
||||
:task_has_failed
|
||||
end
|
||||
end
|
||||
|
||||
# Add a Guard to use.
|
||||
#
|
||||
# @param [String] name the Guard name
|
||||
|
@ -369,7 +369,7 @@ describe Guard do
|
||||
end
|
||||
end
|
||||
|
||||
context "one guard fails (by returning false)" do
|
||||
context "one guard fails" do
|
||||
before do
|
||||
subject.guards.each_with_index do |g, i|
|
||||
g.stub!(:task) do
|
||||
@ -437,6 +437,7 @@ describe Guard do
|
||||
@g = mock(Guard::Guard).as_null_object
|
||||
subject.guards.push(@g)
|
||||
subject.add_group(:foo, { :halt_on_fail => true })
|
||||
subject.add_group(:bar, { :halt_on_fail => false })
|
||||
end
|
||||
|
||||
context "with a task that succeed" do
|
||||
@ -486,16 +487,26 @@ describe Guard do
|
||||
end
|
||||
end
|
||||
|
||||
context "with a task that return false and guard's group has the :halt_on_fail option == true" do
|
||||
before(:each) { @g.stub!(:group) { :foo }; @g.stub!(:failing) { throw :task_has_failed } }
|
||||
context "with a task that throw :task_has_failed" do
|
||||
context "for a guard's group has the :halt_on_fail option == true" do
|
||||
before(:each) { @g.stub!(:group) { :foo }; @g.stub!(:failing) { throw :task_has_failed } }
|
||||
|
||||
it "throws :task_has_failed" do
|
||||
expect { subject.run_supervised_task(@g, :failing) }.to throw_symbol(:task_has_failed)
|
||||
it "throws :task_has_failed" do
|
||||
expect { subject.run_supervised_task(@g, :failing) }.to throw_symbol(:task_has_failed)
|
||||
end
|
||||
end
|
||||
|
||||
context "for a guard's group has the :halt_on_fail option == false" do
|
||||
before(:each) { @g.stub!(:group) { :bar }; @g.stub!(:failing) { throw :task_has_failed } }
|
||||
|
||||
it "catches :task_has_failed" do
|
||||
expect { subject.run_supervised_task(@g, :failing) }.to_not throw_symbol(:task_has_failed)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "with a task that raises an exception" do
|
||||
before(:each) { @g.stub!(:failing) { raise "I break your system" } }
|
||||
before(:each) { @g.stub!(:group) { :foo }; @g.stub!(:failing) { raise "I break your system" } }
|
||||
|
||||
it "fires the Guard" do
|
||||
lambda { subject.run_supervised_task(@g, :failing) }.should change(subject.guards, :size).by(-1)
|
||||
@ -510,6 +521,42 @@ describe Guard do
|
||||
end
|
||||
end
|
||||
|
||||
describe '.guard_symbol' do
|
||||
let(:guard) { mock(Guard::Guard).as_null_object }
|
||||
|
||||
it 'returns :task_has_failed when the group is missing' do
|
||||
subject.guard_symbol(guard).should eql :task_has_failed
|
||||
end
|
||||
|
||||
context 'for a group with :halt_on_fail' do
|
||||
let(:group) { mock(Guard::Group) }
|
||||
|
||||
before do
|
||||
guard.stub(:group).and_return :foo
|
||||
group.stub(:options).and_return({ :halt_on_fail => true })
|
||||
end
|
||||
|
||||
it 'returns :task_has_failed when the group is missing' do
|
||||
subject.should_receive(:groups).with(:foo).and_return group
|
||||
subject.guard_symbol(guard).should eql :no_catch
|
||||
end
|
||||
end
|
||||
|
||||
context 'for a group without :halt_on_fail' do
|
||||
let(:group) { mock(Guard::Group) }
|
||||
|
||||
before do
|
||||
guard.stub(:group).and_return :foo
|
||||
group.stub(:options).and_return({ :halt_on_fail => false })
|
||||
end
|
||||
|
||||
it 'returns :task_has_failed when the group is missing' do
|
||||
subject.should_receive(:groups).with(:foo).and_return group
|
||||
subject.guard_symbol(guard).should eql :task_has_failed
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe ".debug_command_execution" do
|
||||
subject { ::Guard.setup }
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user