|
-module(rebar_hooks).
|
|
|
|
-export([run_all_hooks/5
|
|
,format_error/1]).
|
|
|
|
-include_lib("providers/include/providers.hrl").
|
|
|
|
-spec run_all_hooks(file:filename_all(), pre | post,
|
|
atom() | {atom(), atom()} | string(),
|
|
[providers:t()], rebar_state:t()) -> ok.
|
|
run_all_hooks(Dir, Type, Command, Providers, State) ->
|
|
run_provider_hooks(Dir, Type, Command, Providers, State),
|
|
run_hooks(Dir, Type, Command, State).
|
|
|
|
run_provider_hooks(Dir, Type, Command, Providers, State) ->
|
|
PluginDepsPaths = rebar_state:code_paths(State, all_plugin_deps),
|
|
code:add_pathsa(PluginDepsPaths),
|
|
Providers1 = rebar_state:providers(State),
|
|
State1 = rebar_state:providers(rebar_state:dir(State, Dir), Providers++Providers1),
|
|
AllHooks = rebar_state:get(State1, provider_hooks, []),
|
|
TypeHooks = proplists:get_value(Type, AllHooks, []),
|
|
HookProviders = proplists:get_all_values(Command, TypeHooks),
|
|
|
|
case rebar_core:do(HookProviders, State1) of
|
|
{error, ProviderName} ->
|
|
throw(?PRV_ERROR({bad_provider, Type, Command, ProviderName}));
|
|
{ok, _} ->
|
|
rebar_utils:remove_from_code_path(PluginDepsPaths)
|
|
end.
|
|
|
|
format_error({bad_provider, Type, Command, {Name, Namespace}}) ->
|
|
io_lib:format("Unable to run ~s hooks for '~p', command '~p' in namespace '~p' not found.", [Type, Command, Namespace, Name]);
|
|
format_error({bad_provider, Type, Command, Name}) ->
|
|
io_lib:format("Unable to run ~s hooks for '~p', command '~p' not found.", [Type, Command, Name]).
|
|
|
|
%% @doc The following environment variables are exported when running
|
|
%% a hook (absolute paths):
|
|
%%
|
|
%% REBAR_DEPS_DIR = rebar_dir:deps_dir/1
|
|
%% REBAR_BUILD_DIR = rebar_dir:base_dir/1
|
|
%% REBAR_ROOT_DIR = rebar_dir:root_dir/1
|
|
%% REBAR_CHECKOUTS_DIR = rebar_dir:checkouts_dir/1
|
|
%% REBAR_PLUGINS_DIR = rebar_dir:plugins_dir/1
|
|
%% REBAR_GLOBAL_CONFIG_DIR = rebar_dir:global_config_dir/1
|
|
%% REBAR_GLOBAL_CACHE_DIR = rebar_dir:global_cache_dir/1
|
|
%% REBAR_TEMPLATE_DIR = rebar_dir:template_dir/1
|
|
%% REBAR_APP_DIRS = rebar_dir:lib_dirs/1
|
|
%% REBAR_SRC_DIRS = rebar_dir:src_dirs/1
|
|
%%
|
|
%% autoconf compatible variables
|
|
%% (see: http://www.gnu.org/software/autoconf/manual/autoconf.html#Erlang-Libraries):
|
|
%% ERLANG_ERTS_VER = erlang:system_info(version)
|
|
%% ERLANG_ROOT_DIR = code:root_dir/0
|
|
%% ERLANG_LIB_DIR_erl_interface = code:lib_dir(erl_interface)
|
|
%% ERLANG_LIB_VER_erl_interface = version part of path returned by code:lib_dir(erl_interface)
|
|
%% ERL = ERLANG_ROOT_DIR/bin/erl
|
|
%% ERLC = ERLANG_ROOT_DIR/bin/erl
|
|
%%
|
|
run_hooks(Dir, Type, Command, State) ->
|
|
Hooks = case Type of
|
|
pre ->
|
|
rebar_state:get(State, pre_hooks, []);
|
|
post ->
|
|
rebar_state:get(State, post_hooks, []);
|
|
_ ->
|
|
[]
|
|
end,
|
|
Env = create_env(State),
|
|
lists:foreach(fun({_, C, _}=Hook) when C =:= Command ->
|
|
apply_hook(Dir, Env, Hook);
|
|
({C, _}=Hook) when C =:= Command ->
|
|
apply_hook(Dir, Env, Hook);
|
|
(_) ->
|
|
continue
|
|
end, Hooks).
|
|
|
|
apply_hook(Dir, Env, {Arch, Command, Hook}) ->
|
|
case rebar_utils:is_arch(Arch) of
|
|
true ->
|
|
apply_hook(Dir, Env, {Command, Hook});
|
|
false ->
|
|
ok
|
|
end;
|
|
apply_hook(Dir, Env, {Command, Hook}) ->
|
|
Msg = lists:flatten(io_lib:format("Hook for ~p failed!~n", [Command])),
|
|
rebar_utils:sh(Hook, [use_stdout, {cd, Dir}, {env, Env}, {abort_on_error, Msg}]).
|
|
|
|
create_env(State) ->
|
|
BaseDir = rebar_state:dir(State),
|
|
[
|
|
{"REBAR_DEPS_DIR", filename:absname(rebar_dir:deps_dir(State))},
|
|
{"REBAR_BUILD_DIR", filename:absname(rebar_dir:base_dir(State))},
|
|
{"REBAR_ROOT_DIR", filename:absname(rebar_dir:root_dir(State))},
|
|
{"REBAR_CHECKOUTS_DIR", filename:absname(rebar_dir:checkouts_dir(State))},
|
|
{"REBAR_PLUGINS_DIR", filename:absname(rebar_dir:plugins_dir(State))},
|
|
{"REBAR_GLOBAL_CONFIG_DIR", filename:absname(rebar_dir:global_config_dir(State))},
|
|
{"REBAR_GLOBAL_CACHE_DIR", filename:absname(rebar_dir:global_cache_dir(State))},
|
|
{"REBAR_TEMPLATE_DIR", filename:absname(rebar_dir:template_dir(State))},
|
|
{"REBAR_APP_DIRS", join_dirs(BaseDir, rebar_dir:lib_dirs(State))},
|
|
{"REBAR_SRC_DIRS", join_dirs(BaseDir, rebar_dir:all_src_dirs(State))},
|
|
{"ERLANG_ERTS_VER", erlang:system_info(version)},
|
|
{"ERLANG_ROOT_DIR", code:root_dir()},
|
|
{"ERLANG_LIB_DIR_erl_interface", code:lib_dir(erl_interface)},
|
|
{"ERLANG_LIB_VER_erl_interface", re_version(code:lib_dir(erl_interface))},
|
|
{"ERL", filename:join([code:root_dir(), "bin", "erl"])},
|
|
{"ERLC", filename:join([code:root_dir(), "bin", "erlc"])}
|
|
].
|
|
|
|
join_dirs(BaseDir, Dirs) ->
|
|
string:join([ filename:join(BaseDir, Dir) || Dir <- Dirs ], ":").
|
|
|
|
re_version(Path) ->
|
|
case re:run(Path, "^.*-(?<VER>[^/-]*)$", [{capture, [1], list}]) of
|
|
nomatch -> "";
|
|
{match, [Ver]} -> Ver
|
|
end.
|