summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFred Hebert <mononcqc@ferd.ca>2015-04-05 10:23:43 -0400
committerFred Hebert <mononcqc@ferd.ca>2015-04-05 10:23:43 -0400
commit3250faa75683bdbfc521c4e8c6772f45d6d2e863 (patch)
tree869b863aff8062d78042d27ef62f9236c3a4559f
parenta99344a47066dd26b02cf34e84c15aa2f6f4dbe5 (diff)
parent79e2d6006c989a241d4599d048ff39f094f9e886 (diff)
Merge pull request #320 from tsloughter/dep_plugins
install dep plugins & run provider hooks the same as shell hooks (Rereopen 316)
-rw-r--r--src/rebar.app.src4
-rw-r--r--src/rebar3.erl24
-rw-r--r--src/rebar_core.erl2
-rw-r--r--src/rebar_fetch.erl43
-rw-r--r--src/rebar_hooks.erl27
-rw-r--r--src/rebar_plugins.erl59
-rw-r--r--src/rebar_prv_clean.erl15
-rw-r--r--src/rebar_prv_common_test.erl16
-rw-r--r--src/rebar_prv_compile.erl22
-rw-r--r--src/rebar_prv_deps.erl6
-rw-r--r--src/rebar_prv_eunit.erl15
-rw-r--r--src/rebar_prv_install_deps.erl15
-rw-r--r--src/rebar_prv_lock.erl2
-rw-r--r--src/rebar_state.erl70
-rw-r--r--test/mock_git_resource.erl3
-rw-r--r--test/rebar_compile_SUITE.erl36
-rw-r--r--test/rebar_resource_SUITE.erl8
-rw-r--r--test/rebar_test_utils.erl15
18 files changed, 234 insertions, 148 deletions
diff --git a/src/rebar.app.src b/src/rebar.app.src
index ee4bfd7..eada93b 100644
--- a/src/rebar.app.src
+++ b/src/rebar.app.src
@@ -23,6 +23,10 @@
%% Default log level
{log_level, warn},
+ {resources, [{git, rebar_git_resource},
+ {pkg, rebar_pkg_resource},
+ {hg, rebar_hg_resource}]},
+
{providers, [rebar_prv_app_discovery,
rebar_prv_as,
rebar_prv_clean,
diff --git a/src/rebar3.erl b/src/rebar3.erl
index 87258aa..461206d 100644
--- a/src/rebar3.erl
+++ b/src/rebar3.erl
@@ -77,7 +77,7 @@ run(BaseState, Commands) ->
_ = application:load(rebar),
BaseState1 = rebar_state:set(BaseState, task, Commands),
BaseState2 = rebar_state:set(BaseState1, caller, api),
- run_aux(BaseState2, [], Commands).
+ run_aux(BaseState2, Commands).
%% ====================================================================
%% Internal functions
@@ -86,7 +86,7 @@ run(BaseState, Commands) ->
run(RawArgs) ->
_ = application:load(rebar),
- {GlobalPluginProviders, BaseState} = init_config(),
+ BaseState = init_config(),
BaseState1 = rebar_state:set(BaseState, caller, command_line),
case erlang:system_info(version) of
@@ -98,9 +98,9 @@ run(RawArgs) ->
end,
{BaseState2, _Args1} = set_options(BaseState1, {[], []}),
- run_aux(BaseState2, GlobalPluginProviders, RawArgs).
+ run_aux(BaseState2, RawArgs).
-run_aux(State, GlobalPluginProviders, RawArgs) ->
+run_aux(State, RawArgs) ->
%% Make sure crypto is running
case crypto:start() of
ok -> ok;
@@ -124,16 +124,17 @@ run_aux(State, GlobalPluginProviders, RawArgs) ->
filename:join(filename:absname(rebar_state:dir(State2)), BaseDir)),
{ok, Providers} = application:get_env(rebar, providers),
- {ok, PluginProviders, State4} = rebar_plugins:install(State3),
+ {ok, Resources} = application:get_env(rebar, resources),
+ State4 = rebar_state:resources(State3, Resources),
+ State5 = rebar_plugins:install(State4),
%% Providers can modify profiles stored in opts, so set default after initializing providers
- AllProviders = Providers++PluginProviders++GlobalPluginProviders,
- State5 = rebar_state:create_logic_providers(AllProviders, State4),
- State6 = rebar_state:default(State5, rebar_state:opts(State5)),
+ State6 = rebar_state:create_logic_providers(Providers, State5),
+ State7 = rebar_state:default(State6, rebar_state:opts(State6)),
{Task, Args} = parse_args(RawArgs),
- rebar_core:init_command(rebar_state:command_args(State6, Args), Task).
+ rebar_core:init_command(rebar_state:command_args(State7, Args), Task).
init_config() ->
%% Initialize logging system
@@ -156,10 +157,9 @@ init_config() ->
?DEBUG("Load global config file ~p",
[GlobalConfigFile]),
GlobalConfig = rebar_state:new(global, rebar_config:consult_file(GlobalConfigFile)),
- {ok, PluginProviders, GlobalConfig1} = rebar_plugins:install(GlobalConfig),
+ GlobalConfig1 = rebar_plugins:install(GlobalConfig),
rebar_state:new(GlobalConfig1, Config1);
false ->
- PluginProviders = [],
rebar_state:new(Config1)
end,
@@ -175,7 +175,7 @@ init_config() ->
%% TODO: Do we need this still? I think it may still be used.
%% Initialize vsn cache
- {PluginProviders, rebar_state:set(State1, vsn_cache, dict:new())}.
+ rebar_state:set(State1, vsn_cache, dict:new()).
parse_args([]) ->
parse_args(["help"]);
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_fetch.erl b/src/rebar_fetch.erl
index b2ad211..20bf46b 100644
--- a/src/rebar_fetch.erl
+++ b/src/rebar_fetch.erl
@@ -7,30 +7,28 @@
%% -------------------------------------------------------------------
-module(rebar_fetch).
--export([lock_source/2,
+-export([lock_source/3,
download_source/3,
- needs_update/2]).
+ needs_update/3]).
-export([format_error/1]).
-include("rebar.hrl").
-include_lib("providers/include/providers.hrl").
-%% map short versions of resources to module names
--define(RESOURCES, [{git, rebar_git_resource}, {pkg, rebar_pkg_resource},
- {hg, rebar_hg_resource}]).
-
--spec lock_source(file:filename_all(), rebar_resource:resource()) ->
+-spec lock_source(file:filename_all(), rebar_resource:resource(), rebar_state:t()) ->
rebar_resource:resource() | {error, string()}.
-lock_source(AppDir, Source) ->
- Module = get_resource_type(Source),
+lock_source(AppDir, Source, State) ->
+ Resources = rebar_state:resources(State),
+ Module = get_resource_type(Source, Resources),
Module:lock(AppDir, Source).
-spec download_source(file:filename_all(), rebar_resource:resource(), rebar_state:t()) ->
true | {error, any()}.
download_source(AppDir, Source, State) ->
try
- Module = get_resource_type(Source),
+ Resources = rebar_state:resources(State),
+ Module = get_resource_type(Source, Resources),
TmpDir = ec_file:insecure_mkdtemp(),
AppDir1 = ec_cnv:to_list(AppDir),
case Module:download(TmpDir, Source, State) of
@@ -64,9 +62,10 @@ download_source(AppDir, Source, State) ->
throw(?PRV_ERROR({fetch_fail, Source}))
end.
--spec needs_update(file:filename_all(), rebar_resource:resource()) -> boolean() | {error, string()}.
-needs_update(AppDir, Source) ->
- Module = get_resource_type(Source),
+-spec needs_update(file:filename_all(), rebar_resource:resource(), rebar_state:t()) -> boolean() | {error, string()}.
+needs_update(AppDir, Source, State) ->
+ Resources = rebar_state:resources(State),
+ Module = get_resource_type(Source, Resources),
try
Module:needs_update(AppDir, Source)
catch
@@ -77,17 +76,17 @@ needs_update(AppDir, Source) ->
format_error({fetch_fail, Source}) ->
io_lib:format("Failed to fetch and copy dep: ~p", [Source]).
-get_resource_type({Type, Location}) ->
- find_resource_module(Type, Location);
-get_resource_type({Type, Location, _}) ->
- find_resource_module(Type, Location);
-get_resource_type({Type, _, _, Location}) ->
- find_resource_module(Type, Location);
-get_resource_type(_) ->
+get_resource_type({Type, Location}, Resources) ->
+ find_resource_module(Type, Location, Resources);
+get_resource_type({Type, Location, _}, Resources) ->
+ find_resource_module(Type, Location, Resources);
+get_resource_type({Type, _, _, Location}, Resources) ->
+ find_resource_module(Type, Location, Resources);
+get_resource_type(_, _) ->
rebar_pkg_resource.
-find_resource_module(Type, Location) ->
- case lists:keyfind(Type, 1, ?RESOURCES) of
+find_resource_module(Type, Location, Resources) ->
+ case lists:keyfind(Type, 1, Resources) of
false ->
case code:which(Type) of
non_existing ->
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..a9550ff 100644
--- a/src/rebar_plugins.erl
+++ b/src/rebar_plugins.erl
@@ -3,7 +3,7 @@
-module(rebar_plugins).
--export([install/1]).
+-export([install/1, handle_plugins/2]).
-include("rebar.hrl").
@@ -11,34 +11,45 @@
%% Public API
%% ===================================================================
+-spec install(rebar_state:t()) -> rebar_state:t().
install(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, []),
- PluginProviders = lists:flatten(rebar_utils:filtermap(fun(Plugin) ->
- handle_plugin(Plugin, State1)
- end, Plugins)),
+ DepsDir = rebar_dir:deps_dir(State),
+ Plugins = rebar_state:get(State, plugins, []),
- State2 = rebar_state:set(State1, deps_dir, OldDepsDir),
- {ok, PluginProviders, State2}.
+ 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),
+
+ handle_plugins(Plugins++OtherPlugins, State).
+
+-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).
--spec handle_plugin(rebar_prv_install_deps:dep(), rebar_state:t()) -> {true, any()} | false.
handle_plugin(Plugin, State) ->
try
- {ok, _, State1} = rebar_prv_install_deps:handle_deps(default, State, [Plugin]),
+ %% 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(State1),
+ Apps = rebar_state:all_deps(State2),
ToBuild = lists:dropwhile(fun rebar_app_info:valid/1, Apps),
[build_plugin(AppInfo) || AppInfo <- ToBuild],
plugin_providers(Plugin)
catch
C:T ->
?DEBUG("~p ~p", [C, T]),
- ?WARN("Plugin ~p not available. It will not be used.~n", [Plugin]),
- false
+ ?WARN("Plugin ~p not available. It will not be used.", [Plugin]),
+ []
end.
build_plugin(AppInfo) ->
@@ -56,21 +67,17 @@ 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};
+ Providers;
undefined ->
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]),
- false;
+ ?WARN("Plugin ~p does not export init/1. It will not be used.", [Plugin]),
+ [];
true ->
- {true, Plugin}
+ [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 a0793c1..8fafe23 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, ?PROVIDER, Providers, State),
+ clean_apps(State, Providers, ProjectApps),
+ rebar_hooks:run_all_hooks(Cwd, post, ?PROVIDER, 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, ?PROVIDER, 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, ?PROVIDER, Providers, S)
end, Apps).
handle_args(State) ->
diff --git a/src/rebar_prv_common_test.erl b/src/rebar_prv_common_test.erl
index de77257..7602906 100644
--- a/src/rebar_prv_common_test.erl
+++ b/src/rebar_prv_common_test.erl
@@ -38,6 +38,11 @@ init(State) ->
-spec do(rebar_state:t()) -> {ok, rebar_state:t()} | {error, string()}.
do(State) ->
?INFO("Running Common Test suites...", []),
+ %% Run ct provider prehooks
+ Providers = rebar_state:providers(State),
+ Cwd = rebar_dir:get_cwd(),
+ rebar_hooks:run_all_hooks(Cwd, pre, ?PROVIDER, Providers, State),
+
try
case setup_ct(State) of
{error, {no_tests_specified, Opts}} ->
@@ -46,9 +51,14 @@ do(State) ->
Opts ->
Opts1 = setup_logdir(State, Opts),
?DEBUG("common test opts: ~p", [Opts1]),
- run_test(State, Opts1)
+ {ok, State1} = run_test(State, Opts1),
+ %% Run ct provider posthooks
+ rebar_hooks:run_all_hooks(Cwd, post, ?PROVIDER, Providers, State1),
+ {ok, State1}
end
- catch error:Reason -> ?PRV_ERROR(Reason)
+ catch
+ error:Reason ->
+ ?PRV_ERROR(Reason)
end.
-spec format_error(any()) -> iolist().
@@ -251,7 +261,7 @@ join(undefined, Suites) -> Suites;
join(Dir, Suites) when is_list(Dir), is_integer(hd(Dir)) ->
lists:map(fun(S) -> filename:join([Dir, S]) end, Suites);
%% multiple dirs or a bad dir argument, try to continue anyways
-join(_, Suites) -> Suites.
+join(_, Suites) -> Suites.
find_suite_dirs(Suites) ->
AllDirs = lists:map(fun(S) -> filename:dirname(filename:absname(S)) end, Suites),
diff --git a/src/rebar_prv_compile.erl b/src/rebar_prv_compile.erl
index 5053e57..a440927 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, ?PROVIDER, 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, ?PROVIDER, 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, ?PROVIDER, Providers, S),
AppInfo1 = compile(S, AppInfo),
- rebar_hooks:run_compile_hooks(AppDir, post_hooks, compile, S),
+ rebar_hooks:run_all_hooks(AppDir, post, ?PROVIDER, Providers, S),
true = code:add_patha(rebar_app_info:ebin_dir(AppInfo1)),
AppInfo1.
diff --git a/src/rebar_prv_deps.erl b/src/rebar_prv_deps.erl
index f1697b6..3627e91 100644
--- a/src/rebar_prv_deps.erl
+++ b/src/rebar_prv_deps.erl
@@ -77,7 +77,7 @@ display_dep(_State, {Name, _Vsn, Source, _Opts}) when is_tuple(Source) ->
display_dep(State, {Name, Source={pkg, _, Vsn}, Level}) when is_integer(Level) ->
DepsDir = rebar_dir:deps_dir(State),
AppDir = filename:join([DepsDir, ec_cnv:to_binary(Name)]),
- NeedsUpdate = case rebar_fetch:needs_update(AppDir, Source) of
+ NeedsUpdate = case rebar_fetch:needs_update(AppDir, Source, State) of
true -> "*";
false -> ""
end,
@@ -85,7 +85,7 @@ display_dep(State, {Name, Source={pkg, _, Vsn}, Level}) when is_integer(Level) -
display_dep(State, {Name, Source, Level}) when is_tuple(Source), is_integer(Level), element(1, Source) =:= git ->
DepsDir = rebar_dir:deps_dir(State),
AppDir = filename:join([DepsDir, ec_cnv:to_binary(Name)]),
- NeedsUpdate = case rebar_fetch:needs_update(AppDir, Source) of
+ NeedsUpdate = case rebar_fetch:needs_update(AppDir, Source, State) of
true -> "*";
false -> ""
end,
@@ -93,7 +93,7 @@ display_dep(State, {Name, Source, Level}) when is_tuple(Source), is_integer(Leve
display_dep(State, {Name, Source, Level}) when is_tuple(Source), is_integer(Level) ->
DepsDir = rebar_dir:deps_dir(State),
AppDir = filename:join([DepsDir, ec_cnv:to_binary(Name)]),
- NeedsUpdate = case rebar_fetch:needs_update(AppDir, Source) of
+ NeedsUpdate = case rebar_fetch:needs_update(AppDir, Source, State) of
true -> "*";
false -> ""
end,
diff --git a/src/rebar_prv_eunit.erl b/src/rebar_prv_eunit.erl
index 371d205..3e57fb0 100644
--- a/src/rebar_prv_eunit.erl
+++ b/src/rebar_prv_eunit.erl
@@ -37,9 +37,19 @@ init(State) ->
-spec do(rebar_state:t()) -> {ok, rebar_state:t()} | {error, string()}.
do(State) ->
?INFO("Performing EUnit tests...", []),
+ %% Run eunit provider prehooks
+ Providers = rebar_state:providers(State),
+ Cwd = rebar_dir:get_cwd(),
+ rebar_hooks:run_all_hooks(Cwd, pre, ?PROVIDER, Providers, State),
+
case prepare_tests(State) of
- {ok, Tests} -> do_tests(State, Tests);
- Error -> Error
+ {ok, Tests} ->
+ {ok, State1} = do_tests(State, Tests),
+ %% Run eunit provider posthooks
+ rebar_hooks:run_all_hooks(Cwd, post, ?PROVIDER, Providers, State1),
+ {ok, State1};
+ Error ->
+ Error
end.
do_tests(State, Tests) ->
@@ -250,4 +260,3 @@ help(app) -> "List of application test suites to run";
help(cover) -> "Generate cover data";
help(suite) -> "List of test suites to run";
help(verbose) -> "Verbose output".
-
diff --git a/src/rebar_prv_install_deps.erl b/src/rebar_prv_install_deps.erl
index e92a3f0..db2b036 100644
--- a/src/rebar_prv_install_deps.erl
+++ b/src/rebar_prv_install_deps.erl
@@ -336,13 +336,13 @@ handle_upgrade(AppInfo, SrcDeps, PkgDeps, SrcApps, Level, State, Locks) ->
handle_dep(AppInfo, SrcDeps, PkgDeps, SrcApps, Level, State, Locks) ->
DepsDir = rebar_dir:deps_dir(State),
- {AppInfo1, NewSrcDeps, NewPkgDeps, NewLocks} =
+ {AppInfo1, NewSrcDeps, NewPkgDeps, NewLocks, State1} =
handle_dep(State, DepsDir, AppInfo, Locks, Level),
AppInfo2 = rebar_app_info:dep_level(AppInfo1, Level),
{NewSrcDeps ++ SrcDeps
,NewPkgDeps++PkgDeps
,[AppInfo2 | SrcApps]
- ,State
+ ,State1
,NewLocks}.
-spec handle_dep(rebar_state:t(), file:filename_all(), rebar_app_info:t(), list(), integer()) ->
@@ -359,13 +359,16 @@ handle_dep(State, DepsDir, AppInfo, Locks, Level) ->
S3 = rebar_state:apply_overrides(S2, Name),
AppInfo1 = rebar_app_info:state(AppInfo, S3),
+ %% Dep may have plugins to install. Find and install here.
+ State1 = rebar_plugins:handle_plugins(rebar_state:get(S3, plugins, []), State),
+
Deps = rebar_state:get(S3, deps, []),
%% Upgrade lock level to be the level the dep will have in this dep tree
NewLocks = [{DepName, Source, LockLevel+Level} ||
{DepName, Source, LockLevel} <- rebar_state:get(S3, {locks, default}, [])],
AppInfo2 = rebar_app_info:deps(AppInfo1, rebar_state:deps_names(Deps)),
{SrcDeps, PkgDeps} = parse_deps(DepsDir, Deps, S3, Locks, Level),
- {AppInfo2, SrcDeps, PkgDeps, Locks++NewLocks}.
+ {AppInfo2, SrcDeps, PkgDeps, Locks++NewLocks, State1}.
-spec maybe_fetch(rebar_app_info:t(), boolean() | {true, binary(), integer()},
sets:set(binary()), rebar_state:t()) -> boolean().
@@ -507,12 +510,12 @@ fetch_app(AppInfo, AppDir, State) ->
Result
end.
-maybe_upgrade(AppInfo, AppDir, false, _State) ->
+maybe_upgrade(AppInfo, AppDir, false, State) ->
Source = rebar_app_info:source(AppInfo),
- rebar_fetch:needs_update(AppDir, Source);
+ rebar_fetch:needs_update(AppDir, Source, State);
maybe_upgrade(AppInfo, AppDir, true, State) ->
Source = rebar_app_info:source(AppInfo),
- case rebar_fetch:needs_update(AppDir, Source) of
+ case rebar_fetch:needs_update(AppDir, Source, State) of
true ->
?INFO("Updating ~s", [rebar_app_info:name(AppInfo)]),
case rebar_fetch:download_source(AppDir, Source, State) of
diff --git a/src/rebar_prv_lock.erl b/src/rebar_prv_lock.erl
index e839168..5536ec9 100644
--- a/src/rebar_prv_lock.erl
+++ b/src/rebar_prv_lock.erl
@@ -37,7 +37,7 @@ do(State) ->
%% If source is tuple it is a source dep
%% e.g. {git, "git://github.com/ninenines/cowboy.git", "master"}
{rebar_app_info:name(Dep)
- ,rebar_fetch:lock_source(Dir, Source)
+ ,rebar_fetch:lock_source(Dir, Source, State)
,rebar_app_info:dep_level(Dep)}
end || Dep <- AllDeps, not(rebar_app_info:is_checkout(Dep))],
Dir = rebar_state:dir(State),
diff --git a/src/rebar_state.erl b/src/rebar_state.erl
index cd127c0..68c71a9 100644
--- a/src/rebar_state.erl
+++ b/src/rebar_state.erl
@@ -30,6 +30,7 @@
overrides/1, overrides/2,
apply_overrides/2,
+ resources/1, resources/2, add_resource/2,
providers/1, providers/2, add_provider/2]).
-include("rebar.hrl").
@@ -51,6 +52,7 @@
all_deps = [] :: [rebar_app_info:t()],
overrides = [],
+ resources = [],
providers = []}).
-export_type([t/0]).
@@ -296,6 +298,18 @@ namespace(#state_t{namespace=Namespace}) ->
namespace(State=#state_t{}, Namespace) ->
State#state_t{namespace=Namespace}.
+-spec resources(t()) -> rebar_resource:resource().
+resources(#state_t{resources=Resources}) ->
+ Resources.
+
+-spec resources(t(), [rebar_resource:resource()]) -> t().
+resources(State, NewResources) ->
+ State#state_t{resources=NewResources}.
+
+-spec add_resource(t(), rebar_resource:resource()) -> t().
+add_resource(State=#state_t{resources=Resources}, Resource) ->
+ State#state_t{resources=[Resource | Resources]}.
+
providers(#state_t{providers=Providers}) ->
Providers.
@@ -308,62 +322,25 @@ add_provider(State=#state_t{providers=Providers}, Provider) ->
create_logic_providers(ProviderModules, State0) ->
try
- State1 = lists:foldl(fun(ProviderMod, StateAcc) ->
- case providers:new(ProviderMod, StateAcc) of
- {error, Reason} ->
- ?ERROR(Reason++"~n", []),
- StateAcc;
- {ok, StateAcc1} ->
- StateAcc1
- end
- end, State0, ProviderModules),
- apply_hooks(State1)
+ lists:foldl(fun(ProviderMod, StateAcc) ->
+ case providers:new(ProviderMod, StateAcc) of
+ {error, Reason} ->
+ ?ERROR(Reason++"~n", []),
+ StateAcc;
+ {ok, StateAcc1} ->
+ StateAcc1
+ end
+ end, State0, ProviderModules)
catch
C:T ->
?DEBUG("~p: ~p ~p", [C, T, erlang:get_stacktrace()]),
throw({error, "Failed creating providers. Run with DEBUG=1 for stacktrace."})
end.
-apply_hooks(State0) ->
- try
- Hooks = rebar_state:get(State0, provider_hooks, []),
- PreHooks = proplists:get_value(pre, Hooks, []),
- PostHooks = proplists:get_value(post, Hooks, []),
- State1 = lists:foldl(fun({Target, Hook}, StateAcc) ->
- prepend_hook(StateAcc, Target, Hook)
- end, State0, PreHooks),
- lists:foldl(fun({Target, Hook}, StateAcc) ->
- append_hook(StateAcc, Target, Hook)
- end, State1, PostHooks)
- catch
- C:T ->
- ?DEBUG("~p: ~p ~p", [C, T, erlang:get_stacktrace()]),
- throw({error, "Failed parsing provider hooks. Run with DEBUG=1 for stacktrace."})
- end.
-
%% ===================================================================
%% Internal functions
%% ===================================================================
-prepend_hook(State=#state_t{providers=Providers}, Target, Hook) ->
- State#state_t{providers=add_hook(pre, Providers, Target, Hook)}.
-
-append_hook(State=#state_t{providers=Providers}, Target, Hook) ->
- State#state_t{providers=add_hook(post, Providers, Target, Hook)}.
-
-add_hook(Which, Providers, Target, Hook) ->
- Provider = providers:get_provider(Target, Providers),
- Hooks = providers:hooks(Provider),
- NewHooks = add_hook(Which, Hooks, Hook),
- NewProvider = providers:hooks(Provider, NewHooks),
- [NewProvider | lists:delete(Provider, Providers)].
-
-add_hook(pre, {PreHooks, PostHooks}, Hook) ->
- {[Hook | PreHooks], PostHooks};
-add_hook(post, {PreHooks, PostHooks}, Hook) ->
- {PreHooks, [Hook | PostHooks]}.
-
-
%% Sort the list in proplist-order, meaning that `{a,b}' and `{a,c}'
%% both compare as usual, and `a' and `b' do the same, but `a' and `{a,b}' will
%% compare based on the first element of the key, and in order. So the following
@@ -425,4 +402,3 @@ umerge([], Olds, Merged, CmpMerged, Cmp) when CmpMerged == Cmp ->
lists:reverse(Olds, Merged);
umerge([], Olds, Merged, _CmpMerged, Cmp) ->
lists:reverse(Olds, [Cmp | Merged]).
-
diff --git a/test/mock_git_resource.erl b/test/mock_git_resource.erl
index 9c799fd..d8f747b 100644
--- a/test/mock_git_resource.erl
+++ b/test/mock_git_resource.erl
@@ -99,6 +99,7 @@ mock_vsn(Opts) ->
%% into a `rebar.config' file to describe dependencies.
mock_download(Opts) ->
Deps = proplists:get_value(deps, Opts, []),
+ Config = proplists:get_value(config, Opts, []),
Default = proplists:get_value(default_vsn, Opts, "0.0.0"),
Overrides = proplists:get_value(override_vsn, Opts, []),
meck:expect(
@@ -112,7 +113,7 @@ mock_download(Opts) ->
Dir, App, Vsn,
[kernel, stdlib] ++ [element(1,D) || D <- AppDeps]
),
- rebar_test_utils:create_config(Dir, [{deps, AppDeps}]),
+ rebar_test_utils:create_config(Dir, [{deps, AppDeps}]++Config),
{ok, 'WHATEVER'}
end).
diff --git a/test/rebar_compile_SUITE.erl b/test/rebar_compile_SUITE.erl
index 8564754..ede1a52 100644
--- a/test/rebar_compile_SUITE.erl
+++ b/test/rebar_compile_SUITE.erl
@@ -15,7 +15,8 @@
dont_recompile_when_opts_dont_change/1,
dont_recompile_yrl_or_xrl/1,
deps_in_path/1,
- checkout_priority/1]).
+ checkout_priority/1,
+ compile_plugins/1]).
-include_lib("common_test/include/ct.hrl").
-include_lib("eunit/include/eunit.hrl").
@@ -41,7 +42,7 @@ all() ->
build_checkout_apps, build_checkout_deps,
build_all_srcdirs,
recompile_when_opts_change, dont_recompile_when_opts_dont_change,
- dont_recompile_yrl_or_xrl, deps_in_path, checkout_priority].
+ dont_recompile_yrl_or_xrl, deps_in_path, checkout_priority, compile_plugins].
build_basic_app(Config) ->
AppDir = ?config(apps, Config),
@@ -332,3 +333,34 @@ checkout_priority(Config) ->
?assertEqual(Vsn2, proplists:get_value(vsn, DepProps)),
?assertEqual(Vsn2, proplists:get_value(vsn, PkgProps)).
+
+%% Tests that compiling a project installs and compiles the plugins of deps
+compile_plugins(Config) ->
+ AppDir = ?config(apps, Config),
+ PluginsDir = filename:join([?config(base_dir, Config), "default", "plugins"]),
+
+ Name = rebar_test_utils:create_random_name("app1_"),
+ Vsn = rebar_test_utils:create_random_vsn(),
+ rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]),
+
+ DepName = rebar_test_utils:create_random_name("dep1_"),
+ PluginName = rebar_test_utils:create_random_name("plugin1_"),
+ mock_git_resource:mock([{config, [{plugins, [
+ {list_to_atom(PluginName), Vsn}
+ ]}]}]),
+ mock_pkg_resource:mock([
+ {pkgdeps, [{{iolist_to_binary(PluginName), iolist_to_binary(Vsn)}, []}]}
+ ]),
+
+ RConfFile =
+ rebar_test_utils:create_config(AppDir,
+ [{deps, [
+ {list_to_atom(DepName), {git, "http://site.com/user/"++DepName++".git", {tag, Vsn}}}
+ ]}]),
+ {ok, RConf} = file:consult(RConfFile),
+
+ %% Build with deps.
+ rebar_test_utils:run_and_check(
+ Config, RConf, ["compile"],
+ {ok, [{app, Name}, {plugin, PluginName}, {dep, DepName}]}
+ ).
diff --git a/test/rebar_resource_SUITE.erl b/test/rebar_resource_SUITE.erl
index 95263c7..15f14db 100644
--- a/test/rebar_resource_SUITE.erl
+++ b/test/rebar_resource_SUITE.erl
@@ -12,7 +12,10 @@ groups() ->
{hg, [], [{group, all}]}].
init_per_group(all, Config) ->
- Config;
+ State = rebar_state:resources(rebar_state:new(), [{git, rebar_git_resource},
+ {pkg, rebar_pkg_resource},
+ {hg, rebar_hg_resource}]),
+ [{state, State} | Config];
init_per_group(Name, Config) ->
[{type, Name},
{resource, {Name, "https://example.org/user/app", "vsn"}} | Config].
@@ -33,4 +36,5 @@ end_per_testcase(_, Config) ->
change_type_upgrade(Config) ->
?assert(rebar_fetch:needs_update(?config(path, Config),
- ?config(resource, Config))).
+ ?config(resource, Config),
+ ?config(state, Config))).
diff --git a/test/rebar_test_utils.erl b/test/rebar_test_utils.erl
index 2eb14ac..d245c82 100644
--- a/test/rebar_test_utils.erl
+++ b/test/rebar_test_utils.erl
@@ -158,6 +158,7 @@ top_level_deps([{{Name, Vsn, Ref}, _} | Deps]) ->
%%%%%%%%%%%%%%%
check_results(AppDir, Expected) ->
BuildDirs = filelib:wildcard(filename:join([AppDir, "_build", "*", "lib"])),
+ PluginDirs = filelib:wildcard(filename:join([AppDir, "_build", "*", "plugins"])),
CheckoutsDir = filename:join([AppDir, "_checkouts"]),
LockFile = filename:join([AppDir, "rebar.lock"]),
Locks = lists:flatten(rebar_config:consult_file(LockFile)),
@@ -172,6 +173,8 @@ check_results(AppDir, Expected) ->
DepsNames = [{ec_cnv:to_list(rebar_app_info:name(App)), App} || App <- Deps],
Checkouts = rebar_app_discover:find_apps([CheckoutsDir], all),
CheckoutsNames = [{ec_cnv:to_list(rebar_app_info:name(App)), App} || App <- Checkouts],
+ Plugins = rebar_app_discover:find_apps(PluginDirs, all),
+ PluginsNames = [{ec_cnv:to_list(rebar_app_info:name(App)), App} || App <- Plugins],
lists:foreach(
fun({app, Name}) ->
@@ -213,6 +216,18 @@ check_results(AppDir, Expected) ->
?assertEqual(iolist_to_binary(Vsn),
iolist_to_binary(rebar_app_info:original_vsn(App)))
end
+ ; ({plugin, Name}) ->
+ ct:pal("Name: ~p", [Name]),
+ ?assertNotEqual(false, lists:keyfind(Name, 1, PluginsNames))
+ ; ({plugin, Name, Vsn}) ->
+ ct:pal("Name: ~p, Vsn: ~p", [Name, Vsn]),
+ case lists:keyfind(Name, 1, PluginsNames) of
+ false ->
+ error({dep_not_found, Name});
+ {Name, App} ->
+ ?assertEqual(iolist_to_binary(Vsn),
+ iolist_to_binary(rebar_app_info:original_vsn(App)))
+ end
; ({lock, Name}) ->
ct:pal("Name: ~p", [Name]),
?assertNotEqual(false, lists:keyfind(iolist_to_binary(Name), 1, Locks))