From 8e25a45cbbc3ba796e3cb4331c15a2914fa0e644 Mon Sep 17 00:00:00 2001 From: Tristan Sloughter Date: Sun, 30 Aug 2015 13:39:38 -0500 Subject: update use of hooks and plugins with state in app_info --- src/rebar_app_info.erl | 105 ++++------------------------------------- src/rebar_app_utils.erl | 2 +- src/rebar_base_compiler.erl | 8 ++-- src/rebar_erlc_compiler.erl | 17 +++---- src/rebar_hooks.erl | 38 +++++++-------- src/rebar_prv_clean.erl | 4 +- src/rebar_prv_compile.erl | 30 +++++++----- src/rebar_prv_install_deps.erl | 6 +-- src/rebar_state.erl | 96 +++---------------------------------- src/rebar_utils.erl | 93 +++++++++++++++++++++++++++++++++++- 10 files changed, 162 insertions(+), 237 deletions(-) diff --git a/src/rebar_app_info.erl b/src/rebar_app_info.erl index 3ace5e4..1e5710f 100644 --- a/src/rebar_app_info.erl +++ b/src/rebar_app_info.erl @@ -59,9 +59,7 @@ add_to_profile/3, apply_profiles/2, deduplicate/1, - do_deduplicate/2, - merge_opts/3, - merge_opts/2]). + do_deduplicate/2]). -include("rebar.hrl"). -include_lib("providers/include/providers.hrl"). @@ -158,7 +156,7 @@ update_opts(AppInfo, Opts, Config) -> true = rebar_config:verify_config_format(Terms), LocalOpts = dict:from_list(Terms), - NewOpts = merge_opts(LocalOpts, Opts), + NewOpts = rebar_utils:merge_opts(LocalOpts, Opts), AppInfo#app_info_t{opts=NewOpts ,default=NewOpts}. @@ -425,52 +423,14 @@ all(Dir, [File|Artifacts]) -> %%%%% -apply_overrides(AppInfo, Name) -> - Overrides = rebar_app_info:get(AppInfo, overrides, []), - %Name = binary_to_atom(AppName, utf8), - - %% Inefficient. We want the order we get here though. - AppInfo1 = lists:foldl(fun({override, O}, AppInfoAcc) -> - lists:foldl(fun({deps, Value}, AppInfoAcc1) -> - rebar_app_info:set(AppInfoAcc1, {deps,default}, Value); - ({Key, Value}, AppInfoAcc1) -> - rebar_app_info:set(AppInfoAcc1, Key, Value) - end, AppInfoAcc, O); - (_, AppInfoAcc) -> - AppInfoAcc - end, AppInfo, Overrides), - - AppInfo2 = lists:foldl(fun({override, N, O}, AppInfoAcc) when N =:= Name -> - lists:foldl(fun({deps, Value}, AppInfoAcc1) -> - rebar_app_info:set(AppInfoAcc1, {deps,default}, Value); - ({Key, Value}, AppInfoAcc1) -> - rebar_app_info:set(AppInfoAcc1, Key, Value) - end, AppInfoAcc, O); - (_, AppInfoAcc) -> - AppInfoAcc - end, AppInfo1, Overrides), - - AppInfo3 = lists:foldl(fun({add, N, O}, AppInfoAcc) when N =:= Name -> - lists:foldl(fun({deps, Value}, AppInfoAcc1) -> - OldValue = rebar_app_info:get(AppInfoAcc1, {deps,default}, []), - rebar_app_info:set(AppInfoAcc1, {deps,default}, Value++OldValue); - ({Key, Value}, AppInfoAcc1) -> - OldValue = rebar_app_info:get(AppInfoAcc1, Key, []), - rebar_app_info:set(AppInfoAcc1, Key, Value++OldValue) - end, AppInfoAcc, O); - (_, AppInfoAcc) -> - AppInfoAcc - end, AppInfo2, Overrides), - - Opts = opts(AppInfo3), - AppInfo3#app_info_t{default=Opts}. +apply_overrides(Overrides, AppInfo) -> + Name = binary_to_atom(rebar_app_info:name(AppInfo), utf8), + Opts = rebar_utils:apply_overrides(opts(AppInfo), Name, Overrides), + AppInfo#app_info_t{default=Opts, opts=Opts}. add_to_profile(AppInfo, Profile, KVs) when is_atom(Profile), is_list(KVs) -> - Profiles = rebar_app_info:get(AppInfo, profiles, []), - ProfileOpts = dict:from_list(proplists:get_value(Profile, Profiles, [])), - NewOpts = merge_opts(Profile, dict:from_list(KVs), ProfileOpts), - NewProfiles = [{Profile, dict:to_list(NewOpts)}|lists:keydelete(Profile, 1, Profiles)], - rebar_app_info:set(AppInfo, profiles, NewProfiles). + Opts = rebar_utils:add_to_profile(opts(AppInfo), Profile, KVs), + AppInfo#app_info_t{opts=Opts}. apply_profiles(AppInfo, Profile) when not is_list(Profile) -> apply_profiles(AppInfo, [Profile]); @@ -496,7 +456,7 @@ apply_profiles(AppInfo=#app_info_t{default = Defaults, profiles=CurrentProfiles} case proplists:get_value(Profile, ConfigProfiles, []) of OptsList when is_list(OptsList) -> ProfileOpts = dict:from_list(OptsList), - merge_opts(Profile, ProfileOpts, OptsAcc); + rebar_utils:merge_opts(Profile, ProfileOpts, OptsAcc); Other -> throw(?PRV_ERROR({profile_not_list, Profile, Other})) end @@ -513,50 +473,3 @@ do_deduplicate([Head | Rest], Acc) -> true -> do_deduplicate(Rest, Acc); false -> do_deduplicate(Rest, [Head | Acc]) end. - -merge_opts(Profile, NewOpts, OldOpts) -> - Opts = merge_opts(NewOpts, OldOpts), - - Opts2 = case dict:find(plugins, NewOpts) of - {ok, Value} -> - dict:store({plugins, Profile}, Value, Opts); - error -> - Opts - end, - - case dict:find(deps, NewOpts) of - {ok, Value2} -> - dict:store({deps, Profile}, Value2, Opts2); - error -> - Opts2 - end. - -merge_opts(NewOpts, OldOpts) -> - dict:merge(fun(deps, _NewValue, OldValue) -> - OldValue; - ({deps, _}, NewValue, _OldValue) -> - NewValue; - (plugins, NewValue, _OldValue) -> - NewValue; - ({plugins, _}, NewValue, _OldValue) -> - NewValue; - (profiles, NewValue, OldValue) -> - dict:to_list(merge_opts(dict:from_list(NewValue), dict:from_list(OldValue))); - (_Key, NewValue, OldValue) when is_list(NewValue) -> - case io_lib:printable_list(NewValue) of - true when NewValue =:= [] -> - case io_lib:printable_list(OldValue) of - true -> - NewValue; - false -> - OldValue - end; - true -> - NewValue; - false -> - rebar_utils:tup_umerge(rebar_utils:tup_sort(NewValue) - ,rebar_utils:tup_sort(OldValue)) - end; - (_Key, NewValue, _OldValue) -> - NewValue - end, NewOpts, OldOpts). diff --git a/src/rebar_app_utils.erl b/src/rebar_app_utils.erl index 2509c7d..545ce95 100644 --- a/src/rebar_app_utils.erl +++ b/src/rebar_app_utils.erl @@ -171,7 +171,7 @@ dep_to_app(Parent, DepsDir, Name, Vsn, Source, IsLock, State) -> end, C = rebar_config:consult(rebar_app_info:dir(AppInfo)), AppInfo0 = rebar_app_info:update_opts(AppInfo, rebar_app_info:opts(AppInfo), C), - AppInfo1 = rebar_app_info:apply_overrides(AppInfo0, Name), + AppInfo1 = rebar_app_info:apply_overrides(rebar_state:get(State, overrides, []), AppInfo0), rebar_app_info:is_lock(rebar_app_info:source(AppInfo1, Source), IsLock). format_error({missing_package, Package}) -> diff --git a/src/rebar_base_compiler.erl b/src/rebar_base_compiler.erl index 7193003..31292af 100644 --- a/src/rebar_base_compiler.erl +++ b/src/rebar_base_compiler.erl @@ -31,8 +31,8 @@ -export([run/4, run/7, run/8, - ok_tuple/3, - error_tuple/5]). + ok_tuple/2, + error_tuple/4]). %% =================================================================== %% Public API @@ -69,10 +69,10 @@ run(Config, FirstFiles, SourceDir, SourceExt, TargetDir, TargetExt, simple_compile_wrapper(S, Target, Compile3Fn, C, CheckLastMod) end). -ok_tuple(_Config, Source, Ws) -> +ok_tuple(Source, Ws) -> {ok, format_warnings(Source, Ws)}. -error_tuple(_Config, Source, Es, Ws, Opts) -> +error_tuple(Source, Es, Ws, Opts) -> {error, format_errors(Source, Es), format_warnings(Source, Ws, Opts)}. diff --git a/src/rebar_erlc_compiler.erl b/src/rebar_erlc_compiler.erl index 2b3942c..869ade3 100644 --- a/src/rebar_erlc_compiler.erl +++ b/src/rebar_erlc_compiler.erl @@ -210,7 +210,7 @@ needed_files(G, ErlOpts, Dir, OutDir, SourceFiles) -> TargetBase = target_base(OutDir, Source), Target = TargetBase ++ ".beam", AllOpts = [{outdir, filename:dirname(Target)} - ,{i, filename:join(Dir, "include")}] ++ ErlOpts, + ,{i, filename:join(Dir, "include")}] ++ ErlOpts, digraph:vertex(G, Source) > {Source, filelib:last_modified(Target)} orelse opts_changed(AllOpts, TargetBase) end, SourceFiles). @@ -405,7 +405,7 @@ expand_file_names(Files, Dirs) -> -spec internal_erl_compile(rebar_dict(), file:filename(), file:filename(), file:filename(), list()) -> ok | {ok, any()} | {error, any(), any()}. -internal_erl_compile(Opts, Dir, Module, OutDir, ErlOpts) -> +internal_erl_compile(_Opts, Dir, Module, OutDir, ErlOpts) -> Target = target_base(OutDir, Module) ++ ".beam", ok = filelib:ensure_dir(Target), AllOpts = [{outdir, filename:dirname(Target)}] ++ ErlOpts ++ @@ -414,9 +414,9 @@ internal_erl_compile(Opts, Dir, Module, OutDir, ErlOpts) -> {ok, _Mod} -> ok; {ok, _Mod, Ws} -> - rebar_base_compiler:ok_tuple(Opts, Module, Ws); + rebar_base_compiler:ok_tuple(Module, Ws); {error, Es, Ws} -> - rebar_base_compiler:error_tuple(Opts, Module, Es, Ws, Opts) + rebar_base_compiler:error_tuple(Module, Es, Ws, AllOpts) end. target_base(OutDir, Source) -> @@ -464,8 +464,9 @@ compile_yrl(Source, Target, Opts) -> -spec compile_xrl_yrl(rebar_dict(), file:filename(), file:filename(), list(), module()) -> 'ok'. -compile_xrl_yrl(Opts, Source, Target, AllOpts, Mod) -> - Dir = filename:dirname(Target), +compile_xrl_yrl(_Opts, Source, Target, AllOpts, Mod) -> + %% FIX ME: should be the outdir or something + Dir = filename:dirname(filename:dirname(Target)), AllOpts1 = [{includefile, filename:join(Dir, I)} || {includefile, I} <- AllOpts, filename:pathtype(I) =:= relative], case needs_compile(Source, Target) of @@ -474,9 +475,9 @@ compile_xrl_yrl(Opts, Source, Target, AllOpts, Mod) -> {ok, _} -> ok; {ok, _Mod, Ws} -> - rebar_base_compiler:ok_tuple(Opts, Source, Ws); + rebar_base_compiler:ok_tuple(Source, Ws); {error, Es, Ws} -> - rebar_base_compiler:error_tuple(Opts, Source, + rebar_base_compiler:error_tuple(Source, Es, Ws, AllOpts1) end; false -> diff --git a/src/rebar_hooks.erl b/src/rebar_hooks.erl index c5f8b88..4e5130e 100644 --- a/src/rebar_hooks.erl +++ b/src/rebar_hooks.erl @@ -7,28 +7,29 @@ -include("rebar.hrl"). -include_lib("providers/include/providers.hrl"). -run_all_hooks(Dir, Type, Command, Providers, State) -> - run_all_hooks(Dir, Type, Command, Providers, element(2,rebar_app_info:new(noen)), State). - -spec run_all_hooks(file:filename_all(), pre | post, atom() | {atom(), atom()} | string(), [providers:t()], rebar_app_info:t(), rebar_state:t()) -> ok. run_all_hooks(Dir, Type, Command, Providers, AppInfo, State) -> - run_provider_hooks(Dir, Type, Command, Providers, AppInfo, State), - run_hooks(Dir, Type, Command, AppInfo, State). + run_provider_hooks(Dir, Type, Command, Providers, rebar_app_info:opts(AppInfo), State), + run_hooks(Dir, Type, Command, rebar_app_info:opts(AppInfo), State). + +run_all_hooks(Dir, Type, Command, Providers, State) -> + run_provider_hooks(Dir, Type, Command, Providers, rebar_state:opts(State), State), + run_hooks(Dir, Type, Command, rebar_state:opts(State), State). -run_provider_hooks(Dir, Type, Command, Providers, AppInfo, State) -> - case rebar_app_info:get(AppInfo, provider_hooks, [])++rebar_state:get(State, provider_hooks, []) of +run_provider_hooks(Dir, Type, Command, Providers, Opts, State) -> + case rebar_utils:get(Opts, provider_hooks, []) of [] -> ok; AllHooks -> TypeHooks = proplists:get_value(Type, AllHooks, []), - run_provider_hooks(Dir, Type, Command, Providers, TypeHooks, AppInfo, State) + run_provider_hooks_(Dir, Type, Command, Providers, TypeHooks, rebar_state:opts(State, Opts)) end. -run_provider_hooks(_Dir, _Type, _Command, _Providers, [], _AppInfo, _State) -> +run_provider_hooks_(_Dir, _Type, _Command, _Providers, [], _State) -> ok; -run_provider_hooks(Dir, Type, Command, Providers, TypeHooks, _AppInfo, State) -> +run_provider_hooks_(Dir, Type, Command, Providers, TypeHooks, State) -> PluginDepsPaths = rebar_state:code_paths(State, all_plugin_deps), code:add_pathsa(PluginDepsPaths), Providers1 = rebar_state:providers(State), @@ -71,16 +72,16 @@ format_error({bad_provider, Type, Command, Name}) -> %% ERL = ERLANG_ROOT_DIR/bin/erl %% ERLC = ERLANG_ROOT_DIR/bin/erl %% -run_hooks(Dir, pre, Command, AppInfo, State) -> - run_hooks(Dir, pre_hooks, Command, AppInfo, State); -run_hooks(Dir, post, Command, AppInfo, State) -> - run_hooks(Dir, post_hooks, Command, AppInfo, State); -run_hooks(Dir, Type, Command, AppInfo, State) -> - case rebar_app_info:get(AppInfo, Type, []) of +run_hooks(Dir, pre, Command, Opts, State) -> + run_hooks(Dir, pre_hooks, Command, Opts, State); +run_hooks(Dir, post, Command, Opts, State) -> + run_hooks(Dir, post_hooks, Command, Opts, State); +run_hooks(Dir, Type, Command, Opts, State) -> + case rebar_utils:get(Opts, Type, []) of [] -> ok; Hooks -> - Env = create_env(State, AppInfo), + Env = create_env(State, Opts), lists:foreach(fun({_, C, _}=Hook) when C =:= Command -> apply_hook(Dir, Env, Hook); ({C, _}=Hook) when C =:= Command -> @@ -101,8 +102,7 @@ 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, AppInfo) -> - Opts = rebar_app_info:opts(AppInfo), +create_env(State, Opts) -> BaseDir = rebar_dir:base_dir(State), [ {"REBAR_DEPS_DIR", filename:absname(rebar_dir:deps_dir(State))}, diff --git a/src/rebar_prv_clean.erl b/src/rebar_prv_clean.erl index fa8bcf3..60b61e3 100644 --- a/src/rebar_prv_clean.erl +++ b/src/rebar_prv_clean.erl @@ -50,9 +50,9 @@ do(State) -> clean_apps(EmptyState, Providers, DepApps), Cwd = rebar_dir:get_cwd(), - rebar_hooks:run_all_hooks(Cwd, pre, ?PROVIDER, Providers, element(2,rebar_app_info:new(noen)), 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, element(2,rebar_app_info:new(noen)), State), + rebar_hooks:run_all_hooks(Cwd, post, ?PROVIDER, Providers, State), {ok, State}. diff --git a/src/rebar_prv_compile.erl b/src/rebar_prv_compile.erl index 1675a41..547f5d3 100644 --- a/src/rebar_prv_compile.erl +++ b/src/rebar_prv_compile.erl @@ -45,14 +45,14 @@ do(State) -> %% Need to allow global config vars used on deps. %% Right now no way to differeniate and just give deps a new state. %% But need an account of "all deps" for some hooks to use. - EmptyState = rebar_state:new(), - build_apps(rebar_state:all_deps(EmptyState, - rebar_state:all_deps(State)), Providers, Deps), - + %% EmptyState = rebar_state:new(), + %% build_apps(rebar_state:all_deps(EmptyState, + %% rebar_state:all_deps(State)), Providers, Deps), + build_apps(State, Providers, Deps), {ok, ProjectApps1} = rebar_digraph:compile_order(ProjectApps), %% Run top level hooks *before* project apps compiled but *after* deps are - rebar_hooks:run_all_hooks(Cwd, pre, ?PROVIDER, Providers, element(2,rebar_app_info:new(noen)), State), + rebar_hooks:run_all_hooks(Cwd, pre, ?PROVIDER, Providers, State), ProjectApps2 = build_apps(State, Providers, ProjectApps1), State2 = rebar_state:project_apps(State, ProjectApps2), @@ -60,9 +60,13 @@ do(State) -> ProjAppsPaths = [filename:join(rebar_app_info:out_dir(X), "ebin") || X <- ProjectApps2], State3 = rebar_state:code_paths(State2, all_deps, DepsPaths ++ ProjAppsPaths), - rebar_hooks:run_all_hooks(Cwd, post, ?PROVIDER, Providers, element(2,rebar_app_info:new(noen)), State2), - has_all_artifacts(State3), - + rebar_hooks:run_all_hooks(Cwd, post, ?PROVIDER, Providers, State2), + case rebar_state:has_all_artifacts(State3) of + {false, File} -> + throw(?PRV_ERROR({missing_artifact, File})); + true -> + true + end, rebar_utils:cleanup_code_path(rebar_state:code_paths(State3, default) ++ rebar_state:code_paths(State, all_plugin_deps)), @@ -83,8 +87,8 @@ build_app(State, Providers, AppInfo) -> copy_app_dirs(AppInfo, AppDir, OutDir), %S = rebar_app_info:state_or_new(State, AppInfo), - S1 = rebar_state:all_deps(State, rebar_state:all_deps(State)), - compile(S1, Providers, AppInfo). + %S1 = rebar_state:all_deps(State, rebar_state:all_deps(State)), + compile(State, Providers, AppInfo). compile(State, Providers, AppInfo) -> ?INFO("Compiling ~s", [rebar_app_info:name(AppInfo)]), @@ -95,7 +99,7 @@ compile(State, Providers, AppInfo) -> case rebar_otp_app:compile(State, AppInfo) of {ok, AppInfo1} -> rebar_hooks:run_all_hooks(AppDir, post, ?PROVIDER, Providers, AppInfo, State), - has_all_artifacts(State), + has_all_artifacts(AppInfo1), AppInfo1; Error -> throw(Error) @@ -105,8 +109,8 @@ compile(State, Providers, AppInfo) -> %% Internal functions %% =================================================================== -has_all_artifacts(State) -> - case rebar_state:has_all_artifacts(State) of +has_all_artifacts(AppInfo1) -> + case rebar_app_info:has_all_artifacts(AppInfo1) of {false, File} -> throw(?PRV_ERROR({missing_artifact, File})); true -> diff --git a/src/rebar_prv_install_deps.erl b/src/rebar_prv_install_deps.erl index 6ae22d6..aeda252 100644 --- a/src/rebar_prv_install_deps.erl +++ b/src/rebar_prv_install_deps.erl @@ -256,7 +256,7 @@ handle_dep(State, Profile, DepsDir, AppInfo, Locks, Level) -> C = rebar_config:consult(rebar_app_info:dir(AppInfo)), AppInfo0 = rebar_app_info:update_opts(AppInfo, rebar_app_info:opts(AppInfo), C), - AppInfo1 = rebar_app_info:apply_overrides(AppInfo0, Name), + AppInfo1 = rebar_app_info:apply_overrides(rebar_state:overrides(State), AppInfo0), AppInfo2 = rebar_app_info:apply_profiles(AppInfo1, Profiles), Plugins = rebar_app_info:get(AppInfo2, plugins, []), @@ -266,7 +266,7 @@ handle_dep(State, Profile, DepsDir, AppInfo, Locks, Level) -> rebar_utils:check_blacklisted_otp_versions(rebar_app_info:get(AppInfo3, blacklisted_otp_vsns, [])), %% Dep may have plugins to install. Find and install here. - _S = rebar_plugins:install(State, AppInfo3), + State1 = rebar_plugins:install(State, AppInfo3), %% TODO: Plugin Providers?? %AppInfo1 = rebar_app_info:state(AppInfo, S5), @@ -276,7 +276,7 @@ handle_dep(State, Profile, DepsDir, AppInfo, Locks, Level) -> Deps = rebar_app_info:get(AppInfo3, {deps, default}, []), AppInfo4 = rebar_app_info:deps(AppInfo3, rebar_state:deps_names(Deps)), Deps1 = rebar_app_utils:parse_deps(Name, DepsDir, Deps, State, Locks, Level+1), - {AppInfo4, Deps1, State}. + {AppInfo4, Deps1, State1}. -spec maybe_fetch(rebar_app_info:t(), atom(), boolean(), sets:set(binary()), rebar_state:t()) -> {boolean(), rebar_app_info:t()}. diff --git a/src/rebar_state.erl b/src/rebar_state.erl index e31b01b..47fd853 100644 --- a/src/rebar_state.erl +++ b/src/rebar_state.erl @@ -118,7 +118,7 @@ new(ParentState, Config, Deps, Dir) -> true = rebar_config:verify_config_format(Terms), LocalOpts = dict:from_list(Terms), - NewOpts = merge_opts(LocalOpts, Opts), + NewOpts = rebar_utils:merge_opts(LocalOpts, Opts), ParentState#state_t{dir=Dir ,opts=NewOpts @@ -255,49 +255,12 @@ command_parsed_args(State, CmdArgs) -> apply_overrides(State=#state_t{overrides=Overrides}, AppName) -> Name = binary_to_atom(AppName, utf8), - - %% Inefficient. We want the order we get here though. - State1 = lists:foldl(fun({override, O}, StateAcc) -> - lists:foldl(fun({deps, Value}, StateAcc1) -> - rebar_state:set(StateAcc1, {deps,default}, Value); - ({Key, Value}, StateAcc1) -> - rebar_state:set(StateAcc1, Key, Value) - end, StateAcc, O); - (_, StateAcc) -> - StateAcc - end, State, Overrides), - - State2 = lists:foldl(fun({override, N, O}, StateAcc) when N =:= Name -> - lists:foldl(fun({deps, Value}, StateAcc1) -> - rebar_state:set(StateAcc1, {deps,default}, Value); - ({Key, Value}, StateAcc1) -> - rebar_state:set(StateAcc1, Key, Value) - end, StateAcc, O); - (_, StateAcc) -> - StateAcc - end, State1, Overrides), - - State3 = lists:foldl(fun({add, N, O}, StateAcc) when N =:= Name -> - lists:foldl(fun({deps, Value}, StateAcc1) -> - OldValue = rebar_state:get(StateAcc1, {deps,default}, []), - rebar_state:set(StateAcc1, {deps,default}, Value++OldValue); - ({Key, Value}, StateAcc1) -> - OldValue = rebar_state:get(StateAcc1, Key, []), - rebar_state:set(StateAcc1, Key, Value++OldValue) - end, StateAcc, O); - (_, StateAcc) -> - StateAcc - end, State2, Overrides), - - Opts = opts(State3), - State3#state_t{default=Opts}. + Opts = rebar_utils:apply_overrides(opts(State), Name, Overrides), + State#state_t{default=Opts, opts=Opts}. add_to_profile(State, Profile, KVs) when is_atom(Profile), is_list(KVs) -> - Profiles = rebar_state:get(State, profiles, []), - ProfileOpts = dict:from_list(proplists:get_value(Profile, Profiles, [])), - NewOpts = merge_opts(Profile, dict:from_list(KVs), ProfileOpts), - NewProfiles = [{Profile, dict:to_list(NewOpts)}|lists:keydelete(Profile, 1, Profiles)], - rebar_state:set(State, profiles, NewProfiles). + Opts = rebar_utils:add_to_profile(opts(State), Profile, KVs), + State#state_t{opts=Opts}. apply_profiles(State, Profile) when not is_list(Profile) -> apply_profiles(State, [Profile]); @@ -323,7 +286,7 @@ apply_profiles(State=#state_t{default = Defaults, current_profiles=CurrentProfil case proplists:get_value(Profile, ConfigProfiles, []) of OptsList when is_list(OptsList) -> ProfileOpts = dict:from_list(OptsList), - merge_opts(Profile, ProfileOpts, OptsAcc); + rebar_utils:merge_opts(Profile, ProfileOpts, OptsAcc); Other -> throw(?PRV_ERROR({profile_not_list, Profile, Other})) end @@ -341,53 +304,6 @@ do_deduplicate([Head | Rest], Acc) -> false -> do_deduplicate(Rest, [Head | Acc]) end. -merge_opts(Profile, NewOpts, OldOpts) -> - Opts = merge_opts(NewOpts, OldOpts), - - Opts2 = case dict:find(plugins, NewOpts) of - {ok, Value} -> - dict:store({plugins, Profile}, Value, Opts); - error -> - Opts - end, - - case dict:find(deps, NewOpts) of - {ok, Value2} -> - dict:store({deps, Profile}, Value2, Opts2); - error -> - Opts2 - end. - -merge_opts(NewOpts, OldOpts) -> - dict:merge(fun(deps, _NewValue, OldValue) -> - OldValue; - ({deps, _}, NewValue, _OldValue) -> - NewValue; - (plugins, NewValue, _OldValue) -> - NewValue; - ({plugins, _}, NewValue, _OldValue) -> - NewValue; - (profiles, NewValue, OldValue) -> - dict:to_list(merge_opts(dict:from_list(NewValue), dict:from_list(OldValue))); - (_Key, NewValue, OldValue) when is_list(NewValue) -> - case io_lib:printable_list(NewValue) of - true when NewValue =:= [] -> - case io_lib:printable_list(OldValue) of - true -> - NewValue; - false -> - OldValue - end; - true -> - NewValue; - false -> - rebar_utils:tup_umerge(rebar_utils:tup_sort(NewValue) - ,rebar_utils:tup_sort(OldValue)) - end; - (_Key, NewValue, _OldValue) -> - NewValue - end, NewOpts, OldOpts). - dir(#state_t{dir=Dir}) -> Dir. diff --git a/src/rebar_utils.erl b/src/rebar_utils.erl index 7363d0a..9f66181 100644 --- a/src/rebar_utils.erl +++ b/src/rebar_utils.erl @@ -69,7 +69,11 @@ escape_double_quotes_weak/1, check_min_otp_version/1, check_blacklisted_otp_versions/1, - info_useless/2]). + info_useless/2, + apply_overrides/3, + add_to_profile/3, + merge_opts/2, + merge_opts/3]). %% for internal use only -export([otp_release/0]). @@ -397,6 +401,93 @@ abort_if_blacklisted(BlacklistedRegex, OtpRelease) -> [OtpRelease, BlacklistedRegex]) end. +apply_overrides(Opts, Name, Overrides) -> + %% Inefficient. We want the order we get here though. + Opts1 = lists:foldl(fun({override, O}, OptsAcc) -> + lists:foldl(fun({deps, Value}, OptsAcc1) -> + rebar_utils:set(OptsAcc1, {deps,default}, Value); + ({Key, Value}, OptsAcc1) -> + rebar_utils:set(OptsAcc1, Key, Value) + end, OptsAcc, O); + (_, OptsAcc) -> + OptsAcc + end, Opts, Overrides), + + Opts2 = lists:foldl(fun({override, N, O}, OptsAcc) when N =:= Name -> + lists:foldl(fun({deps, Value}, OptsAcc1) -> + rebar_utils:set(OptsAcc1, {deps,default}, Value); + ({Key, Value}, OptsAcc1) -> + rebar_utils:set(OptsAcc1, Key, Value) + end, OptsAcc, O); + (_, OptsAcc) -> + OptsAcc + end, Opts1, Overrides), + + lists:foldl(fun({add, N, O}, OptsAcc) when N =:= Name -> + lists:foldl(fun({deps, Value}, OptsAcc1) -> + OldValue = rebar_utils:get(OptsAcc1, {deps,default}, []), + rebar_utils:set(OptsAcc1, {deps,default}, Value++OldValue); + ({Key, Value}, OptsAcc1) -> + OldValue = rebar_utils:get(OptsAcc1, Key, []), + rebar_utils:set(OptsAcc1, Key, Value++OldValue) + end, OptsAcc, O); + (_, OptsAcc) -> + OptsAcc + end, Opts2, Overrides). + +add_to_profile(Opts, Profile, KVs) when is_atom(Profile), is_list(KVs) -> + Profiles = rebar_utils:get(Opts, profiles, []), + ProfileOpts = dict:from_list(proplists:get_value(Profile, Profiles, [])), + NewOpts = rebar_utils:merge_opts(Profile, dict:from_list(KVs), ProfileOpts), + NewProfiles = [{Profile, dict:to_list(NewOpts)}|lists:keydelete(Profile, 1, Profiles)], + rebar_utils:set(Opts, profiles, NewProfiles). + +merge_opts(Profile, NewOpts, OldOpts) -> + Opts = merge_opts(NewOpts, OldOpts), + + Opts2 = case dict:find(plugins, NewOpts) of + {ok, Value} -> + dict:store({plugins, Profile}, Value, Opts); + error -> + Opts + end, + + case dict:find(deps, NewOpts) of + {ok, Value2} -> + dict:store({deps, Profile}, Value2, Opts2); + error -> + Opts2 + end. + +merge_opts(NewOpts, OldOpts) -> + dict:merge(fun(deps, _NewValue, OldValue) -> + OldValue; + ({deps, _}, NewValue, _OldValue) -> + NewValue; + (plugins, NewValue, _OldValue) -> + NewValue; + ({plugins, _}, NewValue, _OldValue) -> + NewValue; + (profiles, NewValue, OldValue) -> + dict:to_list(merge_opts(dict:from_list(NewValue), dict:from_list(OldValue))); + (_Key, NewValue, OldValue) when is_list(NewValue) -> + case io_lib:printable_list(NewValue) of + true when NewValue =:= [] -> + case io_lib:printable_list(OldValue) of + true -> + NewValue; + false -> + OldValue + end; + true -> + NewValue; + false -> + rebar_utils:tup_umerge(rebar_utils:tup_sort(NewValue) + ,rebar_utils:tup_sort(OldValue)) + end; + (_Key, NewValue, _OldValue) -> + NewValue + end, NewOpts, OldOpts). %% ==================================================================== %% Internal functions -- cgit v1.1