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.

108 line
4.5 KiB

  1. -module(rebar_hooks).
  2. -export([run_all_hooks/5
  3. ,run_all_hooks/6
  4. ,run_project_and_app_hooks/5
  5. ,format_error/1]).
  6. -include("rebar.hrl").
  7. -include_lib("providers/include/providers.hrl").
  8. -spec run_all_hooks(file:filename_all(), pre | post,
  9. atom() | {atom(), atom()} | string(),
  10. [providers:t()], rebar_app_info:t(), rebar_state:t()) -> rebar_app_info:t().
  11. run_all_hooks(Dir, Type, Command, Providers, AppInfo, State) ->
  12. ?DEBUG("Running hooks for ~p in app ~ts (~ts) with configuration:",
  13. [Command, rebar_app_info:name(AppInfo), Dir]),
  14. State1 = rebar_state:current_app(State, AppInfo),
  15. State2 = run_provider_hooks(Dir, Type, Command, Providers, rebar_app_info:opts(AppInfo), State1),
  16. run_hooks(Dir, Type, Command, rebar_app_info:opts(AppInfo), State1),
  17. rebar_state:current_app(State2).
  18. run_all_hooks(Dir, Type, Command, Providers, State) ->
  19. ?DEBUG("Running hooks for ~p with configuration:", [Command]),
  20. run_provider_hooks(Dir, Type, Command, Providers, rebar_state:opts(State), State),
  21. run_hooks(Dir, Type, Command, rebar_state:opts(State), State).
  22. run_project_and_app_hooks(Dir, Type, Command, Providers, State) ->
  23. ProjectApps = rebar_state:project_apps(State),
  24. ?DEBUG("Running app-specific hooks", []),
  25. [rebar_hooks:run_all_hooks(Dir, Type, Command, Providers, AppInfo, State) || AppInfo <- ProjectApps],
  26. ?DEBUG("Running project-wide hooks", []),
  27. run_all_hooks(Dir, Type, Command, Providers, State).
  28. format_error({bad_provider, Type, Command, {Name, Namespace}}) ->
  29. io_lib:format("Unable to run ~ts hooks for '~p', command '~p' in namespace '~p' not found.", [Type, Command, Namespace, Name]);
  30. format_error({bad_provider, Type, Command, Name}) ->
  31. io_lib:format("Unable to run ~ts hooks for '~p', command '~p' not found.", [Type, Command, Name]).
  32. %%%%%%%%%%%%%%%
  33. %%% PRIVATE %%%
  34. %%%%%%%%%%%%%%%
  35. run_provider_hooks(Dir, Type, Command, Providers, Opts, State) ->
  36. case rebar_opts:get(Opts, provider_hooks, []) of
  37. [] ->
  38. State;
  39. AllHooks ->
  40. TypeHooks = proplists:get_value(Type, AllHooks, []),
  41. run_provider_hooks_(Dir, Type, Command, Providers, TypeHooks, rebar_state:opts(State, Opts))
  42. end.
  43. run_provider_hooks_(_Dir, _Type, _Command, _Providers, [], State) ->
  44. State;
  45. run_provider_hooks_(Dir, Type, Command, Providers, TypeHooks, State) ->
  46. case proplists:get_all_values(Command, TypeHooks) of
  47. [] ->
  48. ?DEBUG("\t{provider_hooks, []}.", []),
  49. State;
  50. HookProviders ->
  51. rebar_paths:set_paths([plugins], State),
  52. Providers1 = rebar_state:providers(State),
  53. State1 = rebar_state:providers(rebar_state:dir(State, Dir), Providers++Providers1),
  54. ?DEBUG("\t{provider_hooks, [{~p, ~p}]}.",
  55. [Type, HookProviders]),
  56. case rebar_core:do(HookProviders, State1) of
  57. {error, ProviderName} ->
  58. ?DEBUG(format_error({bad_provider, Type, Command, ProviderName}), []),
  59. throw(?PRV_ERROR({bad_provider, Type, Command, ProviderName}));
  60. {ok, State2} ->
  61. rebar_paths:set_paths([deps], State2),
  62. State2
  63. end
  64. end.
  65. run_hooks(Dir, pre, Command, Opts, State) ->
  66. run_hooks(Dir, pre_hooks, Command, Opts, State);
  67. run_hooks(Dir, post, Command, Opts, State) ->
  68. run_hooks(Dir, post_hooks, Command, Opts, State);
  69. run_hooks(Dir, Type, Command, Opts, State) ->
  70. case rebar_opts:get(Opts, Type, []) of
  71. [] ->
  72. ?DEBUG("\t{~p, []}.", [Type]),
  73. ?DIAGNOSTIC("run_hooks(~p, ~p, ~p) -> no hooks defined\n", [Dir, Type, Command]),
  74. ok;
  75. Hooks ->
  76. Env = rebar_env:create_env(State, Opts),
  77. CommandHooks = lists:filter(
  78. fun({_, C, _}) when C =:= Command -> true;
  79. ({C, _}) when C =:= Command -> true;
  80. (_) -> false
  81. end,
  82. Hooks
  83. ),
  84. ?DEBUG("\t{~p, ~p}.",
  85. [Type, CommandHooks]),
  86. lists:foreach(fun(Hook) -> apply_hook(Dir, Env, Hook) end, CommandHooks)
  87. end.
  88. apply_hook(Dir, Env, {Arch, Command, Hook}) ->
  89. case rebar_utils:is_arch(Arch) of
  90. true ->
  91. apply_hook(Dir, Env, {Command, Hook});
  92. false ->
  93. ok
  94. end;
  95. apply_hook(Dir, Env, {Command, Hook}) ->
  96. Msg = lists:flatten(io_lib:format("Hook for ~p failed!~n", [Command])),
  97. rebar_utils:sh(Hook, [use_stdout, {cd, Dir}, {env, Env}, {abort_on_error, Msg}]).