diff options
Diffstat (limited to 'src/rebar_plugins.erl')
-rw-r--r-- | src/rebar_plugins.erl | 107 |
1 files changed, 74 insertions, 33 deletions
diff --git a/src/rebar_plugins.erl b/src/rebar_plugins.erl index c16223e..7e12324 100644 --- a/src/rebar_plugins.erl +++ b/src/rebar_plugins.erl @@ -3,7 +3,10 @@ -module(rebar_plugins). --export([install/1, handle_plugins/2]). +-export([project_apps_install/1 + ,install/1 + ,handle_plugins/3 + ,handle_plugins/4]). -include("rebar.hrl"). @@ -11,52 +14,90 @@ %% Public API %% =================================================================== +-spec project_apps_install(rebar_state:t()) -> rebar_state:t(). +project_apps_install(State) -> + Profiles = rebar_state:current_profiles(State), + ProjectApps = rebar_state:project_apps(State), + + lists:foldl(fun(Profile, StateAcc) -> + Plugins = rebar_state:get(State, {plugins, Profile}, []), + StateAcc1 = handle_plugins(Profile, Plugins, StateAcc), + + lists:foldl(fun(App, StateAcc2) -> + AppDir = rebar_app_info:dir(App), + C = rebar_config:consult(AppDir), + S = rebar_state:new(rebar_state:new(), C, AppDir), + Plugins2 = rebar_state:get(S, {plugins, Profile}, []), + handle_plugins(Profile, Plugins2, StateAcc2) + end, StateAcc1, ProjectApps) + end, State, Profiles). + -spec install(rebar_state:t()) -> rebar_state:t(). install(State) -> - Plugins = rebar_state:get(State, plugins, []), + Profiles = rebar_state:current_profiles(State), + lists:foldl(fun(Profile, StateAcc) -> + Plugins = rebar_state:get(State, {plugins, Profile}, []), + handle_plugins(Profile, Plugins, StateAcc) + end, State, Profiles). - ProjectApps = rebar_state:project_apps(State), +handle_plugins(Profile, Plugins, State) -> + handle_plugins(Profile, Plugins, State, false). - 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), +handle_plugins(Profile, Plugins, State, Upgrade) -> + %% Set deps dir to plugins dir so apps are installed there + Locks = rebar_state:lock(State), + DepsDir = rebar_state:get(State, deps_dir, ?DEFAULT_DEPS_DIR), + State1 = rebar_state:set(State, deps_dir, ?DEFAULT_PLUGINS_DIR), - handle_plugins(Plugins++OtherPlugins, State). + %% Install each plugin individually so if one fails to install it doesn't effect the others + {_PluginProviders, State2} = + lists:foldl(fun(Plugin, {PluginAcc, StateAcc}) -> + {NewPlugins, NewState} = handle_plugin(Profile, Plugin, StateAcc, Upgrade), + NewState1 = rebar_state:create_logic_providers(NewPlugins, NewState), + {PluginAcc++NewPlugins, NewState1} + end, {[], State1}, Plugins), --spec handle_plugins([rebar_prv_install_deps:dep()], rebar_state:t()) -> rebar_state:t(). -handle_plugins(Plugins, State) -> - PluginProviders = lists:flatmap(fun(Plugin) -> - handle_plugin(Plugin, State) - end, Plugins), - rebar_state:create_logic_providers(PluginProviders, State). + %% reset deps dir + State3 = rebar_state:set(State2, deps_dir, DepsDir), + rebar_state:lock(State3, Locks). -handle_plugin(Plugin, State) -> +handle_plugin(Profile, Plugin, State, Upgrade) -> try - %% Set deps dir to plugins dir so apps are installed there - State1 = rebar_state:set(State, deps_dir, ?DEFAULT_PLUGINS_DIR), - {ok, _, State2} = rebar_prv_install_deps:handle_deps(default, State1, [Plugin]), - - Apps = rebar_state:all_deps(State2), - ToBuild = lists:dropwhile(fun rebar_app_info:valid/1, Apps), - [build_plugin(AppInfo) || AppInfo <- ToBuild], - [true = code:add_patha(filename:join(rebar_app_info:dir(AppInfo), "ebin")) || AppInfo <- Apps], - plugin_providers(Plugin) + {ok, Apps, State2} = rebar_prv_install_deps:handle_deps(Profile, State, [Plugin], Upgrade), + {no_cycle, Sorted} = rebar_prv_install_deps:find_cycles(Apps), + ToBuild = rebar_prv_install_deps:cull_compile(Sorted, []), + + %% Add already built plugin deps to the code path + CodePaths = [rebar_app_info:ebin_dir(A) || A <- Apps -- ToBuild], + code:add_pathsa(CodePaths), + + %% Build plugin and its deps + [build_plugin(AppInfo, Apps, State2) || AppInfo <- ToBuild], + + %% Add newly built deps and plugin to code path + State3 = rebar_state:update_all_plugin_deps(State2, Apps), + NewCodePaths = [rebar_app_info:ebin_dir(A) || A <- ToBuild], + code:add_pathsa(CodePaths), + + %% Store plugin code paths so we can remove them when compiling project apps + State4 = rebar_state:update_code_paths(State3, all_plugin_deps, CodePaths++NewCodePaths), + + {plugin_providers(Plugin), State4} catch C:T -> - ?DEBUG("~p ~p", [C, T]), + ?DEBUG("~p ~p ~p", [C, T, erlang:get_stacktrace()]), ?WARN("Plugin ~p not available. It will not be used.", [Plugin]), - [] + {[], State} end. -build_plugin(AppInfo) -> - AppDir = rebar_app_info:dir(AppInfo), - C = rebar_config:consult(AppDir), - S = rebar_state:new(rebar_state:new(), C, AppDir), - rebar_prv_compile:compile(S, AppInfo). +build_plugin(AppInfo, Apps, State) -> + Providers = rebar_state:providers(State), + Providers1 = rebar_state:providers(rebar_app_info:state(AppInfo)), + S = rebar_state:all_deps(rebar_app_info:state_or_new(State, AppInfo), Apps), + rebar_prv_compile:compile(S, Providers++Providers1, AppInfo). +plugin_providers({Plugin, _, _, _}) when is_atom(Plugin) -> + validate_plugin(Plugin); plugin_providers({Plugin, _, _}) when is_atom(Plugin) -> validate_plugin(Plugin); plugin_providers({Plugin, _}) when is_atom(Plugin) -> |