瀏覽代碼

update use of hooks and plugins with state in app_info

pull/760/head
Tristan Sloughter 9 年之前
父節點
當前提交
8e25a45cbb
共有 10 個文件被更改,包括 162 次插入237 次删除
  1. +9
    -96
      src/rebar_app_info.erl
  2. +1
    -1
      src/rebar_app_utils.erl
  3. +4
    -4
      src/rebar_base_compiler.erl
  4. +9
    -8
      src/rebar_erlc_compiler.erl
  5. +19
    -19
      src/rebar_hooks.erl
  6. +2
    -2
      src/rebar_prv_clean.erl
  7. +17
    -13
      src/rebar_prv_compile.erl
  8. +3
    -3
      src/rebar_prv_install_deps.erl
  9. +6
    -90
      src/rebar_state.erl
  10. +92
    -1
      src/rebar_utils.erl

+ 9
- 96
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).

+ 1
- 1
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}) ->

+ 4
- 4
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)}.

+ 9
- 8
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 ->

+ 19
- 19
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))},

+ 2
- 2
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}.

+ 17
- 13
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 ->

+ 3
- 3
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()}.

+ 6
- 90
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.

+ 92
- 1
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

Loading…
取消
儲存