From a88bf7d96066f58db534efb7de59d52a88c02f6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20G=C3=B3mez?= Date: Tue, 21 Jun 2022 17:04:03 -0230 Subject: [PATCH] Skip unnecessary invokes to nested task of not needed tasks When a task is no needed (because `needed?` is false), running it with `--trace` still report all it dependencies. Rake is still calling `invoke_prerequisites` in a task not `needed`. This change simply avoid that call. --- lib/rake/task.rb | 6 ++++-- test/test_rake_task.rb | 29 +++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/lib/rake/task.rb b/lib/rake/task.rb index a8ed24ddf..695493262 100644 --- a/lib/rake/task.rb +++ b/lib/rake/task.rb @@ -215,8 +215,10 @@ def invoke_with_call_chain(task_args, invocation_chain) @already_invoked = true - invoke_prerequisites(task_args, new_chain) - execute(task_args) if needed? + if needed? + invoke_prerequisites(task_args, new_chain) + execute(task_args) + end rescue Exception => ex add_chain_to(ex, new_chain) @invocation_exception = ex diff --git a/test/test_rake_task.rb b/test/test_rake_task.rb index bffe2cb59..3f1d236e0 100644 --- a/test/test_rake_task.rb +++ b/test/test_rake_task.rb @@ -92,6 +92,35 @@ def test_tasks_can_be_traced Rake.application.options.trace = false end + def test_no_unnecesary_nested_invokes + test_no_unnecesary_nested_invokes__trace = [] # "Namespaced" array name + + # Overwrite "invoke_with_call_chain" to trace the tasks being _invoked_ + Rake::Task.alias_method :old_invoke_with_call_chain, :invoke_with_call_chain + Rake::Task.define_method(:invoke_with_call_chain) do |task_args, invocation_chain| + test_no_unnecesary_nested_invokes__trace << name + old_invoke_with_call_chain(task_args, invocation_chain) + end + + # Create the dependency graph t1 -> t2 -> t3 + t1 = task(t1: [:t2]) + t2 = task(t2: [:t3]) + t3 = task(:t3) + + # Force t2 to be not needed + t2.define_singleton_method(:needed?) { false } + + t1.invoke + + # Restore the original "invoke_with_call_chain" method, so other + # tests don't use the patched one. + Rake::Task.alias_method :invoke_with_call_chain, :old_invoke_with_call_chain + Rake::Task.remove_method :old_invoke_with_call_chain + + # Because t2 was not needed, there is no need to "invoke" t3 neither. + refute_includes test_no_unnecesary_nested_invokes__trace, "t3" + end + def test_no_double_invoke runlist = [] t1 = task(t1: [:t2, :t3]) { |t| runlist << t.name; 3321 }