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.
|
# 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
|
# 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 [Symbol] task the task to run
|
||||||
# @param [Array<String>] files the list of files to pass to the task
|
# @param [Array<String>] files the list of files to pass to the task
|
||||||
#
|
#
|
||||||
def run_guard_task(task, files = nil)
|
def run_guard_task(task, files = nil)
|
||||||
groups.each do |group|
|
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|
|
guards(:group => group.name).each do |guard|
|
||||||
if task == :run_on_change
|
if task == :run_on_change
|
||||||
run_on_change_task(files, guard, task)
|
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.
|
# 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 [Guard::Guard] guard the Guard to execute
|
||||||
# @param [Symbol] task the task to run
|
# @param [Symbol] task the task to run
|
||||||
# @param [Array] args the arguments for the task
|
# @param [Array] args the arguments for the task
|
||||||
# @raise [:task_has_failed] when task has failed
|
# @raise [:task_has_failed] when task has failed
|
||||||
#
|
#
|
||||||
def run_supervised_task(guard, task, *args)
|
def run_supervised_task(guard, task, *args)
|
||||||
guard.hook("#{ task }_begin", *args)
|
catch guard_symbol(guard) do
|
||||||
result = guard.send(task, *args)
|
guard.hook("#{ task }_begin", *args)
|
||||||
guard.hook("#{ task }_end", result)
|
result = guard.send(task, *args)
|
||||||
|
guard.hook("#{ task }_end", result)
|
||||||
|
|
||||||
result
|
result
|
||||||
|
end
|
||||||
|
|
||||||
rescue Exception => ex
|
rescue Exception => ex
|
||||||
UI.error("#{ guard.class.name } failed to achieve its <#{ task.to_s }>, exception was:" +
|
UI.error("#{ guard.class.name } failed to achieve its <#{ task.to_s }>, exception was:" +
|
||||||
@ -284,6 +289,25 @@ module Guard
|
|||||||
ex
|
ex
|
||||||
end
|
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.
|
# Add a Guard to use.
|
||||||
#
|
#
|
||||||
# @param [String] name the Guard name
|
# @param [String] name the Guard name
|
||||||
|
@ -369,7 +369,7 @@ describe Guard do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context "one guard fails (by returning false)" do
|
context "one guard fails" do
|
||||||
before do
|
before do
|
||||||
subject.guards.each_with_index do |g, i|
|
subject.guards.each_with_index do |g, i|
|
||||||
g.stub!(:task) do
|
g.stub!(:task) do
|
||||||
@ -437,6 +437,7 @@ describe Guard do
|
|||||||
@g = mock(Guard::Guard).as_null_object
|
@g = mock(Guard::Guard).as_null_object
|
||||||
subject.guards.push(@g)
|
subject.guards.push(@g)
|
||||||
subject.add_group(:foo, { :halt_on_fail => true })
|
subject.add_group(:foo, { :halt_on_fail => true })
|
||||||
|
subject.add_group(:bar, { :halt_on_fail => false })
|
||||||
end
|
end
|
||||||
|
|
||||||
context "with a task that succeed" do
|
context "with a task that succeed" do
|
||||||
@ -486,16 +487,26 @@ describe Guard do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context "with a task that return false and guard's group has the :halt_on_fail option == true" do
|
context "with a task that throw :task_has_failed" do
|
||||||
before(:each) { @g.stub!(:group) { :foo }; @g.stub!(:failing) { throw :task_has_failed } }
|
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
|
it "throws :task_has_failed" do
|
||||||
expect { subject.run_supervised_task(@g, :failing) }.to throw_symbol(:task_has_failed)
|
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
|
||||||
end
|
end
|
||||||
|
|
||||||
context "with a task that raises an exception" do
|
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
|
it "fires the Guard" do
|
||||||
lambda { subject.run_supervised_task(@g, :failing) }.should change(subject.guards, :size).by(-1)
|
lambda { subject.run_supervised_task(@g, :failing) }.should change(subject.guards, :size).by(-1)
|
||||||
@ -510,6 +521,42 @@ describe Guard do
|
|||||||
end
|
end
|
||||||
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
|
describe ".debug_command_execution" do
|
||||||
subject { ::Guard.setup }
|
subject { ::Guard.setup }
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user