Ensure reenabling a task from inside a child propagates up, closes #10227

This commit is contained in:
José Valim
2020-07-23 16:43:07 +02:00
parent afb6e207a4
commit 97e8b0242d
2 changed files with 36 additions and 25 deletions
+19 -21
View File
@@ -355,22 +355,18 @@ defmodule Mix.Task do
alias = Mix.Project.config()[:aliases][String.to_atom(task)]
cond do
alias && Mix.TasksServer.run({:alias, task, proj}) ->
res = run_alias(List.wrap(alias), args, task, :ok)
Mix.TasksServer.put({:task, task, proj})
res
Mix.TasksServer.run({:task, task, proj}) ->
is_nil(alias) ->
run_task(proj, task, args)
Mix.TasksServer.run({:alias, task, proj}) ->
run_alias(List.wrap(alias), args, proj, task, :ok)
true ->
:noop
end
end
defp run_task(proj, task, args) do
if Mix.debug?(), do: output_task_debug_info(task, args, proj)
# 1. If the task is available, we run it.
# 2. Otherwise we compile and load dependencies
# 3. Finally, we compile the current project in hope it is available.
@@ -379,8 +375,6 @@ defmodule Mix.Task do
get_task_or_run(proj, task, fn -> Mix.Task.run("compile", []) end) ||
get!(task)
run_requirements(module)
recursive = recursive(module)
cond do
@@ -392,8 +386,9 @@ defmodule Mix.Task do
not recursive && Mix.ProjectStack.recursing() ->
Mix.ProjectStack.on_recursing_root(fn -> run(task, args) end)
true ->
Mix.TasksServer.put({:task, task, proj})
Mix.TasksServer.run({:task, task, proj}) ->
if Mix.debug?(), do: output_task_debug_info(task, args, proj)
run_requirements(module)
try do
module.run(args)
@@ -401,13 +396,16 @@ defmodule Mix.Task do
e in OptionParser.ParseError ->
Mix.raise("Could not invoke task #{inspect(task)}: " <> Exception.message(e))
end
true ->
:noop
end
end
defp run_requirements(module) do
Enum.each(requirements(module), fn requirement ->
[task | args] = OptionParser.split(requirement)
Mix.Task.run(task, args)
run(task, args)
end)
end
@@ -435,24 +433,24 @@ defmodule Mix.Task do
end
end
defp run_alias([h | t], alias_args, original_task, _res) when is_binary(h) do
defp run_alias([h | t], alias_args, proj, original_task, _res) when is_binary(h) do
case OptionParser.split(h) do
[^original_task | args] ->
res = Mix.Task.run(original_task, args ++ alias_args)
run_alias(t, [], original_task, res)
res = run_task(proj, original_task, args ++ alias_args)
run_alias(t, [], proj, original_task, res)
[task | args] ->
res = Mix.Task.run(task, join_args(args, alias_args, t))
run_alias(t, alias_args, original_task, res)
res = run(task, join_args(args, alias_args, t))
run_alias(t, alias_args, proj, original_task, res)
end
end
defp run_alias([h | t], alias_args, original_task, _res) when is_function(h, 1) do
defp run_alias([h | t], alias_args, proj, original_task, _res) when is_function(h, 1) do
res = h.(join_args([], alias_args, t))
run_alias(t, alias_args, original_task, res)
run_alias(t, alias_args, proj, original_task, res)
end
defp run_alias([], _alias_task, _original_task, res) do
defp run_alias([], _alias_task, _proj, _original_task, res) do
res
end
+17 -4
View File
@@ -150,11 +150,25 @@ defmodule Mix.TaskTest do
in_fixture("umbrella_dep/deps/umbrella", fn ->
Mix.Project.in_project(:umbrella, ".", fn _ ->
assert [:ok, :ok] = Mix.Task.run("clean")
assert :noop = Mix.Task.run("clean")
assert [:noop, :noop] = Mix.Task.run("clean")
Mix.Task.reenable("clean")
assert [:ok, :ok] = Mix.Task.run("clean")
assert :noop = Mix.Task.run("clean")
assert [:noop, :noop] = Mix.Task.run("clean")
end)
end)
end
test "reenable/1 for recursive inside umbrella child" do
in_fixture("umbrella_dep/deps/umbrella", fn ->
Mix.Project.in_project(:umbrella, ".", fn _ ->
assert [:ok, :ok] = Mix.Task.run("cmd", ["echo", "hello"])
assert [:ok, :ok] = Mix.Task.run("cmd", ["echo", "world"])
assert_received {:mix_shell, :run, ["hello" <> _]}
assert_received {:mix_shell, :run, ["world" <> _]}
assert_received {:mix_shell, :run, ["hello" <> _]}
assert_received {:mix_shell, :run, ["world" <> _]}
end)
end)
end
@@ -178,7 +192,7 @@ defmodule Mix.TaskTest do
in_fixture("umbrella_dep/deps/umbrella", fn ->
Mix.Project.in_project(:umbrella, ".", fn _ ->
assert [:ok, :ok] = Mix.Task.run("clean")
assert :noop = Mix.Task.run("clean")
assert [:noop, :noop] = Mix.Task.run("clean")
assert [:ok, :ok] = Mix.Task.rerun("clean")
end)
end)
@@ -186,7 +200,6 @@ defmodule Mix.TaskTest do
test "get!" do
Mix.Project.push(MixTest.Case.Sample)
assert Mix.Task.get!("hello") == Mix.Tasks.Hello
assert_raise Mix.NoTaskError, "The task \"unknown\" could not be found", fn ->