Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

147 lignes
6.5 KiB

il y a 10 ans
  1. %% -*- erlang-indent-level: 4;indent-tabs-mode: nil -*-
  2. %% ex: ts=4 sw=4 et
  3. %% -------------------------------------------------------------------
  4. %%
  5. %% rebar: Erlang Build Tools
  6. %%
  7. %% Copyright (c) 2009 Dave Smith (dizzyd@dizzyd.com)
  8. %%
  9. %% Permission is hereby granted, free of charge, to any person obtaining a copy
  10. %% of this software and associated documentation files (the "Software"), to deal
  11. %% in the Software without restriction, including without limitation the rights
  12. %% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  13. %% copies of the Software, and to permit persons to whom the Software is
  14. %% furnished to do so, subject to the following conditions:
  15. %%
  16. %% The above copyright notice and this permission notice shall be included in
  17. %% all copies or substantial portions of the Software.
  18. %%
  19. %% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  20. %% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  21. %% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  22. %% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  23. %% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  24. %% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  25. %% THE SOFTWARE.
  26. %% -------------------------------------------------------------------
  27. -module(rebar_core).
  28. -export([init_command/2, process_namespace/2, process_command/2, do/2, format_error/1]).
  29. -include("rebar.hrl").
  30. -include_lib("providers/include/providers.hrl").
  31. init_command(State, do) ->
  32. process_command(rebar_state:namespace(State, default), do);
  33. init_command(State, as) ->
  34. process_command(rebar_state:namespace(State, default), as);
  35. init_command(State, Command) ->
  36. case process_namespace(State, Command) of
  37. {ok, State1, Command1} ->
  38. process_command(State1, Command1);
  39. {error, Reason} ->
  40. {error, Reason}
  41. end.
  42. process_namespace(_State, as) ->
  43. {error, "Namespace 'as' is forbidden"};
  44. process_namespace(State, Command) ->
  45. Providers = rebar_state:providers(State),
  46. CommandProvider = providers:get_provider(Command, Providers, default),
  47. case CommandProvider of
  48. not_found ->
  49. case providers:get_providers_by_namespace(Command, Providers) of
  50. [] ->
  51. {error, io_lib:format("Command ~p not found", [Command])};
  52. _ ->
  53. %% Replay 'do' as a command of that namespace
  54. {ok, rebar_state:namespace(State, Command), do}
  55. end;
  56. _ ->
  57. {ok, rebar_state:namespace(State, default), Command}
  58. end.
  59. -spec process_command(rebar_state:t(), atom()) -> {ok, rebar_state:t()} | {error, string()} | {error, {module(), any()}}.
  60. process_command(State, Command) ->
  61. %% ? rebar_prv_install_deps:setup_env(State),
  62. Providers = rebar_state:providers(State),
  63. Namespace = rebar_state:namespace(State),
  64. TargetProviders = providers:get_target_providers(Command, Providers, Namespace),
  65. CommandProvider = providers:get_provider(Command, Providers, Namespace),
  66. case CommandProvider of
  67. not_found when Command =/= do ->
  68. case Namespace of
  69. default ->
  70. {error, io_lib:format("Command ~p not found", [Command])};
  71. _ ->
  72. {error, io_lib:format("Command ~p not found in namespace ~p",
  73. [Command, Namespace])}
  74. end;
  75. not_found when Command =:= do, Namespace =/= default ->
  76. do([{default, do} | TargetProviders], State);
  77. CommandProvider ->
  78. case Command of
  79. do ->
  80. do(TargetProviders, State);
  81. as ->
  82. do(TargetProviders, State);
  83. _ ->
  84. Profiles = providers:profiles(CommandProvider),
  85. State1 = rebar_state:apply_profiles(State, Profiles),
  86. Opts = providers:opts(CommandProvider)++rebar3:global_option_spec_list(),
  87. case getopt:parse(Opts, rebar_state:command_args(State1)) of
  88. {ok, Args} ->
  89. State2 = rebar_state:command_parsed_args(State1, Args),
  90. do(TargetProviders, State2);
  91. {error, {invalid_option, Option}} ->
  92. {error, io_lib:format("Invalid option ~s on task ~p", [Option, Command])};
  93. {error, {invalid_option_arg, {Option, Arg}}} ->
  94. {error, io_lib:format("Invalid argument ~s to option ~s", [Arg, Option])};
  95. {error, {missing_option_arg, Option}} ->
  96. {error, io_lib:format("Missing argument to option ~s", [Option])}
  97. end
  98. end
  99. end.
  100. -spec do([{atom(), atom()}], rebar_state:t()) -> {ok, rebar_state:t()} | {error, string()} | {error, {module(), any()}}.
  101. do([], State) ->
  102. {ok, State};
  103. do([ProviderName | Rest], State) ->
  104. %% Special providers like 'as', 'do' or some hooks may be passed
  105. %% as a tuple {Namespace, Name}, otherwise not. Handle them
  106. %% on a per-need basis.
  107. Provider = case ProviderName of
  108. {Namespace, Name} ->
  109. providers:get_provider(Name
  110. ,rebar_state:providers(State)
  111. ,Namespace);
  112. _ ->
  113. providers:get_provider(ProviderName
  114. ,rebar_state:providers(State)
  115. ,rebar_state:namespace(State))
  116. end,
  117. try providers:do(Provider, State) of
  118. {ok, State1} ->
  119. do(Rest, State1);
  120. {error, Error} ->
  121. {error, Error}
  122. catch
  123. error:undef ->
  124. Stack = erlang:get_stacktrace(),
  125. case Stack of
  126. [{ProviderName, do, [_], _}|_] ->
  127. %% This should really only happen if a plugin provider doesn't export do/1
  128. ?DEBUG("Undefined call to provider's do/1 function:~n~p", [Stack]),
  129. ?PRV_ERROR({bad_provider_namespace, ProviderName});
  130. _ -> % re-raise
  131. erlang:raise(error, undef, Stack)
  132. end;
  133. error:{badrecord,provider} ->
  134. {error, ProviderName}
  135. end.
  136. format_error({bad_provider_namespace, {Namespace, Name}}) ->
  137. io_lib:format("Undefined command ~s in namespace ~s", [Name, Namespace]);
  138. format_error({bad_provider_namespace, Name}) ->
  139. io_lib:format("Undefined command ~s", [Name]).