From d034f40c38753860c2da894f1966af5399f3efce Mon Sep 17 00:00:00 2001 From: Tristan Sloughter Date: Tue, 1 Sep 2015 17:48:04 -0500 Subject: move opts functions to new module rebar_opts --- src/rebar_opts.erl | 155 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 155 insertions(+) create mode 100644 src/rebar_opts.erl (limited to 'src/rebar_opts.erl') diff --git a/src/rebar_opts.erl b/src/rebar_opts.erl new file mode 100644 index 0000000..47451c5 --- /dev/null +++ b/src/rebar_opts.erl @@ -0,0 +1,155 @@ +-module(rebar_opts). + +-export([get/2, + get/3, + set/3, + + erl_opts/1, + + apply_overrides/3, + add_to_profile/3, + merge_opts/2, + merge_opts/3]). + +-include("rebar.hrl"). + +get(Opts, Key) -> + {ok, Value} = dict:find(Key, Opts), + Value. + +get(Opts, Key, Default) -> + case dict:find(Key, Opts) of + {ok, Value} -> + Value; + error -> + Default + end. + +set(Opts, Key, Value) -> + dict:store(Key, Value, Opts). + +%% @doc Return list of erl_opts +-spec erl_opts(rebar_dict()) -> list(). +erl_opts(Opts) -> + RawErlOpts = filter_defines(?MODULE:get(Opts, erl_opts, []), []), + Defines = [{d, list_to_atom(D)} || + D <- ?MODULE:get(Opts, defines, [])], + AllOpts = Defines ++ RawErlOpts, + case proplists:is_defined(no_debug_info, AllOpts) of + true -> + [O || O <- AllOpts, O =/= no_debug_info]; + false -> + [debug_info|AllOpts] + 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) -> + set(OptsAcc1, {deps,default}, Value); + ({Key, Value}, OptsAcc1) -> + 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) -> + set(OptsAcc1, {deps,default}, Value); + ({Key, Value}, OptsAcc1) -> + 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 = ?MODULE:get(OptsAcc1, {deps,default}, []), + set(OptsAcc1, {deps,default}, Value++OldValue); + ({Key, Value}, OptsAcc1) -> + OldValue = ?MODULE:get(OptsAcc1, Key, []), + 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 = ?MODULE:get(Opts, 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)], + 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(NewValue, OldValue) + end; + (_Key, NewValue, _OldValue) -> + NewValue + end, NewOpts, OldOpts). + +%% Internal functions + +%% +%% Filter a list of erl_opts platform_define options such that only +%% those which match the provided architecture regex are returned. +%% +filter_defines([], Acc) -> + lists:reverse(Acc); +filter_defines([{platform_define, ArchRegex, Key} | Rest], Acc) -> + case rebar_utils:is_arch(ArchRegex) of + true -> + filter_defines(Rest, [{d, Key} | Acc]); + false -> + filter_defines(Rest, Acc) + end; +filter_defines([{platform_define, ArchRegex, Key, Value} | Rest], Acc) -> + case rebar_utils:is_arch(ArchRegex) of + true -> + filter_defines(Rest, [{d, Key, Value} | Acc]); + false -> + filter_defines(Rest, Acc) + end; +filter_defines([Opt | Rest], Acc) -> + filter_defines(Rest, [Opt | Acc]). -- cgit v1.1