diff options
author | Fred Hebert <mononcqc@ferd.ca> | 2015-04-05 10:23:43 -0400 |
---|---|---|
committer | Fred Hebert <mononcqc@ferd.ca> | 2015-04-05 10:23:43 -0400 |
commit | 3250faa75683bdbfc521c4e8c6772f45d6d2e863 (patch) | |
tree | 869b863aff8062d78042d27ef62f9236c3a4559f | |
parent | a99344a47066dd26b02cf34e84c15aa2f6f4dbe5 (diff) | |
parent | 79e2d6006c989a241d4599d048ff39f094f9e886 (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.src | 4 | ||||
-rw-r--r-- | src/rebar3.erl | 24 | ||||
-rw-r--r-- | src/rebar_core.erl | 2 | ||||
-rw-r--r-- | src/rebar_fetch.erl | 43 | ||||
-rw-r--r-- | src/rebar_hooks.erl | 27 | ||||
-rw-r--r-- | src/rebar_plugins.erl | 59 | ||||
-rw-r--r-- | src/rebar_prv_clean.erl | 15 | ||||
-rw-r--r-- | src/rebar_prv_common_test.erl | 16 | ||||
-rw-r--r-- | src/rebar_prv_compile.erl | 22 | ||||
-rw-r--r-- | src/rebar_prv_deps.erl | 6 | ||||
-rw-r--r-- | src/rebar_prv_eunit.erl | 15 | ||||
-rw-r--r-- | src/rebar_prv_install_deps.erl | 15 | ||||
-rw-r--r-- | src/rebar_prv_lock.erl | 2 | ||||
-rw-r--r-- | src/rebar_state.erl | 70 | ||||
-rw-r--r-- | test/mock_git_resource.erl | 3 | ||||
-rw-r--r-- | test/rebar_compile_SUITE.erl | 36 | ||||
-rw-r--r-- | test/rebar_resource_SUITE.erl | 8 | ||||
-rw-r--r-- | test/rebar_test_utils.erl | 15 |
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)) |