Skip to content

Commit a8ebea2

Browse files
authored
Merge pull request #252 from grzuy/fix_multitask_failures
[Fixes #189] [Fixes #190] Don't run task if it depends on already invoked but failed task
2 parents 55bee9a + edb7743 commit a8ebea2

File tree

3 files changed

+53
-48
lines changed

3 files changed

+53
-48
lines changed

lib/rake/multi_task.rb

Lines changed: 1 addition & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -5,46 +5,10 @@ module Rake
55
# parallel using Ruby threads.
66
#
77
class MultiTask < Task
8-
9-
# Same as invoke, but explicitly pass a call chain to detect
10-
# circular dependencies. This is largely copied from Rake::Task
11-
# but has been updated such that if multiple tasks depend on this
12-
# one in parallel, they will all fail if the first execution of
13-
# this task fails.
14-
def invoke_with_call_chain(task_args, invocation_chain)
15-
new_chain = Rake::InvocationChain.append(self, invocation_chain)
16-
@lock.synchronize do
17-
begin
18-
if @already_invoked
19-
if @invocation_exception
20-
if application.options.trace
21-
application.trace "** Previous invocation of #{name} failed #{format_trace_flags}"
22-
end
23-
raise @invocation_exception
24-
else
25-
return
26-
end
27-
end
28-
29-
if application.options.trace
30-
application.trace "** Invoke #{name} #{format_trace_flags}"
31-
end
32-
@already_invoked = true
33-
34-
invoke_prerequisites(task_args, new_chain)
35-
execute(task_args) if needed?
36-
rescue Exception => ex
37-
add_chain_to(ex, new_chain)
38-
@invocation_exception = ex
39-
raise
40-
end
41-
end
42-
end
43-
448
private
9+
4510
def invoke_prerequisites(task_args, invocation_chain) # :nodoc:
4611
invoke_prerequisites_concurrently(task_args, invocation_chain)
4712
end
4813
end
49-
5014
end

lib/rake/task.rb

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ def initialize(task_name, app)
103103
@scope = app.current_scope
104104
@arg_names = nil
105105
@locations = []
106+
@invocation_exception = nil
106107
end
107108

108109
# Enhance a task with prerequisites or actions. Returns self.
@@ -183,20 +184,39 @@ def invoke(*args)
183184

184185
# Same as invoke, but explicitly pass a call chain to detect
185186
# circular dependencies.
186-
def invoke_with_call_chain(task_args, invocation_chain) # :nodoc:
187-
new_chain = InvocationChain.append(self, invocation_chain)
187+
#
188+
# If multiple tasks depend on this
189+
# one in parallel, they will all fail if the first execution of
190+
# this task fails.
191+
def invoke_with_call_chain(task_args, invocation_chain)
192+
new_chain = Rake::InvocationChain.append(self, invocation_chain)
188193
@lock.synchronize do
189-
if application.options.trace
190-
application.trace "** Invoke #{name} #{format_trace_flags}"
194+
begin
195+
if application.options.trace
196+
application.trace "** Invoke #{name} #{format_trace_flags}"
197+
end
198+
199+
if @already_invoked
200+
if @invocation_exception
201+
if application.options.trace
202+
application.trace "** Previous invocation of #{name} failed #{format_trace_flags}"
203+
end
204+
raise @invocation_exception
205+
else
206+
return
207+
end
208+
end
209+
210+
@already_invoked = true
211+
212+
invoke_prerequisites(task_args, new_chain)
213+
execute(task_args) if needed?
214+
rescue Exception => ex
215+
add_chain_to(ex, new_chain)
216+
@invocation_exception = ex
217+
raise ex
191218
end
192-
return if @already_invoked
193-
@already_invoked = true
194-
invoke_prerequisites(task_args, new_chain)
195-
execute(task_args) if needed?
196219
end
197-
rescue Exception => ex
198-
add_chain_to(ex, new_chain)
199-
raise ex
200220
end
201221
protected :invoke_with_call_chain
202222

test/test_rake_multi_task.rb

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,4 +82,25 @@ def test_cross_thread_prerequisite_failures
8282
Rake::Task[:b].invoke
8383
end
8484
end
85+
86+
def test_task_not_executed_if_dependant_task_failed_concurrently
87+
multitask :default => [:one, :two]
88+
89+
task :one do
90+
raise
91+
end
92+
93+
task_two_was_executed = false
94+
task :two => :one do
95+
task_two_was_executed = true
96+
end
97+
98+
begin
99+
Rake::Task[:default].invoke
100+
rescue RuntimeError
101+
ensure
102+
sleep 0.5
103+
refute task_two_was_executed
104+
end
105+
end
85106
end

0 commit comments

Comments
 (0)