From 459ff732a3e06b060517152f7b5e2fa65f6680e7 Mon Sep 17 00:00:00 2001
From: Tristan Sloughter <t@crashfast.com>
Date: Sat, 4 Apr 2015 09:59:16 -0500
Subject: install dep plugins & run provider hooks the same as shell hooks

---
 src/rebar_core.erl             |  2 +-
 src/rebar_hooks.erl            | 27 ++++++++++++++++++++++++---
 src/rebar_plugins.erl          | 27 +++++++++++++++++----------
 src/rebar_prv_clean.erl        | 15 ++++++++-------
 src/rebar_prv_compile.erl      | 22 +++++++++++++---------
 src/rebar_prv_install_deps.erl |  5 ++++-
 6 files changed, 67 insertions(+), 31 deletions(-)

(limited to 'src')

diff --git a/src/rebar_core.erl b/src/rebar_core.erl
index 6abab68..7fe7332 100644
--- a/src/rebar_core.erl
+++ b/src/rebar_core.erl
@@ -26,7 +26,7 @@
 %% -------------------------------------------------------------------
 -module(rebar_core).
 
--export([init_command/2, process_namespace/2, process_command/2]).
+-export([init_command/2, process_namespace/2, process_command/2, do/2]).
 
 -include("rebar.hrl").
 
diff --git a/src/rebar_hooks.erl b/src/rebar_hooks.erl
index 706d6b9..e144a8e 100644
--- a/src/rebar_hooks.erl
+++ b/src/rebar_hooks.erl
@@ -1,9 +1,30 @@
 -module(rebar_hooks).
 
--export([run_compile_hooks/4]).
+-export([run_all_hooks/5]).
 
-run_compile_hooks(Dir, Type, Command, State) ->
-    Hooks = rebar_state:get(State, Type, []),
+-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) ->
+    State1 = rebar_state:providers(rebar_state:dir(State, Dir), Providers),
+    AllHooks = rebar_state:get(State1, provider_hooks, []),
+    TypeHooks = proplists:get_value(Type, AllHooks, []),
+    HookProviders = proplists:get_all_values(Command, TypeHooks),
+    rebar_core:do(HookProviders, State1).
+
+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 = [{"REBAR_DEPS_DIR", filename:absname(rebar_dir:deps_dir(State))}],
     lists:foreach(fun({_, C, _}=Hook) when C =:= Command ->
                           apply_hook(Dir, Env, Hook);
diff --git a/src/rebar_plugins.erl b/src/rebar_plugins.erl
index 5a0ca3c..45321e8 100644
--- a/src/rebar_plugins.erl
+++ b/src/rebar_plugins.erl
@@ -12,17 +12,28 @@
 %% ===================================================================
 
 install(State) ->
+    DepsDir = rebar_dir:deps_dir(State),
     %% Set deps_dir to a different dir for plugin so they don't collide
     OldDepsDir = rebar_state:get(State, deps_dir, ?DEFAULT_DEPS_DIR),
     State1 = rebar_state:set(State, deps_dir, ?DEFAULT_PLUGINS_DIR),
-    DepsDir = rebar_dir:deps_dir(State1),
-    expand_plugins(DepsDir),
     Plugins = rebar_state:get(State1, plugins, []),
+
+    ProjectApps = rebar_state:project_apps(State),
+    DepApps = rebar_app_discover:find_apps([DepsDir], all),
+
+    OtherPlugins = lists:flatmap(fun(App) ->
+                                         AppDir = rebar_app_info:dir(App),
+                                         C = rebar_config:consult(AppDir),
+                                         S = rebar_state:new(rebar_state:new(), C, AppDir),
+                                         rebar_state:get(S, plugins, [])
+                                 end, ProjectApps++DepApps),
+
     PluginProviders = lists:flatten(rebar_utils:filtermap(fun(Plugin) ->
                                                                   handle_plugin(Plugin, State1)
-                                                          end, Plugins)),
+                                                          end, Plugins++OtherPlugins)),
 
     State2 = rebar_state:set(State1, deps_dir, OldDepsDir),
+
     {ok, PluginProviders, State2}.
 
 -spec handle_plugin(rebar_prv_install_deps:dep(), rebar_state:t()) -> {true, any()} | false.
@@ -37,7 +48,7 @@ handle_plugin(Plugin, State) ->
     catch
         C:T ->
             ?DEBUG("~p ~p", [C, T]),
-            ?WARN("Plugin ~p not available. It will not be used.~n", [Plugin]),
+            ?WARN("Plugin ~p not available. It will not be used.", [Plugin]),
             false
     end.
 
@@ -56,7 +67,7 @@ plugin_providers(Plugin) when is_atom(Plugin) ->
     validate_plugin(Plugin).
 
 validate_plugin(Plugin) ->
-    ok = application:load(Plugin),
+    _ = application:load(Plugin),
     case application:get_env(Plugin, providers) of
         {ok, Providers} ->
             {true, Providers};
@@ -64,13 +75,9 @@ validate_plugin(Plugin) ->
             Exports = Plugin:module_info(exports),
             case lists:member({init,1}, Exports) of
                 false ->
-                    ?WARN("Plugin ~p does not export init/1. It will not be used.~n", [Plugin]),
+                    ?WARN("Plugin ~p does not export init/1. It will not be used.", [Plugin]),
                     false;
                 true ->
                     {true, Plugin}
             end
     end.
-
-expand_plugins(Dir) ->
-    Apps = filelib:wildcard(filename:join([Dir, "*", "ebin"])),
-    ok = code:add_pathsa(Apps).
diff --git a/src/rebar_prv_clean.erl b/src/rebar_prv_clean.erl
index 0da286b..5bc1552 100644
--- a/src/rebar_prv_clean.erl
+++ b/src/rebar_prv_clean.erl
@@ -32,6 +32,7 @@ init(State) ->
 
 -spec do(rebar_state:t()) -> {ok, rebar_state:t()} | {error, string()}.
 do(State) ->
+    Providers = rebar_state:providers(State),
     ProjectApps = rebar_state:project_apps(State),
     {all, All} = handle_args(State),
 
@@ -46,12 +47,12 @@ do(State) ->
     %% Need to allow global config vars used on deps
     %% Right now no way to differeniate and just give deps a new state
     EmptyState = rebar_state:new(),
-    clean_apps(EmptyState, DepApps),
+    clean_apps(EmptyState, Providers, DepApps),
 
     Cwd = rebar_dir:get_cwd(),
-    rebar_hooks:run_compile_hooks(Cwd, pre_hooks, clean, State),
-    clean_apps(State, ProjectApps),
-    rebar_hooks:run_compile_hooks(Cwd, post_hooks, clean, State),
+    rebar_hooks:run_all_hooks(Cwd, pre, clean, Providers, State),
+    clean_apps(State, Providers, ProjectApps),
+    rebar_hooks:run_all_hooks(Cwd, post, clean, Providers, State),
 
     {ok, State}.
 
@@ -63,7 +64,7 @@ format_error(Reason) ->
 %% Internal functions
 %% ===================================================================
 
-clean_apps(State, Apps) ->
+clean_apps(State, Providers, Apps) ->
     lists:foreach(fun(AppInfo) ->
                           AppDir = rebar_app_info:dir(AppInfo),
                           C = rebar_config:consult(AppDir),
@@ -71,9 +72,9 @@ clean_apps(State, Apps) ->
 
                           ?INFO("Cleaning out ~s...", [rebar_app_info:name(AppInfo)]),
                           %% Legacy hook support
-                          rebar_hooks:run_compile_hooks(AppDir, pre_hooks, clean, S),
+                          rebar_hooks:run_all_hooks(AppDir, pre, clean, Providers, S),
                           rebar_erlc_compiler:clean(State, rebar_app_info:out_dir(AppInfo)),
-                          rebar_hooks:run_compile_hooks(AppDir, post_hooks, clean, S)
+                          rebar_hooks:run_all_hooks(AppDir, post, clean, Providers, S)
                   end, Apps).
 
 handle_args(State) ->
diff --git a/src/rebar_prv_compile.erl b/src/rebar_prv_compile.erl
index 0b70f22..c79403d 100644
--- a/src/rebar_prv_compile.erl
+++ b/src/rebar_prv_compile.erl
@@ -32,20 +32,23 @@ init(State) ->
 -spec do(rebar_state:t()) -> {ok, rebar_state:t()} | {error, string()}.
 do(State) ->
     ProjectApps = rebar_state:project_apps(State),
+    Providers = rebar_state:providers(State),
     Deps = rebar_state:deps_to_build(State),
     Cwd = rebar_dir:get_cwd(),
-    rebar_hooks:run_compile_hooks(Cwd, pre_hooks, compile, State),
+
+    rebar_hooks:run_all_hooks(Cwd, pre, compile, Providers, State),
 
     %% Need to allow global config vars used on deps
     %% Right now no way to differeniate and just give deps a new state
     EmptyState = rebar_state:new(),
-    build_apps(EmptyState, Deps),
+    build_apps(EmptyState, Providers, Deps),
 
     %% Use the project State for building project apps
     %% Set hooks to empty so top-level hooks aren't run for each project app
     State2 = rebar_state:set(rebar_state:set(State, post_hooks, []), pre_hooks, []),
-    ProjectApps1 = build_apps(State2, ProjectApps),
-    rebar_hooks:run_compile_hooks(Cwd, post_hooks, compile, State),
+    ProjectApps1 = build_apps(State2, Providers, ProjectApps),
+
+    rebar_hooks:run_all_hooks(Cwd, post, compile, Providers, State),
 
     {ok, rebar_state:project_apps(State, ProjectApps1)}.
 
@@ -53,10 +56,10 @@ do(State) ->
 format_error(Reason) ->
     io_lib:format("~p", [Reason]).
 
-build_apps(State, Apps) ->
-    [build_app(State, AppInfo) || AppInfo <- Apps].
+build_apps(State, Providers, Apps) ->
+    [build_app(State, Providers, AppInfo) || AppInfo <- Apps].
 
-build_app(State, AppInfo) ->
+build_app(State, Providers, AppInfo) ->
     AppDir = rebar_app_info:dir(AppInfo),
     OutDir = rebar_app_info:out_dir(AppInfo),
 
@@ -71,9 +74,10 @@ build_app(State, AppInfo) ->
         end,
 
     %% Legacy hook support
-    rebar_hooks:run_compile_hooks(AppDir, pre_hooks, compile, S),
+
+    rebar_hooks:run_all_hooks(AppDir, pre, compile,  Providers, S),
     AppInfo1 = compile(S, AppInfo),
-    rebar_hooks:run_compile_hooks(AppDir, post_hooks, compile, S),
+    rebar_hooks:run_all_hooks(AppDir, post, compile, Providers, S),
 
     true = code:add_patha(rebar_app_info:ebin_dir(AppInfo1)),
     AppInfo1.
diff --git a/src/rebar_prv_install_deps.erl b/src/rebar_prv_install_deps.erl
index e92a3f0..8d07cd3 100644
--- a/src/rebar_prv_install_deps.erl
+++ b/src/rebar_prv_install_deps.erl
@@ -85,7 +85,10 @@ do(State) ->
             no_cycle ->
                 case compile_order(Source, ProjectApps) of
                     {ok, ToCompile} ->
-                        {ok, rebar_state:deps_to_build(State1, ToCompile)};
+                        %% Deps may have plugins to install. Find and intall here.
+                        {ok, PluginProviders, State2} = rebar_plugins:install(State1),
+                        State3 = rebar_state:create_logic_providers(PluginProviders, State2),
+                        {ok, rebar_state:deps_to_build(State3, ToCompile)};
                     {error, Error} ->
                         {error, Error}
                 end
-- 
cgit v1.1