You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

117 line
4.5 KiB

10 年之前
10 年之前
10 年之前
10 年之前
10 年之前
10 年之前
  1. %% -*- erlang-indent-level: 4;indent-tabs-mode: nil -*-
  2. %% ex: ts=4 sw=4 et
  3. -module(rebar_prv_do).
  4. -behaviour(provider).
  5. -export([init/1,
  6. do/1,
  7. do_tasks/2,
  8. format_error/1]).
  9. -include("rebar.hrl").
  10. -define(PROVIDER, do).
  11. -define(DEPS, []).
  12. %% ===================================================================
  13. %% Public API
  14. %% ===================================================================
  15. -spec init(rebar_state:t()) -> {ok, rebar_state:t()}.
  16. init(State) ->
  17. State1 = rebar_state:add_provider(State, providers:create([{name, ?PROVIDER},
  18. {module, ?MODULE},
  19. {bare, true},
  20. {deps, ?DEPS},
  21. {example, "rebar3 do <task1>, <task2>, ..."},
  22. {short_desc, "Higher order provider for running multiple tasks in a sequence."},
  23. {desc, "Higher order provider for running multiple tasks in a sequence."},
  24. {opts, []}])),
  25. {ok, State1}.
  26. -spec do(rebar_state:t()) -> {ok, rebar_state:t()} | {error, string()}.
  27. do(State) ->
  28. case rebar_utils:args_to_tasks(rebar_state:command_args(State)) of
  29. [] ->
  30. AllProviders = rebar_state:providers(State),
  31. Namespace = rebar_state:namespace(State),
  32. Providers = providers:get_providers_by_namespace(Namespace, AllProviders),
  33. providers:help(Providers),
  34. {ok, State};
  35. Tasks ->
  36. do_tasks(Tasks, State)
  37. end.
  38. -spec do_tasks(list(Task), State) -> Res when
  39. Task :: {string(), string()} |
  40. {string(), atom()} |
  41. {atom(), atom(), string()},
  42. State :: rebar_state:t(),
  43. Res :: {ok, rebar_state:t()} |
  44. {error, term()}.
  45. do_tasks([], State) ->
  46. {ok, State};
  47. do_tasks([{TaskStr, Args} | Tail], State) when is_list(Args) ->
  48. Task = list_to_atom(TaskStr),
  49. State1 = rebar_state:set(State, task, Task),
  50. State2 = rebar_state:command_args(State1, Args),
  51. Namespace = rebar_state:namespace(State2),
  52. do_task(TaskStr, Args, Tail, State, Namespace);
  53. do_tasks([{Namespace, Task} | Tail], State) ->
  54. do_task(atom_to_list(Task), [], Tail, State, Namespace);
  55. do_tasks([{Namespace, Task, Args} | Tail], State)
  56. when is_atom(Namespace), is_atom(Task) ->
  57. do_task(atom_to_list(Task), Args, Tail, State, Namespace).
  58. do_task(TaskStr, Args, Tail, State, Namespace) ->
  59. Task = list_to_atom(TaskStr),
  60. State1 = rebar_state:set(State, task, Task),
  61. State2 = rebar_state:command_args(State1, Args),
  62. case Namespace of
  63. default ->
  64. %% The first task we hit might be a namespace!
  65. case maybe_namespace(State2, Task, Args) of
  66. {ok, FinalState} when Tail =:= [] ->
  67. {ok, FinalState};
  68. {ok, _} ->
  69. do_tasks(Tail, State);
  70. {error, Reason} ->
  71. {error, Reason}
  72. end;
  73. _ ->
  74. %% We're already in a non-default namespace, check the
  75. %% task directly.
  76. State3 = rebar_state:namespace(State2, Namespace),
  77. case rebar_core:process_command(State3, Task) of
  78. {ok, FinalState} when Tail =:= [] ->
  79. {ok, FinalState};
  80. {ok, _} ->
  81. do_tasks(Tail, State);
  82. {error, Reason} ->
  83. {error, Reason}
  84. end
  85. end.
  86. -spec format_error(any()) -> iolist().
  87. format_error(Reason) ->
  88. io_lib:format("~p", [Reason]).
  89. maybe_namespace(State, Task, Args) ->
  90. case rebar_core:process_namespace(State, Task) of
  91. {ok, State2, Task} ->
  92. %% The task exists after all.
  93. rebar_core:process_command(State2, Task);
  94. {ok, State2, do} when Args =/= [] ->
  95. %% We are in 'do' so we can't apply it directly.
  96. [NewTaskStr | NewArgs] = Args,
  97. NewTask = list_to_atom(NewTaskStr),
  98. State3 = rebar_state:command_args(State2, NewArgs),
  99. rebar_core:process_command(State3, NewTask);
  100. {ok, _, _} ->
  101. %% No arguments to consider as a command. Woops.
  102. {error, io_lib:format("Command ~p not found", [Task])};
  103. {error, Reason} ->
  104. {error, Reason}
  105. end.