summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFred Hebert <mononcqc@ferd.ca>2015-09-03 20:56:29 -0700
committerFred Hebert <mononcqc@ferd.ca>2015-09-03 20:56:29 -0700
commita311961e8b6c1634bc3beee9854f5b2d4f72393d (patch)
treeb1f143c545768b4891f08892a7ee18f24fc16dbc
parentbee43181d2c60df78e159da263b0889a64f5b88e (diff)
parenta81444ae1c32fb1ff73bd571327fd6adeec9901f (diff)
Merge pull request #760 from tsloughter/app_info_state
move state into app_info
-rw-r--r--src/rebar_app_discover.erl116
-rw-r--r--src/rebar_app_info.erl192
-rw-r--r--src/rebar_app_utils.erl36
-rw-r--r--src/rebar_base_compiler.erl8
-rw-r--r--src/rebar_dir.erl34
-rw-r--r--src/rebar_erlc_compiler.erl126
-rw-r--r--src/rebar_hooks.erl42
-rw-r--r--src/rebar_opts.erl155
-rw-r--r--src/rebar_otp_app.erl16
-rw-r--r--src/rebar_plugins.erl24
-rw-r--r--src/rebar_prv_clean.erl13
-rw-r--r--src/rebar_prv_common_test.erl6
-rw-r--r--src/rebar_prv_compile.erl39
-rw-r--r--src/rebar_prv_install_deps.erl78
-rw-r--r--src/rebar_prv_plugins_upgrade.erl5
-rw-r--r--src/rebar_state.erl122
-rw-r--r--src/rebar_utils.erl73
-rw-r--r--test/rebar_dir_SUITE.erl42
-rw-r--r--test/rebar_profiles_SUITE.erl3
-rw-r--r--test/rebar_src_dirs_SUITE.erl12
20 files changed, 628 insertions, 514 deletions
diff --git a/src/rebar_app_discover.erl b/src/rebar_app_discover.erl
index 5a25a9e..9d7c62a 100644
--- a/src/rebar_app_discover.erl
+++ b/src/rebar_app_discover.erl
@@ -5,7 +5,8 @@
find_unbuilt_apps/1,
find_apps/1,
find_apps/2,
- find_app/2]).
+ find_app/2,
+ find_app/3]).
-include("rebar.hrl").
-include_lib("providers/include/providers.hrl").
@@ -25,12 +26,12 @@ do(State, LibDirs) ->
%% Handle top level deps
State1 = lists:foldl(fun(Profile, StateAcc) ->
ProfileDeps = rebar_state:get(StateAcc, {deps, Profile}, []),
- ProfileDeps2 = rebar_utils:tup_dedup(rebar_utils:tup_sort(ProfileDeps)),
+ ProfileDeps2 = rebar_utils:tup_dedup(ProfileDeps),
StateAcc1 = rebar_state:set(StateAcc, {deps, Profile}, ProfileDeps2),
ParsedDeps = parse_profile_deps(Profile
,TopLevelApp
,ProfileDeps2
- ,StateAcc1
+ ,rebar_state:opts(StateAcc1)
,StateAcc1),
rebar_state:set(StateAcc1, {parsed_deps, Profile}, ParsedDeps)
end, State, lists:reverse(CurrentProfiles)),
@@ -72,54 +73,49 @@ format_error({missing_module, Module}) ->
io_lib:format("Module defined in app file missing: ~p~n", [Module]).
merge_deps(AppInfo, State) ->
- Default = rebar_state:default(State),
- CurrentProfiles = rebar_state:current_profiles(State),
- Name = rebar_app_info:name(AppInfo),
+ Default = reset_hooks(rebar_state:default(State)),
C = project_app_config(AppInfo, State),
+ AppInfo0 = rebar_app_info:update_opts(AppInfo, Default, C),
- %% We reset the opts here to default so no profiles are applied multiple times
- AppState = rebar_state:apply_overrides(
- rebar_state:apply_profiles(
- rebar_state:new(reset_hooks(rebar_state:opts(State, Default)), C,
- rebar_app_info:dir(AppInfo)), CurrentProfiles), Name),
- AppState1 = rebar_state:overrides(AppState, rebar_state:get(AppState, overrides, [])),
+ CurrentProfiles = rebar_state:current_profiles(State),
+ Name = rebar_app_info:name(AppInfo0),
- rebar_utils:check_min_otp_version(rebar_state:get(AppState1, minimum_otp_vsn, undefined)),
- rebar_utils:check_blacklisted_otp_versions(rebar_state:get(AppState1, blacklisted_otp_vsns, [])),
+ %% We reset the opts here to default so no profiles are applied multiple times
+ AppInfo1 = rebar_app_info:apply_overrides(rebar_state:get(State, overrides, []), AppInfo0),
+ AppInfo2 = rebar_app_info:apply_profiles(AppInfo1, CurrentProfiles),
- AppState2 = rebar_state:set(AppState1, artifacts, []),
- AppInfo1 = rebar_app_info:state(AppInfo, AppState2),
+ %% Will throw an exception if checks fail
+ rebar_app_info:verify_otp_vsn(AppInfo2),
State1 = lists:foldl(fun(Profile, StateAcc) ->
- handle_profile(Profile, Name, AppState1, StateAcc)
+ handle_profile(Profile, Name, AppInfo2, StateAcc)
end, State, lists:reverse(CurrentProfiles)),
- {AppInfo1, State1}.
+ {AppInfo2, State1}.
-handle_profile(Profile, Name, AppState, State) ->
+handle_profile(Profile, Name, AppInfo, State) ->
TopParsedDeps = rebar_state:get(State, {parsed_deps, Profile}, {[], []}),
TopLevelProfileDeps = rebar_state:get(State, {deps, Profile}, []),
- AppProfileDeps = rebar_state:get(AppState, {deps, Profile}, []),
- AppProfileDeps2 = rebar_utils:tup_dedup(rebar_utils:tup_sort(AppProfileDeps)),
- ProfileDeps2 = rebar_utils:tup_dedup(rebar_utils:tup_umerge(
- rebar_utils:tup_sort(TopLevelProfileDeps)
- ,rebar_utils:tup_sort(AppProfileDeps2))),
+ AppProfileDeps = rebar_app_info:get(AppInfo, {deps, Profile}, []),
+ AppProfileDeps2 = rebar_utils:tup_dedup(AppProfileDeps),
+ ProfileDeps2 = rebar_utils:tup_dedup(rebar_utils:tup_umerge(TopLevelProfileDeps
+ ,AppProfileDeps2)),
State1 = rebar_state:set(State, {deps, Profile}, ProfileDeps2),
%% Only deps not also specified in the top level config need
%% to be included in the parsed deps
NewDeps = ProfileDeps2 -- TopLevelProfileDeps,
- ParsedDeps = parse_profile_deps(Profile, Name, NewDeps, AppState, State1),
+ ParsedDeps = parse_profile_deps(Profile, Name, NewDeps, rebar_app_info:opts(AppInfo), State1),
State2 = rebar_state:set(State1, {deps, Profile}, ProfileDeps2),
rebar_state:set(State2, {parsed_deps, Profile}, TopParsedDeps++ParsedDeps).
-parse_profile_deps(Profile, Name, Deps, AppState, State) ->
+parse_profile_deps(Profile, Name, Deps, Opts, State) ->
DepsDir = rebar_prv_install_deps:profile_dep_dir(State, Profile),
Locks = rebar_state:get(State, {locks, Profile}, []),
rebar_app_utils:parse_deps(Name
,DepsDir
,Deps
- ,AppState
+ ,rebar_state:opts(State, Opts)
,Locks
,1).
@@ -134,15 +130,16 @@ maybe_reset_hooks(C, Dir, State) ->
case ec_file:real_dir_path(rebar_dir:root_dir(State)) of
Dir ->
C1 = proplists:delete(provider_hooks, C),
- proplists:delete(post_hooks, proplists:delete(pre_hooks, C1));
+ C2 = proplists:delete(artifacts, C1),
+ proplists:delete(post_hooks, proplists:delete(pre_hooks, C2));
_ ->
C
end.
-reset_hooks(State) ->
- lists:foldl(fun(Key, StateAcc) ->
- rebar_state:set(StateAcc, Key, [])
- end, State, [post_hooks, pre_hooks, provider_hooks]).
+reset_hooks(Opts) ->
+ lists:foldl(fun(Key, OptsAcc) ->
+ rebar_opts:set(OptsAcc, Key, [])
+ end, Opts, [post_hooks, pre_hooks, provider_hooks, artifacts]).
-spec all_app_dirs(list(file:name())) -> list(file:name()).
all_app_dirs(LibDirs) ->
@@ -183,41 +180,46 @@ find_apps(LibDirs, Validate) ->
-spec find_app(file:filename_all(), valid | invalid | all) -> {true, rebar_app_info:t()} | false.
find_app(AppDir, Validate) ->
+ find_app(rebar_app_info:new(), AppDir, Validate).
+
+find_app(AppInfo, AppDir, Validate) ->
AppFile = filelib:wildcard(filename:join([AppDir, "ebin", "*.app"])),
AppSrcFile = filelib:wildcard(filename:join([AppDir, "src", "*.app.src"])),
AppSrcScriptFile = filelib:wildcard(filename:join([AppDir, "src", "*.app.src.script"])),
- AppInfo = try_handle_app_file(AppFile, AppDir, AppSrcFile, AppSrcScriptFile, Validate),
- AppInfo.
+ try_handle_app_file(AppInfo, AppFile, AppDir, AppSrcFile, AppSrcScriptFile, Validate).
app_dir(AppFile) ->
filename:join(rebar_utils:droplast(filename:split(filename:dirname(AppFile)))).
--spec create_app_info(file:name(), file:name()) -> rebar_app_info:t().
-create_app_info(AppDir, AppFile) ->
+-spec create_app_info(rebar_app_info:t(), file:name(), file:name()) -> rebar_app_info:t().
+create_app_info(AppInfo, AppDir, AppFile) ->
[{application, AppName, AppDetails}] = rebar_config:consult_app_file(AppFile),
AppVsn = proplists:get_value(vsn, AppDetails),
Applications = proplists:get_value(applications, AppDetails, []),
IncludedApplications = proplists:get_value(included_applications, AppDetails, []),
- {ok, AppInfo} = rebar_app_info:new(AppName, AppVsn, AppDir),
- AppInfo1 = rebar_app_info:applications(
- rebar_app_info:app_details(AppInfo, AppDetails),
+ AppInfo1 = rebar_app_info:name(
+ rebar_app_info:original_vsn(
+ rebar_app_info:dir(AppInfo, AppDir), AppVsn), AppName),
+ AppInfo2 = rebar_app_info:applications(
+ rebar_app_info:app_details(AppInfo1, AppDetails),
IncludedApplications++Applications),
- Valid = case rebar_app_utils:validate_application_info(AppInfo1) of
+ Valid = case rebar_app_utils:validate_application_info(AppInfo2) =:= true
+ andalso rebar_app_info:has_all_artifacts(AppInfo2) =:= true of
true ->
true;
_ ->
false
end,
- rebar_app_info:dir(rebar_app_info:valid(AppInfo1, Valid), AppDir).
+ rebar_app_info:dir(rebar_app_info:valid(AppInfo2, Valid), AppDir).
%% Read in and parse the .app file if it is availabe. Do the same for
%% the .app.src file if it exists.
-try_handle_app_file([], AppDir, [], AppSrcScriptFile, Validate) ->
- try_handle_app_src_file([], AppDir, AppSrcScriptFile, Validate);
-try_handle_app_file([], AppDir, AppSrcFile, _, Validate) ->
- try_handle_app_src_file([], AppDir, AppSrcFile, Validate);
-try_handle_app_file([File], AppDir, AppSrcFile, _, Validate) ->
- try create_app_info(AppDir, File) of
+try_handle_app_file(AppInfo, [], AppDir, [], AppSrcScriptFile, Validate) ->
+ try_handle_app_src_file(AppInfo, [], AppDir, AppSrcScriptFile, Validate);
+try_handle_app_file(AppInfo, [], AppDir, AppSrcFile, _, Validate) ->
+ try_handle_app_src_file(AppInfo, [], AppDir, AppSrcFile, Validate);
+try_handle_app_file(AppInfo0, [File], AppDir, AppSrcFile, _, Validate) ->
+ try create_app_info(AppInfo0, AppDir, File) of
AppInfo ->
AppInfo1 = rebar_app_info:app_file(AppInfo, File),
AppInfo2 = case AppSrcFile of
@@ -249,26 +251,26 @@ try_handle_app_file([File], AppDir, AppSrcFile, _, Validate) ->
catch
throw:{error, {Module, Reason}} ->
?DEBUG("Falling back to app.src file because .app failed: ~s", [Module:format_error(Reason)]),
- try_handle_app_src_file(File, AppDir, AppSrcFile, Validate)
+ try_handle_app_src_file(AppInfo0, File, AppDir, AppSrcFile, Validate)
end;
-try_handle_app_file(Other, _AppDir, _AppSrcFile, _, _Validate) ->
+try_handle_app_file(_AppInfo, Other, _AppDir, _AppSrcFile, _, _Validate) ->
throw({error, {multiple_app_files, Other}}).
%% Read in the .app.src file if we aren't looking for a valid (already built) app
-try_handle_app_src_file(_, _AppDir, [], _Validate) ->
+try_handle_app_src_file(_AppInfo, _, _AppDir, [], _Validate) ->
false;
-try_handle_app_src_file(_, _AppDir, _AppSrcFile, valid) ->
+try_handle_app_src_file(_AppInfo, _, _AppDir, _AppSrcFile, valid) ->
false;
-try_handle_app_src_file(_, AppDir, [File], Validate) when Validate =:= invalid
- ; Validate =:= all ->
- AppInfo = create_app_info(AppDir, File),
+try_handle_app_src_file(AppInfo, _, AppDir, [File], Validate) when Validate =:= invalid
+ ; Validate =:= all ->
+ AppInfo1 = create_app_info(AppInfo, AppDir, File),
case filename:extension(File) of
".script" ->
- {true, rebar_app_info:app_file_src_script(AppInfo, File)};
+ {true, rebar_app_info:app_file_src_script(AppInfo1, File)};
_ ->
- {true, rebar_app_info:app_file_src(AppInfo, File)}
+ {true, rebar_app_info:app_file_src(AppInfo1, File)}
end;
-try_handle_app_src_file(_, _AppDir, Other, _Validate) ->
+try_handle_app_src_file(_AppInfo, _, _AppDir, Other, _Validate) ->
throw({error, {multiple_app_files, Other}}).
enable(State, AppInfo) ->
diff --git a/src/rebar_app_info.erl b/src/rebar_app_info.erl
index bb5104e..92706f3 100644
--- a/src/rebar_app_info.erl
+++ b/src/rebar_app_info.erl
@@ -1,15 +1,15 @@
-module(rebar_app_info).
--export([new/1,
+-export([new/0,
+ new/1,
new/2,
new/3,
new/4,
new/5,
+ update_opts/3,
discover/1,
name/1,
name/2,
- config/1,
- config/2,
app_file_src/1,
app_file_src/2,
app_file_src_script/1,
@@ -35,21 +35,35 @@
dir/2,
out_dir/1,
out_dir/2,
+ default/1,
+ default/2,
+ opts/1,
+ opts/2,
+ get/2,
+ get/3,
+ set/3,
resource_type/1,
resource_type/2,
source/1,
source/2,
- state/1,
- state/2,
- state_or_new/2,
is_lock/1,
is_lock/2,
is_checkout/1,
is_checkout/2,
valid/1,
- valid/2]).
+ valid/2,
+
+ verify_otp_vsn/1,
+ has_all_artifacts/1,
+
+ apply_overrides/2,
+ add_to_profile/3,
+ apply_profiles/2,
+ deduplicate/1,
+ do_deduplicate/2]).
-include("rebar.hrl").
+-include_lib("providers/include/providers.hrl").
-export_type([t/0]).
@@ -57,19 +71,19 @@
app_file_src :: file:filename_all() | undefined,
app_file_src_script:: file:filename_all() | undefined,
app_file :: file:filename_all() | undefined,
- config :: rebar_state:t() | undefined,
original_vsn :: binary() | string() | undefined,
parent=root :: binary() | root,
app_details=[] :: list(),
applications=[] :: list(),
deps=[] :: list(),
profiles=[default] :: [atom()],
+ default=dict:new() :: rebar_dict(),
+ opts=dict:new() :: rebar_dict(),
dep_level=0 :: integer(),
dir :: file:name(),
out_dir :: file:name(),
resource_type :: pkg | src,
source :: string() | tuple() | undefined,
- state :: rebar_state:t() | undefined,
is_lock=false :: boolean(),
is_checkout=false :: boolean(),
valid :: boolean()}).
@@ -84,6 +98,10 @@
%% ============================================================================
%% @doc Build a new, empty, app info value. This is not of a lot of use and you
%% probably wont be doing this much.
+-spec new() -> t().
+new() ->
+ #app_info_t{}.
+
-spec new(atom() | binary() | string()) ->
{ok, t()}.
new(AppName) ->
@@ -125,6 +143,36 @@ new(Parent, AppName, Vsn, Dir, Deps) ->
out_dir=ec_cnv:to_list(Dir),
deps=Deps}}.
+update_opts(AppInfo, Opts, Config) ->
+ LockDeps = case resource_type(AppInfo) of
+ pkg ->
+ Deps = deps(AppInfo),
+ [{{locks, default}, Deps}, {{deps, default}, Deps}];
+ _ ->
+ deps_from_config(dir(AppInfo), Config)
+ end,
+
+ Plugins = proplists:get_value(plugins, Config, []),
+ Terms = LockDeps++[{{plugins, default}, Plugins} | Config],
+ true = rebar_config:verify_config_format(Terms),
+ LocalOpts = dict:from_list(Terms),
+
+ NewOpts = rebar_opts:merge_opts(LocalOpts, Opts),
+
+ AppInfo#app_info_t{opts=NewOpts
+ ,default=NewOpts}.
+
+deps_from_config(Dir, Config) ->
+ case rebar_config:consult_lock_file(filename:join(Dir, ?LOCK_FILE)) of
+ [D] ->
+ %% We want the top level deps only from the lock file.
+ %% This ensures deterministic overrides for configs.
+ Deps = [X || X <- D, element(3, X) =:= 0],
+ [{{locks, default}, D}, {{deps, default}, Deps}];
+ _ ->
+ [{{deps, default}, proplists:get_value(deps, Config, [])}]
+ end.
+
%% @doc discover a complete version of the app info with all fields set.
-spec discover(file:filename_all()) -> {ok, t()} | not_found.
discover(Dir) ->
@@ -143,13 +191,33 @@ name(#app_info_t{name=Name}) ->
name(AppInfo=#app_info_t{}, AppName) ->
AppInfo#app_info_t{name=ec_cnv:to_binary(AppName)}.
--spec config(t()) -> rebar_state:t().
-config(#app_info_t{config=Config}) ->
- Config.
+opts(#app_info_t{opts=Opts}) ->
+ Opts.
+
+opts(AppInfo, Opts) ->
+ AppInfo#app_info_t{opts=Opts}.
+
+default(#app_info_t{default=Default}) ->
+ Default.
+
+default(AppInfo, Default) ->
+ AppInfo#app_info_t{default=Default}.
+
+get(AppInfo, Key) ->
+ {ok, Value} = dict:find(Key, AppInfo#app_info_t.opts),
+ Value.
+
+get(AppInfo, Key, Default) ->
+ case dict:find(Key, AppInfo#app_info_t.opts) of
+ {ok, Value} ->
+ Value;
+ error ->
+ Default
+ end.
--spec config(t(), rebar_state:t()) -> t().
-config(AppInfo=#app_info_t{}, Config) ->
- AppInfo#app_info_t{config=Config}.
+-spec set(t(), any(), any()) -> t().
+set(AppInfo=#app_info_t{opts=Opts}, Key, Value) ->
+ AppInfo#app_info_t{opts = dict:store(Key, Value, Opts)}.
-spec app_file_src(t()) -> file:filename_all() | undefined.
app_file_src(#app_info_t{app_file_src=undefined, dir=Dir, name=Name}) ->
@@ -305,22 +373,6 @@ source(AppInfo=#app_info_t{}, Source) ->
source(#app_info_t{source=Source}) ->
Source.
--spec state(t(), rebar_state:t() | undefined) -> t().
-state(AppInfo=#app_info_t{}, State) ->
- AppInfo#app_info_t{state=State}.
-
--spec state(t()) -> rebar_state:t() | undefined.
-state(#app_info_t{state=State}) ->
- State.
-
--spec state_or_new(rebar_state:t(), t()) -> rebar_state:t().
-state_or_new(State, AppInfo=#app_info_t{state=undefined}) ->
- AppDir = dir(AppInfo),
- C = rebar_config:consult(AppDir),
- rebar_state:new(State, C, AppInfo);
-state_or_new(_State, #app_info_t{state=State}) ->
- State.
-
-spec is_lock(t(), boolean()) -> t().
is_lock(AppInfo=#app_info_t{}, IsLock) ->
AppInfo#app_info_t{is_lock=IsLock}.
@@ -338,9 +390,9 @@ is_checkout(#app_info_t{is_checkout=IsCheckout}) ->
IsCheckout.
-spec valid(t()) -> boolean().
-valid(AppInfo=#app_info_t{valid=undefined, state=State}) ->
+valid(AppInfo=#app_info_t{valid=undefined}) ->
case rebar_app_utils:validate_application_info(AppInfo) =:= true
- andalso rebar_state:has_all_artifacts(State) =:= true of
+ andalso has_all_artifacts(AppInfo) =:= true of
true ->
true;
_ ->
@@ -352,3 +404,77 @@ valid(#app_info_t{valid=Valid}) ->
-spec valid(t(), boolean()) -> t().
valid(AppInfo=#app_info_t{}, Valid) ->
AppInfo#app_info_t{valid=Valid}.
+
+verify_otp_vsn(AppInfo) ->
+ rebar_utils:check_min_otp_version(rebar_app_info:get(AppInfo, minimum_otp_vsn, undefined)),
+ rebar_utils:check_blacklisted_otp_versions(rebar_app_info:get(AppInfo, blacklisted_otp_vsns, [])).
+
+-spec has_all_artifacts(#app_info_t{}) -> true | {false, file:filename()}.
+has_all_artifacts(AppInfo) ->
+ Artifacts = rebar_app_info:get(AppInfo, artifacts, []),
+ Dir = dir(AppInfo),
+ all(Dir, Artifacts).
+
+all(_, []) ->
+ true;
+all(Dir, [File|Artifacts]) ->
+ case filelib:is_regular(filename:join(Dir, File)) of
+ false ->
+ ?DEBUG("Missing artifact ~s", [filename:join(Dir, File)]),
+ {false, File};
+ true ->
+ all(Dir, Artifacts)
+ end.
+
+%%%%%
+
+apply_overrides(Overrides, AppInfo) ->
+ Name = binary_to_atom(rebar_app_info:name(AppInfo), utf8),
+ Opts = rebar_opts: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) ->
+ Opts = rebar_opts: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]);
+apply_profiles(AppInfo, [default]) ->
+ AppInfo;
+apply_profiles(AppInfo=#app_info_t{default = Defaults, profiles=CurrentProfiles}, Profiles) ->
+ AppliedProfiles = case Profiles of
+ %% Head of list global profile is special, only for use by rebar3
+ %% It does not clash if a user does `rebar3 as global...` but when
+ %% it is the head we must make sure not to prepend `default`
+ [global | _] ->
+ Profiles;
+ _ ->
+ deduplicate(CurrentProfiles ++ Profiles)
+ end,
+
+ ConfigProfiles = rebar_app_info:get(AppInfo, profiles, []),
+
+ NewOpts =
+ lists:foldl(fun(default, OptsAcc) ->
+ OptsAcc;
+ (Profile, OptsAcc) ->
+ case proplists:get_value(Profile, ConfigProfiles, []) of
+ OptsList when is_list(OptsList) ->
+ ProfileOpts = dict:from_list(OptsList),
+ rebar_opts:merge_opts(Profile, ProfileOpts, OptsAcc);
+ Other ->
+ throw(?PRV_ERROR({profile_not_list, Profile, Other}))
+ end
+ end, Defaults, AppliedProfiles),
+ AppInfo#app_info_t{profiles = AppliedProfiles, opts=NewOpts}.
+
+deduplicate(Profiles) ->
+ do_deduplicate(lists:reverse(Profiles), []).
+
+do_deduplicate([], Acc) ->
+ Acc;
+do_deduplicate([Head | Rest], Acc) ->
+ case lists:member(Head, Acc) of
+ true -> do_deduplicate(Rest, Acc);
+ false -> do_deduplicate(Rest, [Head | Acc])
+ end.
diff --git a/src/rebar_app_utils.erl b/src/rebar_app_utils.erl
index a7c78f5..be2b289 100644
--- a/src/rebar_app_utils.erl
+++ b/src/rebar_app_utils.erl
@@ -157,26 +157,24 @@ pkg_to_app(Parent, DepsDir, AppName, PkgName, PkgVsn, IsLock, State) ->
dep_to_app(Parent, DepsDir, Name, Vsn, Source, IsLock, State) ->
CheckoutsDir = ec_cnv:to_list(rebar_dir:checkouts_dir(State, Name)),
- BaseDir = rebar_state:get(State, base_dir, []),
- {ok, App1} = case rebar_app_info:discover(CheckoutsDir) of
- {ok, App} ->
- {ok, rebar_app_info:is_checkout(App, true)};
- not_found ->
- Dir = ec_cnv:to_list(filename:join(DepsDir, Name)),
- case rebar_app_info:discover(Dir) of
- {ok, App} ->
- {ok, rebar_app_info:parent(App, Parent)};
- not_found ->
- rebar_app_info:new(Parent, Name, Vsn, Dir, [])
- end
- end,
- C = rebar_config:consult(rebar_app_info:dir(App1)),
- S = rebar_state:new(rebar_state:new(), C, App1),
+ {ok, AppInfo} = case rebar_app_info:discover(CheckoutsDir) of
+ {ok, App} ->
+ {ok, rebar_app_info:is_checkout(App, true)};
+ not_found ->
+ Dir = ec_cnv:to_list(filename:join(DepsDir, Name)),
+ case rebar_app_info:discover(Dir) of
+ {ok, App} ->
+ {ok, rebar_app_info:parent(App, Parent)};
+ not_found ->
+ rebar_app_info:new(Parent, Name, Vsn, Dir, [])
+ end
+ end,
+ C = rebar_config:consult(rebar_app_info:dir(AppInfo)),
+ AppInfo0 = rebar_app_info:update_opts(AppInfo, rebar_app_info:opts(AppInfo), C),
Overrides = rebar_state:get(State, overrides, []),
- ParentOverrides = rebar_state:overrides(State),
- S1 = rebar_state:set(rebar_state:overrides(S, ParentOverrides++Overrides), base_dir, BaseDir),
- App2 = rebar_app_info:state(App1, S1),
- rebar_app_info:is_lock(rebar_app_info:source(App2, Source), IsLock).
+ AppInfo1 = rebar_app_info:set(AppInfo0, overrides, rebar_app_info:get(AppInfo, overrides, [])++Overrides),
+ AppInfo2 = rebar_app_info:apply_overrides(rebar_app_info:get(AppInfo1, overrides, []), AppInfo1),
+ rebar_app_info:is_lock(rebar_app_info:source(AppInfo2, Source), IsLock).
format_error({missing_package, Package}) ->
io_lib:format("Package not found in registry: ~s", [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_dir.erl b/src/rebar_dir.erl
index 7af94ea..7aeb11e 100644
--- a/src/rebar_dir.erl
+++ b/src/rebar_dir.erl
@@ -129,34 +129,34 @@ do_make_relative_path(Source, Target) ->
Base = lists:duplicate(max(length(Target) - 1, 0), ".."),
filename:join(Base ++ Source).
--spec src_dirs(rebar_state:t()) -> list(file:filename_all()).
-src_dirs(State) -> src_dirs(State, []).
+-spec src_dirs(rebar_dict()) -> list(file:filename_all()).
+src_dirs(Opts) -> src_dirs(Opts, []).
--spec src_dirs(rebar_state:t(), list(file:filename_all())) -> list(file:filename_all()).
-src_dirs(State, Default) ->
- ErlOpts = rebar_utils:erl_opts(State),
+-spec src_dirs(rebar_dict(), list(file:filename_all())) -> list(file:filename_all()).
+src_dirs(Opts, Default) ->
+ ErlOpts = rebar_opts:erl_opts(Opts),
Vs = proplists:get_all_values(src_dirs, ErlOpts),
- case lists:append([rebar_state:get(State, src_dirs, []) | Vs]) of
+ case lists:append([rebar_opts:get(Opts, src_dirs, []) | Vs]) of
[] -> Default;
Dirs -> Dirs
end.
--spec extra_src_dirs(rebar_state:t()) -> list(file:filename_all()).
-extra_src_dirs(State) -> extra_src_dirs(State, []).
+-spec extra_src_dirs(rebar_dict()) -> list(file:filename_all()).
+extra_src_dirs(Opts) -> extra_src_dirs(Opts, []).
--spec extra_src_dirs(rebar_state:t(), list(file:filename_all())) -> list(file:filename_all()).
-extra_src_dirs(State, Default) ->
- ErlOpts = rebar_utils:erl_opts(State),
+-spec extra_src_dirs(rebar_dict(), list(file:filename_all())) -> list(file:filename_all()).
+extra_src_dirs(Opts, Default) ->
+ ErlOpts = rebar_opts:erl_opts(Opts),
Vs = proplists:get_all_values(extra_src_dirs, ErlOpts),
- case lists:append([rebar_state:get(State, extra_src_dirs, []) | Vs]) of
+ case lists:append([rebar_opts:get(Opts, extra_src_dirs, []) | Vs]) of
[] -> Default;
Dirs -> Dirs
end.
--spec all_src_dirs(rebar_state:t()) -> list(file:filename_all()).
-all_src_dirs(State) -> all_src_dirs(State, [], []).
+-spec all_src_dirs(rebar_dict()) -> list(file:filename_all()).
+all_src_dirs(Opts) -> all_src_dirs(Opts, [], []).
--spec all_src_dirs(rebar_state:t(), list(file:filename_all()), list(file:filename_all())) ->
+-spec all_src_dirs(rebar_dict(), list(file:filename_all()), list(file:filename_all())) ->
list(file:filename_all()).
-all_src_dirs(State, SrcDefault, ExtraDefault) ->
- src_dirs(State, SrcDefault) ++ extra_src_dirs(State, ExtraDefault).
+all_src_dirs(Opts, SrcDefault, ExtraDefault) ->
+ src_dirs(Opts, SrcDefault) ++ extra_src_dirs(Opts, ExtraDefault).
diff --git a/src/rebar_erlc_compiler.erl b/src/rebar_erlc_compiler.erl
index 90193da..0fc5455 100644
--- a/src/rebar_erlc_compiler.erl
+++ b/src/rebar_erlc_compiler.erl
@@ -26,7 +26,7 @@
%% -------------------------------------------------------------------
-module(rebar_erlc_compiler).
--export([compile/2,
+-export([compile/1,
compile/3,
clean/2]).
@@ -80,31 +80,32 @@
%% 'old_inets'}]}.
%%
--spec compile(rebar_state:t(), file:name()) -> 'ok'.
-compile(Config, Dir) ->
- compile(Config, Dir, filename:join([Dir, "ebin"])).
+-spec compile(rebar_app_info:t()) -> 'ok'.
+compile(AppInfo) ->
+ Dir = ec_cnv:to_list(rebar_app_info:out_dir(AppInfo)),
+ compile(rebar_app_info:opts(AppInfo), Dir, filename:join([Dir, "ebin"])).
--spec compile(rebar_state:t(), file:name(), file:name()) -> 'ok'.
-compile(Config, Dir, OutDir) ->
- rebar_base_compiler:run(Config,
- check_files(rebar_state:get(
- Config, xrl_first_files, [])),
+-spec compile(rebar_dict(), file:name(), file:name()) -> 'ok'.
+compile(Opts, Dir, OutDir) ->
+ rebar_base_compiler:run(Opts,
+ check_files(rebar_opts:get(
+ Opts, xrl_first_files, [])),
filename:join(Dir, "src"), ".xrl", filename:join(Dir, "src"), ".erl",
fun compile_xrl/3),
- rebar_base_compiler:run(Config,
- check_files(rebar_state:get(
- Config, yrl_first_files, [])),
+ rebar_base_compiler:run(Opts,
+ check_files(rebar_opts:get(
+ Opts, yrl_first_files, [])),
filename:join(Dir, "src"), ".yrl", filename:join(Dir, "src"), ".erl",
fun compile_yrl/3),
- rebar_base_compiler:run(Config,
- check_files(rebar_state:get(
- Config, mib_first_files, [])),
+ rebar_base_compiler:run(Opts,
+ check_files(rebar_opts:get(
+ Opts, mib_first_files, [])),
filename:join(Dir, "mibs"), ".mib", filename:join([Dir, "priv", "mibs"]), ".bin",
fun compile_mib/3),
- doterl_compile(Config, Dir, OutDir).
+ doterl_compile(Opts, Dir, OutDir).
--spec clean(rebar_state:t(), file:filename()) -> 'ok'.
-clean(_Config, AppDir) ->
+-spec clean(rebar_dict(), file:filename()) -> 'ok'.
+clean(_Opts, AppDir) ->
MibFiles = rebar_utils:find_files(filename:join(AppDir, "mibs"), ?RE_PREFIX".*\\.mib\$"),
MIBs = [filename:rootname(filename:basename(MIB)) || MIB <- MibFiles],
rebar_file_utils:delete_each(
@@ -133,17 +134,17 @@ clean(_Config, AppDir) ->
%% Internal functions
%% ===================================================================
--spec doterl_compile(rebar_state:t(), file:filename(), file:filename()) -> ok.
-doterl_compile(State, Dir, ODir) ->
- ErlOpts = rebar_utils:erl_opts(State),
- doterl_compile(State, Dir, ODir, [], ErlOpts).
+-spec doterl_compile(rebar_dict(), file:filename(), file:filename()) -> ok.
+doterl_compile(Opts, Dir, ODir) ->
+ ErlOpts = rebar_opts:erl_opts(Opts),
+ doterl_compile(Opts, Dir, ODir, [], ErlOpts).
-doterl_compile(Config, Dir, OutDir, MoreSources, ErlOpts) ->
+doterl_compile(Opts, Dir, OutDir, MoreSources, ErlOpts) ->
?DEBUG("erl_opts ~p", [ErlOpts]),
%% Support the src_dirs option allowing multiple directories to
%% contain erlang source. This might be used, for example, should
%% eunit tests be separated from the core application source.
- SrcDirs = [filename:join(Dir, X) || X <- rebar_dir:all_src_dirs(Config, ["src"], [])],
+ SrcDirs = [filename:join(Dir, X) || X <- rebar_dir:all_src_dirs(Opts, ["src"], [])],
AllErlFiles = gather_src(SrcDirs, []) ++ MoreSources,
%% Make sure that ebin/ exists and is on the path
@@ -155,7 +156,7 @@ doterl_compile(Config, Dir, OutDir, MoreSources, ErlOpts) ->
G = init_erlcinfo(proplists:get_all_values(i, ErlOpts), AllErlFiles, Dir, OutDir),
NeededErlFiles = needed_files(G, ErlOpts, Dir, OutDir1, AllErlFiles),
- {ErlFirstFiles, ErlOptsFirst} = erl_first_files(Config, ErlOpts, Dir, NeededErlFiles),
+ {ErlFirstFiles, ErlOptsFirst} = erl_first_files(Opts, ErlOpts, Dir, NeededErlFiles),
{DepErls, OtherErls} = lists:partition(
fun(Source) -> digraph:in_degree(G, Source) > 0 end,
[File || File <- NeededErlFiles, not lists:member(File, ErlFirstFiles)]),
@@ -165,7 +166,7 @@ doterl_compile(Config, Dir, OutDir, MoreSources, ErlOpts) ->
?DEBUG("Files to compile first: ~p", [FirstErls]),
try
rebar_base_compiler:run(
- Config, FirstErls, OtherErls,
+ Opts, FirstErls, OtherErls,
fun(S, C) ->
ErlOpts1 = case lists:member(S, ErlFirstFiles) of
true -> ErlOptsFirst;
@@ -182,8 +183,8 @@ doterl_compile(Config, Dir, OutDir, MoreSources, ErlOpts) ->
%% Get files which need to be compiled first, i.e. those specified in erl_first_files
%% and parse_transform options. Also produce specific erl_opts for these first
%% files, so that yet to be compiled parse transformations are excluded from it.
-erl_first_files(Config, ErlOpts, Dir, NeededErlFiles) ->
- ErlFirstFilesConf = rebar_state:get(Config, erl_first_files, []),
+erl_first_files(Opts, ErlOpts, Dir, NeededErlFiles) ->
+ ErlFirstFilesConf = rebar_opts:get(Opts, erl_first_files, []),
NeededSrcDirs = lists:usort(lists:map(fun filename:dirname/1, NeededErlFiles)),
%% NOTE: order of files here is important!
ErlFirstFiles =
@@ -208,10 +209,10 @@ needed_files(G, ErlOpts, Dir, OutDir, SourceFiles) ->
lists:filter(fun(Source) ->
TargetBase = target_base(OutDir, Source),
Target = TargetBase ++ ".beam",
- Opts = [{outdir, filename:dirname(Target)}
- ,{i, filename:join(Dir, "include")}] ++ ErlOpts,
+ AllOpts = [{outdir, filename:dirname(Target)}
+ ,{i, filename:join(Dir, "include")}] ++ ErlOpts,
digraph:vertex(G, Source) > {Source, filelib:last_modified(Target)}
- orelse opts_changed(Opts, TargetBase)
+ orelse opts_changed(AllOpts, TargetBase)
end, SourceFiles).
maybe_rm_beam_and_edge(G, OutDir, Source) ->
@@ -402,40 +403,40 @@ expand_file_names(Files, Dirs) ->
end, Files).
--spec internal_erl_compile(rebar_state:t(), file:filename(), file:filename(),
+-spec internal_erl_compile(rebar_dict(), file:filename(), file:filename(),
file:filename(), list()) -> ok | {ok, any()} | {error, any(), any()}.
-internal_erl_compile(Config, Dir, Module, OutDir, ErlOpts) ->
+internal_erl_compile(_Opts, Dir, Module, OutDir, ErlOpts) ->
Target = target_base(OutDir, Module) ++ ".beam",
ok = filelib:ensure_dir(Target),
- Opts = [{outdir, filename:dirname(Target)}] ++ ErlOpts ++
+ AllOpts = [{outdir, filename:dirname(Target)}] ++ ErlOpts ++
[{i, filename:join(Dir, "include")}, return],
- case compile:file(Module, Opts) of
+ case compile:file(Module, AllOpts) of
{ok, _Mod} ->
ok;
{ok, _Mod, Ws} ->
- rebar_base_compiler:ok_tuple(Config, Module, Ws);
+ rebar_base_compiler:ok_tuple(Module, Ws);
{error, Es, Ws} ->
- rebar_base_compiler:error_tuple(Config, Module, Es, Ws, Opts)
+ rebar_base_compiler:error_tuple(Module, Es, Ws, AllOpts)
end.
target_base(OutDir, Source) ->
filename:join(OutDir, filename:basename(Source, ".erl")).
-spec compile_mib(file:filename(), file:filename(),
- rebar_state:t()) -> 'ok'.
-compile_mib(Source, Target, Config) ->
- Dir = rebar_state:dir(Config),
+ rebar_dict()) -> 'ok'.
+compile_mib(Source, Target, Opts) ->
+ Dir = filename:dirname(Target),
ok = filelib:ensure_dir(Target),
ok = filelib:ensure_dir(filename:join([Dir, "include", "dummy.hrl"])),
- Opts = [{outdir, filename:join([Dir, "priv", "mibs"])}
- ,{i, [filename:join([Dir, "priv", "mibs"])]}] ++
- rebar_state:get(Config, mib_opts, []),
+ AllOpts = [{outdir, Dir}
+ ,{i, [Dir]}] ++
+ rebar_opts:get(Opts, mib_opts, []),
- case snmpc:compile(Source, Opts) of
+ case snmpc:compile(Source, AllOpts) of
{ok, _} ->
Mib = filename:rootname(Target),
MibToHrlOpts =
- case proplists:get_value(verbosity, Opts, undefined) of
+ case proplists:get_value(verbosity, AllOpts, undefined) of
undefined ->
#options{specific = []};
Verbosity ->
@@ -450,33 +451,34 @@ compile_mib(Source, Target, Config) ->
end.
-spec compile_xrl(file:filename(), file:filename(),
- rebar_state:t()) -> 'ok'.
-compile_xrl(Source, Target, Config) ->
- Opts = [{scannerfile, Target} | rebar_state:get(Config, xrl_opts, [])],
- compile_xrl_yrl(Config, Source, Target, Opts, leex).
+ rebar_dict()) -> 'ok'.
+compile_xrl(Source, Target, Opts) ->
+ AllOpts = [{scannerfile, Target} | rebar_opts:get(Opts, xrl_opts, [])],
+ compile_xrl_yrl(Opts, Source, Target, AllOpts, leex).
-spec compile_yrl(file:filename(), file:filename(),
- rebar_state:t()) -> 'ok'.
-compile_yrl(Source, Target, Config) ->
- Opts = [{parserfile, Target} | rebar_state:get(Config, yrl_opts, [])],
- compile_xrl_yrl(Config, Source, Target, Opts, yecc).
+ rebar_dict()) -> 'ok'.
+compile_yrl(Source, Target, Opts) ->
+ AllOpts = [{parserfile, Target} | rebar_opts:get(Opts, yrl_opts, [])],
+ compile_xrl_yrl(Opts, Source, Target, AllOpts, yecc).
--spec compile_xrl_yrl(rebar_state:t(), file:filename(),
+-spec compile_xrl_yrl(rebar_dict(), file:filename(),
file:filename(), list(), module()) -> 'ok'.
-compile_xrl_yrl(Config, Source, Target, Opts, Mod) ->
- Dir = rebar_state:dir(Config),
- Opts1 = [{includefile, filename:join(Dir, I)} || {includefile, I} <- Opts,
- filename:pathtype(I) =:= relative],
+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
true ->
- case Mod:file(Source, Opts1 ++ [{return, true}]) of
+ case Mod:file(Source, AllOpts1 ++ [{return, true}]) of
{ok, _} ->
ok;
{ok, _Mod, Ws} ->
- rebar_base_compiler:ok_tuple(Config, Source, Ws);
+ rebar_base_compiler:ok_tuple(Source, Ws);
{error, Es, Ws} ->
- rebar_base_compiler:error_tuple(Config, Source,
- Es, Ws, Opts1)
+ rebar_base_compiler:error_tuple(Source,
+ Es, Ws, AllOpts1)
end;
false ->
skipped
diff --git a/src/rebar_hooks.erl b/src/rebar_hooks.erl
index 857336c..6db3c77 100644
--- a/src/rebar_hooks.erl
+++ b/src/rebar_hooks.erl
@@ -1,6 +1,7 @@
-module(rebar_hooks).
-export([run_all_hooks/5
+ ,run_all_hooks/6
,format_error/1]).
-include("rebar.hrl").
@@ -8,29 +9,32 @@
-spec run_all_hooks(file:filename_all(), pre | post,
atom() | {atom(), atom()} | string(),
- [providers:t()], rebar_state:t()) -> ok.
+ [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, 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, State),
- run_hooks(Dir, Type, Command, 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, State) ->
- case rebar_state:get(State, provider_hooks, []) of
+run_provider_hooks(Dir, Type, Command, Providers, Opts, State) ->
+ case rebar_opts:get(Opts, provider_hooks, []) of
[] ->
ok;
AllHooks ->
TypeHooks = proplists:get_value(Type, AllHooks, []),
- run_provider_hooks(Dir, Type, Command, Providers, TypeHooks, State)
+ run_provider_hooks_(Dir, Type, Command, Providers, TypeHooks, rebar_state:opts(State, Opts))
end.
-run_provider_hooks(_Dir, _Type, _Command, _Providers, [], _State) ->
+run_provider_hooks_(_Dir, _Type, _Command, _Providers, [], _State) ->
ok;
-run_provider_hooks(Dir, Type, Command, Providers, TypeHooks, 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),
State1 = rebar_state:providers(rebar_state:dir(State, Dir), Providers++Providers1),
HookProviders = proplists:get_all_values(Command, TypeHooks),
-
case rebar_core:do(HookProviders, State1) of
{error, ProviderName} ->
?DEBUG(format_error({bad_provider, Type, Command, ProviderName}), []),
@@ -67,16 +71,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, State) ->
- run_hooks(Dir, pre_hooks, Command, State);
-run_hooks(Dir, post, Command, State) ->
- run_hooks(Dir, post_hooks, Command, State);
-run_hooks(Dir, Type, Command, State) ->
- case rebar_state:get(State, 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_opts:get(Opts, Type, []) of
[] ->
ok;
Hooks ->
- Env = create_env(State),
+ Env = create_env(State, Opts),
lists:foreach(fun({_, C, _}=Hook) when C =:= Command ->
apply_hook(Dir, Env, Hook);
({C, _}=Hook) when C =:= Command ->
@@ -97,8 +101,8 @@ 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) ->
- BaseDir = rebar_state:dir(State),
+create_env(State, Opts) ->
+ BaseDir = rebar_dir:base_dir(State),
[
{"REBAR_DEPS_DIR", filename:absname(rebar_dir:deps_dir(State))},
{"REBAR_BUILD_DIR", filename:absname(rebar_dir:base_dir(State))},
@@ -109,7 +113,7 @@ create_env(State) ->
{"REBAR_GLOBAL_CACHE_DIR", filename:absname(rebar_dir:global_cache_dir(State))},
{"REBAR_TEMPLATE_DIR", filename:absname(rebar_dir:template_dir(State))},
{"REBAR_APP_DIRS", join_dirs(BaseDir, rebar_dir:lib_dirs(State))},
- {"REBAR_SRC_DIRS", join_dirs(BaseDir, rebar_dir:all_src_dirs(State))},
+ {"REBAR_SRC_DIRS", join_dirs(BaseDir, rebar_dir:all_src_dirs(Opts))},
{"ERLANG_ERTS_VER", erlang:system_info(version)},
{"ERLANG_ROOT_DIR", code:root_dir()},
{"ERLANG_LIB_DIR_erl_interface", code:lib_dir(erl_interface)},
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]).
diff --git a/src/rebar_otp_app.erl b/src/rebar_otp_app.erl
index 507da70..c1d90bc 100644
--- a/src/rebar_otp_app.erl
+++ b/src/rebar_otp_app.erl
@@ -106,7 +106,7 @@ preprocess(State, AppInfo, AppSrcFile) ->
%% substitute. Note that we include the list of modules available in
%% ebin/ and update the app data accordingly.
OutDir = rebar_app_info:out_dir(AppInfo),
- AppVars = load_app_vars(State) ++ [{modules, ebin_modules(State, AppInfo, OutDir)}],
+ AppVars = load_app_vars(State) ++ [{modules, ebin_modules(AppInfo, OutDir)}],
A1 = apply_app_vars(AppVars, AppData),
%% AppSrcFile may contain instructions for generating a vsn number
@@ -158,21 +158,21 @@ validate_name(AppName, File) ->
?PRV_ERROR({invalid_name, File, AppName})
end.
-ebin_modules(State, App, Dir) ->
+ebin_modules(AppInfo, Dir) ->
Beams = lists:sort(rebar_utils:beams(filename:join(Dir, "ebin"))),
- ExtraDirs = extra_dirs(State),
- F = fun(Beam) -> not in_extra_dir(App, Beam, ExtraDirs) end,
+ ExtraDirs = extra_dirs(AppInfo),
+ F = fun(Beam) -> not in_extra_dir(AppInfo, Beam, ExtraDirs) end,
Filtered = lists:filter(F, Beams),
[rebar_utils:beam_to_mod(N) || N <- Filtered].
extra_dirs(State) ->
- Extras = rebar_dir:extra_src_dirs(State),
- SrcDirs = rebar_dir:src_dirs(State, ["src"]),
+ Extras = rebar_dir:extra_src_dirs(rebar_app_info:opts(State)),
+ SrcDirs = rebar_dir:src_dirs(rebar_app_info:opts(State), ["src"]),
%% remove any dirs that are defined in `src_dirs` from `extra_src_dirs`
Extras -- SrcDirs.
-in_extra_dir(App, Beam, Dirs) ->
- lists:any(fun(Dir) -> lists:prefix(filename:join([rebar_app_info:out_dir(App), Dir]),
+in_extra_dir(AppInfo, Beam, Dirs) ->
+ lists:any(fun(Dir) -> lists:prefix(filename:join([rebar_app_info:out_dir(AppInfo), Dir]),
beam_src(Beam)) end,
Dirs).
diff --git a/src/rebar_plugins.erl b/src/rebar_plugins.erl
index 6c2daef..80f62f5 100644
--- a/src/rebar_plugins.erl
+++ b/src/rebar_plugins.erl
@@ -4,7 +4,7 @@
-module(rebar_plugins).
-export([project_apps_install/1
- ,install/1
+ ,install/2
,handle_plugins/3
,handle_plugins/4]).
@@ -23,20 +23,19 @@ project_apps_install(State) ->
Plugins = rebar_state:get(State, {plugins, Profile}, []),
StateAcc1 = handle_plugins(Profile, Plugins, StateAcc),
- lists:foldl(fun(App, StateAcc2) ->
- AppDir = rebar_app_info:dir(App),
- C = rebar_config:consult(AppDir),
- S = rebar_state:new(rebar_state:new(), C, AppDir),
- Plugins2 = rebar_state:get(S, {plugins, Profile}, []),
+ lists:foldl(fun(AppInfo, StateAcc2) ->
+ C = rebar_config:consult(rebar_app_info:dir(AppInfo)),
+ AppInfo0 = rebar_app_info:update_opts(AppInfo, rebar_app_info:opts(AppInfo), C),
+ Plugins2 = rebar_state:get(AppInfo0, {plugins, Profile}, []),
handle_plugins(Profile, Plugins2, StateAcc2)
end, StateAcc1, ProjectApps)
end, State, Profiles).
--spec install(rebar_state:t()) -> rebar_state:t().
-install(State) ->
+-spec install(rebar_state:t(), rebar_app_info:t()) -> rebar_state:t().
+install(State, AppInfo) ->
Profiles = rebar_state:current_profiles(State),
lists:foldl(fun(Profile, StateAcc) ->
- Plugins = rebar_state:get(State, {plugins, Profile}, []),
+ Plugins = rebar_app_info:get(AppInfo, {plugins, Profile}, []),
handle_plugins(Profile, Plugins, StateAcc)
end, State, Profiles).
@@ -92,10 +91,11 @@ handle_plugin(Profile, Plugin, State, Upgrade) ->
build_plugin(AppInfo, Apps, State) ->
Providers = rebar_state:providers(State),
- Providers1 = rebar_state:providers(rebar_app_info:state(AppInfo)),
- S = rebar_state:all_deps(rebar_app_info:state_or_new(State, AppInfo), Apps),
+ %Providers1 = rebar_state:providers(rebar_app_info:state(AppInfo)),
+ %rebar_app_info:state_or_new(State, AppInfo)
+ S = rebar_state:all_deps(State, Apps),
S1 = rebar_state:set(S, deps_dir, ?DEFAULT_PLUGINS_DIR),
- rebar_prv_compile:compile(S1, Providers++Providers1, AppInfo).
+ rebar_prv_compile:compile(S1, Providers, AppInfo).
plugin_providers({Plugin, _, _, _}) when is_atom(Plugin) ->
validate_plugin(Plugin);
diff --git a/src/rebar_prv_clean.erl b/src/rebar_prv_clean.erl
index f10d12b..503291d 100644
--- a/src/rebar_prv_clean.erl
+++ b/src/rebar_prv_clean.erl
@@ -44,10 +44,7 @@ do(State) ->
DepApps = []
end,
- %% 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, Providers, DepApps),
+ clean_apps(State, Providers, DepApps),
Cwd = rebar_dir:get_cwd(),
rebar_hooks:run_all_hooks(Cwd, pre, ?PROVIDER, Providers, State),
@@ -66,13 +63,11 @@ format_error(Reason) ->
clean_apps(State, Providers, Apps) ->
lists:foreach(fun(AppInfo) ->
- AppDir = rebar_app_info:dir(AppInfo),
- S = rebar_app_info:state_or_new(State, AppInfo),
-
?INFO("Cleaning out ~s...", [rebar_app_info:name(AppInfo)]),
- rebar_hooks:run_all_hooks(AppDir, pre, ?PROVIDER, Providers, S),
+ AppDir = rebar_app_info:dir(AppInfo),
+ rebar_hooks:run_all_hooks(AppDir, pre, ?PROVIDER, Providers, AppInfo, State),
rebar_erlc_compiler:clean(State, rebar_app_info:out_dir(AppInfo)),
- rebar_hooks:run_all_hooks(AppDir, post, ?PROVIDER, Providers, S)
+ rebar_hooks:run_all_hooks(AppDir, post, ?PROVIDER, Providers, AppInfo, State)
end, Apps).
handle_args(State) ->
diff --git a/src/rebar_prv_common_test.erl b/src/rebar_prv_common_test.erl
index 25e9dad..aafc425 100644
--- a/src/rebar_prv_common_test.erl
+++ b/src/rebar_prv_common_test.erl
@@ -43,12 +43,12 @@ do(State) ->
%% Run ct provider prehooks
Providers = rebar_state:providers(State),
Cwd = rebar_dir:get_cwd(),
- rebar_hooks:run_all_hooks(Cwd, pre, ?PROVIDER, Providers, State),
+ rebar_hooks:run_all_hooks(Cwd, pre, ?PROVIDER, Providers, element(2,rebar_app_info:new(noen)), State),
try run_test(State) of
{ok, State1} = Result ->
%% Run ct provider posthooks
- rebar_hooks:run_all_hooks(Cwd, post, ?PROVIDER, Providers, State1),
+ rebar_hooks:run_all_hooks(Cwd, post, ?PROVIDER, Providers, element(2,rebar_app_info:new(noen)), State1),
rebar_utils:cleanup_code_path(rebar_state:code_paths(State, default)),
Result;
?PRV_ERROR(_) = Error ->
@@ -307,7 +307,7 @@ copy(State, Dir) ->
compile_dir(State, Dir) ->
NewState = replace_src_dirs(State, [filename:absname(Dir)]),
- ok = rebar_erlc_compiler:compile(NewState, rebar_dir:base_dir(State), Dir),
+ ok = rebar_erlc_compiler:compile(rebar_state:opts(NewState), rebar_dir:base_dir(State), Dir),
ok = maybe_cover_compile(State, Dir),
Dir.
diff --git a/src/rebar_prv_compile.erl b/src/rebar_prv_compile.erl
index 74be7a6..56e5e84 100644
--- a/src/rebar_prv_compile.erl
+++ b/src/rebar_prv_compile.erl
@@ -42,13 +42,7 @@ do(State) ->
Deps = rebar_state:deps_to_build(State),
Cwd = rebar_state:dir(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),
-
+ build_apps(State, Providers, Deps),
{ok, ProjectApps1} = rebar_digraph:compile_order(ProjectApps),
%% Run top level hooks *before* project apps compiled but *after* deps are
@@ -61,8 +55,12 @@ do(State) ->
State3 = rebar_state:code_paths(State2, all_deps, DepsPaths ++ ProjAppsPaths),
rebar_hooks:run_all_hooks(Cwd, post, ?PROVIDER, Providers, State2),
- has_all_artifacts(State3),
-
+ 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)),
@@ -80,22 +78,19 @@ build_apps(State, Providers, Apps) ->
build_app(State, Providers, AppInfo) ->
AppDir = rebar_app_info:dir(AppInfo),
OutDir = rebar_app_info:out_dir(AppInfo),
- copy_app_dirs(State, AppDir, OutDir),
-
- S = rebar_app_info:state_or_new(State, AppInfo),
- S1 = rebar_state:all_deps(S, rebar_state:all_deps(State)),
- compile(S1, Providers, AppInfo).
+ copy_app_dirs(AppInfo, AppDir, OutDir),
+ compile(State, Providers, AppInfo).
compile(State, Providers, AppInfo) ->
?INFO("Compiling ~s", [rebar_app_info:name(AppInfo)]),
AppDir = rebar_app_info:dir(AppInfo),
- rebar_hooks:run_all_hooks(AppDir, pre, ?PROVIDER, Providers, State),
+ rebar_hooks:run_all_hooks(AppDir, pre, ?PROVIDER, Providers, AppInfo, State),
- rebar_erlc_compiler:compile(State, ec_cnv:to_list(rebar_app_info:out_dir(AppInfo))),
+ rebar_erlc_compiler:compile(AppInfo),
case rebar_otp_app:compile(State, AppInfo) of
{ok, AppInfo1} ->
- rebar_hooks:run_all_hooks(AppDir, post, ?PROVIDER, Providers, State),
- has_all_artifacts(State),
+ rebar_hooks:run_all_hooks(AppDir, post, ?PROVIDER, Providers, AppInfo, State),
+ has_all_artifacts(AppInfo1),
AppInfo1;
Error ->
throw(Error)
@@ -105,15 +100,15 @@ 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 ->
true
end.
-copy_app_dirs(State, OldAppDir, AppDir) ->
+copy_app_dirs(AppInfo, OldAppDir, AppDir) ->
case ec_cnv:to_binary(filename:absname(OldAppDir)) =/=
ec_cnv:to_binary(filename:absname(AppDir)) of
true ->
@@ -142,7 +137,7 @@ copy_app_dirs(State, OldAppDir, AppDir) ->
end,
%% link to src_dirs to be adjacent to ebin is needed for R15 use of cover/xref
- SrcDirs = rebar_dir:all_src_dirs(State, ["src"], []),
+ SrcDirs = rebar_dir:all_src_dirs(rebar_app_info:opts(AppInfo), ["src"], []),
[symlink_or_copy(OldAppDir, AppDir, Dir) || Dir <- ["priv", "include"] ++ SrcDirs];
false ->
ok
diff --git a/src/rebar_prv_install_deps.erl b/src/rebar_prv_install_deps.erl
index ca9344b..fd1aa49 100644
--- a/src/rebar_prv_install_deps.erl
+++ b/src/rebar_prv_install_deps.erl
@@ -253,29 +253,30 @@ update_unseen_dep(AppInfo, Profile, Level, Deps, Apps, State, Upgrade, Seen, Loc
handle_dep(State, Profile, DepsDir, AppInfo, Locks, Level) ->
Profiles = rebar_state:current_profiles(State),
Name = rebar_app_info:name(AppInfo),
-
- %% Deps may be under a sub project app, find it and use its state if so
- S = rebar_app_info:state(AppInfo),
C = rebar_config:consult(rebar_app_info:dir(AppInfo)),
- S1 = rebar_state:new(S, C, AppInfo),
- S2 = rebar_state:apply_overrides(S1, Name),
- S3 = rebar_state:apply_profiles(S2, Profiles),
- Plugins = rebar_state:get(S3, plugins, []),
- S4 = rebar_state:set(S3, {plugins, Profile}, Plugins),
+ AppInfo0 = rebar_app_info:update_opts(AppInfo, rebar_app_info:opts(AppInfo), C),
+ AppInfo1 = rebar_app_info:apply_overrides(rebar_app_info:get(AppInfo, overrides, []), AppInfo0),
+ AppInfo2 = rebar_app_info:apply_profiles(AppInfo1, Profiles),
+
+ Plugins = rebar_app_info:get(AppInfo2, plugins, []),
+ AppInfo3 = rebar_app_info:set(AppInfo2, {plugins, Profile}, Plugins),
- rebar_utils:check_min_otp_version(rebar_state:get(S4, minimum_otp_vsn, undefined)),
- rebar_utils:check_blacklisted_otp_versions(rebar_state:get(S4, blacklisted_otp_vsns, [])),
+ %% Will throw an exception if checks fail
+ rebar_app_info:verify_otp_vsn(AppInfo3),
%% Dep may have plugins to install. Find and install here.
- S5 = rebar_plugins:install(S4),
- AppInfo1 = rebar_app_info:state(AppInfo, S5),
+ State1 = rebar_plugins:install(State, AppInfo3),
%% Upgrade lock level to be the level the dep will have in this dep tree
- Deps = rebar_state:get(S5, {deps, default}, []),
- AppInfo2 = rebar_app_info:deps(AppInfo1, rebar_state:deps_names(Deps)),
- Deps1 = rebar_app_utils:parse_deps(Name, DepsDir, Deps, S5, Locks, Level+1),
- {AppInfo2, Deps1, State}.
+ Deps = rebar_app_info:get(AppInfo3, {deps, default}, []),
+ AppInfo4 = rebar_app_info:deps(AppInfo3, rebar_state:deps_names(Deps)),
+
+ %% Keep all overrides from the global config and this dep when parsing its deps
+ Overrides = rebar_app_info:get(AppInfo0, overrides, []),
+ Deps1 = rebar_app_utils:parse_deps(Name, DepsDir, Deps, rebar_state:set(State, overrides, Overrides)
+ ,Locks, Level+1),
+ {AppInfo4, Deps1, State1}.
-spec maybe_fetch(rebar_app_info:t(), atom(), boolean(),
sets:set(binary()), rebar_state:t()) -> {boolean(), rebar_app_info:t()}.
@@ -286,24 +287,20 @@ maybe_fetch(AppInfo, Profile, Upgrade, Seen, State) ->
true ->
{false, AppInfo};
false ->
- case rebar_app_discover:find_app(AppDir, all) of
+ case rebar_app_discover:find_app(AppInfo, AppDir, all) of
false ->
true = fetch_app(AppInfo, AppDir, State),
maybe_symlink_default(State, Profile, AppDir, AppInfo),
{true, rebar_app_info:valid(update_app_info(AppDir, AppInfo), false)};
{true, AppInfo1} ->
- %% Preserve the state we created with overrides
- AppInfo2 = copy_app_info(AppInfo, AppInfo1),
- AppState = rebar_app_info:state(AppInfo),
- AppInfo3 = rebar_app_info:state(AppInfo2, AppState),
- case sets:is_element(rebar_app_info:name(AppInfo3), Seen) of
+ case sets:is_element(rebar_app_info:name(AppInfo1), Seen) of
true ->
- {false, AppInfo3};
+ {false, AppInfo1};
false ->
- maybe_symlink_default(State, Profile, AppDir, AppInfo3),
+ maybe_symlink_default(State, Profile, AppDir, AppInfo1),
MaybeUpgrade = maybe_upgrade(AppInfo, AppDir, Upgrade, State),
- AppInfo4 = update_app_info(AppDir, AppInfo3),
- {MaybeUpgrade, AppInfo4}
+ AppInfo2 = update_app_info(AppDir, AppInfo1),
+ {MaybeUpgrade, AppInfo2}
end
end
end.
@@ -360,32 +357,13 @@ fetch_app(AppInfo, AppDir, State) ->
%% So this is the first time for newly downloaded apps that its .app/.app.src data can
%% be read in an parsed.
update_app_info(AppDir, AppInfo) ->
- case rebar_app_info:discover(AppDir) of
- {ok, Found} ->
- AppDetails = rebar_app_info:app_details(Found),
- Vsn = rebar_app_info:original_vsn(Found),
- Applications = proplists:get_value(applications, AppDetails, []),
- IncludedApplications = proplists:get_value(included_applications, AppDetails, []),
- AppInfo1 = rebar_app_info:original_vsn(rebar_app_info:applications(
- rebar_app_info:app_details(AppInfo, AppDetails),
- IncludedApplications++Applications), Vsn),
- AppInfo2 = copy_app_info(AppInfo, AppInfo1),
- rebar_app_info:valid(AppInfo2, undefined);
- not_found ->
+ case rebar_app_discover:find_app(AppInfo, AppDir, all) of
+ {true, AppInfo1} ->
+ AppInfo1;
+ false ->
throw(?PRV_ERROR({dep_app_not_found, AppDir, rebar_app_info:name(AppInfo)}))
end.
-copy_app_info(OldAppInfo, NewAppInfo) ->
- Deps = rebar_app_info:deps(OldAppInfo),
- ResourceType = rebar_app_info:resource_type(OldAppInfo),
- Parent = rebar_app_info:parent(OldAppInfo),
- Source = rebar_app_info:source(OldAppInfo),
-
- rebar_app_info:deps(
- rebar_app_info:resource_type(
- rebar_app_info:source(
- rebar_app_info:parent(NewAppInfo, Parent), Source), ResourceType), Deps).
-
maybe_upgrade(AppInfo, AppDir, Upgrade, State) ->
Source = rebar_app_info:source(AppInfo),
case Upgrade orelse rebar_app_info:is_lock(AppInfo) of
@@ -420,4 +398,4 @@ warn_skip_deps(AppInfo, State) ->
not_needs_compile(App) ->
not(rebar_app_info:is_checkout(App))
andalso rebar_app_info:valid(App)
- andalso rebar_state:has_all_artifacts(rebar_app_info:state(App)) =:= true.
+ andalso rebar_app_info:has_all_artifacts(App) =:= true.
diff --git a/src/rebar_prv_plugins_upgrade.erl b/src/rebar_prv_plugins_upgrade.erl
index fabfa5b..f946f40 100644
--- a/src/rebar_prv_plugins_upgrade.erl
+++ b/src/rebar_prv_plugins_upgrade.erl
@@ -91,5 +91,6 @@ build_plugin(AppInfo, Apps, State) ->
Providers = rebar_state:providers(State),
AppDir = rebar_app_info:dir(AppInfo),
C = rebar_config:consult(AppDir),
- S = rebar_state:new(rebar_state:all_deps(rebar_state:new(), Apps), C, AppInfo),
- rebar_prv_compile:compile(S, Providers, AppInfo).
+ S = rebar_state:new(rebar_state:all_deps(rebar_state:new(), Apps), C, AppDir),
+ AppInfo1 = rebar_app_info:update_opts(AppInfo, rebar_app_info:opts(AppInfo), C),
+ rebar_prv_compile:compile(S, Providers, AppInfo1).
diff --git a/src/rebar_state.erl b/src/rebar_state.erl
index e31b01b..2a5aa01 100644
--- a/src/rebar_state.erl
+++ b/src/rebar_state.erl
@@ -35,8 +35,6 @@
deps_names/1,
- overrides/1, overrides/2,
- apply_overrides/2,
resources/1, resources/2, add_resource/2,
providers/1, providers/2, add_provider/2]).
@@ -62,7 +60,6 @@
all_plugin_deps = [] :: [rebar_app_info:t()],
all_deps = [] :: [rebar_app_info:t()],
- overrides = [],
resources = [],
providers = []}).
@@ -97,19 +94,9 @@ new(ParentState=#state_t{}, Config) ->
Dir = rebar_dir:get_cwd(),
new(ParentState, Config, Dir).
--spec new(t(), list(), rebar_app_info:t() | file:filename_all()) -> t().
-new(ParentState, Config, Dir) when is_list(Dir) ->
- new(ParentState, Config, deps_from_config(Dir, Config), Dir);
-new(ParentState, Config, AppInfo) ->
- Dir = rebar_app_info:dir(AppInfo),
- DepLocks = case rebar_app_info:resource_type(AppInfo) of
- pkg ->
- Deps = rebar_app_info:deps(AppInfo),
- [{{locks, default}, Deps}, {{deps, default}, Deps}];
- _ ->
- deps_from_config(Dir, Config)
- end,
- new(ParentState, Config, DepLocks, Dir).
+-spec new(t(), list(), file:filename_all()) -> t().
+new(ParentState, Config, Dir) ->
+ new(ParentState, Config, deps_from_config(Dir, Config), Dir).
new(ParentState, Config, Deps, Dir) ->
Opts = ParentState#state_t.opts,
@@ -118,7 +105,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_opts:merge_opts(LocalOpts, Opts),
ParentState#state_t{dir=Dir
,opts=NewOpts
@@ -253,51 +240,9 @@ command_parsed_args(#state_t{command_parsed_args=CmdArgs}) ->
command_parsed_args(State, CmdArgs) ->
State#state_t{command_parsed_args=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}.
-
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_opts: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 +268,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_opts:merge_opts(Profile, ProfileOpts, OptsAcc);
Other ->
throw(?PRV_ERROR({profile_not_list, Profile, Other}))
end
@@ -341,53 +286,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.
@@ -404,12 +302,6 @@ deps_names(State) ->
Deps = rebar_state:get(State, deps, []),
deps_names(Deps).
-overrides(#state_t{overrides=Overrides}) ->
- Overrides.
-
-overrides(State=#state_t{}, Overrides) ->
- State#state_t{overrides=Overrides}.
-
project_apps(#state_t{project_apps=Apps}) ->
Apps.
diff --git a/src/rebar_utils.erl b/src/rebar_utils.erl
index 02a2262..564b384 100644
--- a/src/rebar_utils.erl
+++ b/src/rebar_utils.erl
@@ -45,7 +45,6 @@
vcs_vsn/3,
deprecated/3,
deprecated/4,
- erl_opts/1,
indent/1,
update_code/1,
remove_from_code_path/1,
@@ -218,20 +217,6 @@ deprecated(Old, New, When) ->
"'~p' will be removed ~s.~n">>,
[Old, Old, New, Old, When]).
-%% @doc Return list of erl_opts
--spec erl_opts(rebar_state:t()) -> list().
-erl_opts(Config) ->
- RawErlOpts = filter_defines(rebar_state:get(Config, erl_opts, []), []),
- Defines = [{d, list_to_atom(D)} ||
- D <- rebar_state:get(Config, defines, [])],
- Opts = Defines ++ RawErlOpts,
- case proplists:is_defined(no_debug_info, Opts) of
- true ->
- [O || O <- Opts, O =/= no_debug_info];
- false ->
- [debug_info|Opts]
- end.
-
%% for use by `do` task
%% note: this does not handle the case where you have an argument that
@@ -247,20 +232,23 @@ deps_to_binary([{Name, Source} | T]) ->
deps_to_binary([Name | T]) ->
[ec_cnv:to_binary(Name) | deps_to_binary(T)].
-tup_dedup([]) ->
+tup_dedup(List) ->
+ tup_dedup_(tup_sort(List)).
+
+tup_dedup_([]) ->
[];
-tup_dedup([A]) ->
+tup_dedup_([A]) ->
[A];
-tup_dedup([A,B|T]) when element(1, A) =:= element(1, B) ->
- tup_dedup([A | T]);
-tup_dedup([A,B|T]) when element(1, A) =:= B ->
- tup_dedup([A | T]);
-tup_dedup([A,B|T]) when A =:= element(1, B) ->
- tup_dedup([A | T]);
-tup_dedup([A,A|T]) ->
- [A|tup_dedup(T)];
-tup_dedup([A|T]) ->
- [A|tup_dedup(T)].
+tup_dedup_([A,B|T]) when element(1, A) =:= element(1, B) ->
+ tup_dedup_([A | T]);
+tup_dedup_([A,B|T]) when element(1, A) =:= B ->
+ tup_dedup_([A | T]);
+tup_dedup_([A,B|T]) when A =:= element(1, B) ->
+ tup_dedup_([A | T]);
+tup_dedup_([A,A|T]) ->
+ [A|tup_dedup_(T)];
+tup_dedup_([A|T]) ->
+ [A|tup_dedup_(T)].
%% 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
@@ -289,9 +277,12 @@ tup_sort(List) ->
%%
%% This lets us apply proper overrides to list of elements according to profile
%% priority. This function depends on a stable proplist sort.
-tup_umerge([], Olds) ->
+tup_umerge(NewList, OldList) ->
+ tup_umerge_(tup_sort(NewList), tup_sort(OldList)).
+
+tup_umerge_([], Olds) ->
Olds;
-tup_umerge([New|News], Olds) ->
+tup_umerge_([New|News], Olds) ->
lists:reverse(umerge(News, Olds, [], New)).
tup_find(_Elem, []) ->
@@ -379,7 +370,6 @@ abort_if_blacklisted(BlacklistedRegex, OtpRelease) ->
[OtpRelease, BlacklistedRegex])
end.
-
%% ====================================================================
%% Internal functions
%% ====================================================================
@@ -644,29 +634,6 @@ find_resource_module(Type, Resources) ->
{ok, Module}
end.
-%%
-%% 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]).
-
%% @doc ident to the level specified
-spec indent(non_neg_integer()) -> iolist().
indent(Amount) when erlang:is_integer(Amount) ->
diff --git a/test/rebar_dir_SUITE.erl b/test/rebar_dir_SUITE.erl
index a3c5052..6fbc081 100644
--- a/test/rebar_dir_SUITE.erl
+++ b/test/rebar_dir_SUITE.erl
@@ -28,39 +28,39 @@ end_per_testcase(_, _Config) -> ok.
default_src_dirs(Config) ->
{ok, State} = rebar_test_utils:run_and_check(Config, [], ["compile"], return),
-
- [] = rebar_dir:src_dirs(State),
- ["src"] = rebar_dir:src_dirs(State, ["src"]).
+
+ [] = rebar_dir:src_dirs(rebar_state:opts(State)),
+ ["src"] = rebar_dir:src_dirs(rebar_state:opts(State), ["src"]).
default_extra_src_dirs(Config) ->
{ok, State} = rebar_test_utils:run_and_check(Config, [], ["compile"], return),
-
- [] = rebar_dir:extra_src_dirs(State),
- ["src"] = rebar_dir:extra_src_dirs(State, ["src"]).
+
+ [] = rebar_dir:extra_src_dirs(rebar_state:opts(State)),
+ ["src"] = rebar_dir:extra_src_dirs(rebar_state:opts(State), ["src"]).
default_all_src_dirs(Config) ->
{ok, State} = rebar_test_utils:run_and_check(Config, [], ["compile"], return),
-
- [] = rebar_dir:all_src_dirs(State),
- ["src", "test"] = rebar_dir:all_src_dirs(State, ["src"], ["test"]).
+
+ [] = rebar_dir:all_src_dirs(rebar_state:opts(State)),
+ ["src", "test"] = rebar_dir:all_src_dirs(rebar_state:opts(State), ["src"], ["test"]).
src_dirs(Config) ->
RebarConfig = [{erl_opts, [{src_dirs, ["foo", "bar", "baz"]}]}],
{ok, State} = rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], return),
-
- ["foo", "bar", "baz"] = rebar_dir:src_dirs(State).
+
+ ["foo", "bar", "baz"] = rebar_dir:src_dirs(rebar_state:opts(State)).
extra_src_dirs(Config) ->
RebarConfig = [{erl_opts, [{extra_src_dirs, ["foo", "bar", "baz"]}]}],
{ok, State} = rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], return),
-
- ["foo", "bar", "baz"] = rebar_dir:extra_src_dirs(State).
+
+ ["foo", "bar", "baz"] = rebar_dir:extra_src_dirs(rebar_state:opts(State)).
all_src_dirs(Config) ->
RebarConfig = [{erl_opts, [{src_dirs, ["foo", "bar"]}, {extra_src_dirs, ["baz", "qux"]}]}],
{ok, State} = rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], return),
-
- ["foo", "bar", "baz", "qux"] = rebar_dir:all_src_dirs(State).
+
+ ["foo", "bar", "baz", "qux"] = rebar_dir:all_src_dirs(rebar_state:opts(State)).
profile_src_dirs(Config) ->
RebarConfig = [
@@ -70,9 +70,9 @@ profile_src_dirs(Config) ->
]}
],
{ok, State} = rebar_test_utils:run_and_check(Config, RebarConfig, ["as", "more", "compile"], return),
-
+
R = lists:sort(["foo", "bar", "baz", "qux"]),
- R = lists:sort(rebar_dir:src_dirs(State)).
+ R = lists:sort(rebar_dir:src_dirs(rebar_state:opts(State))).
profile_extra_src_dirs(Config) ->
RebarConfig = [
@@ -82,9 +82,9 @@ profile_extra_src_dirs(Config) ->
]}
],
{ok, State} = rebar_test_utils:run_and_check(Config, RebarConfig, ["as", "more", "compile"], return),
-
+
R = lists:sort(["foo", "bar", "baz", "qux"]),
- R = lists:sort(rebar_dir:extra_src_dirs(State)).
+ R = lists:sort(rebar_dir:extra_src_dirs(rebar_state:opts(State))).
profile_all_src_dirs(Config) ->
RebarConfig = [
@@ -94,6 +94,6 @@ profile_all_src_dirs(Config) ->
]}
],
{ok, State} = rebar_test_utils:run_and_check(Config, RebarConfig, ["as", "more", "compile"], return),
-
+
R = lists:sort(["foo", "bar", "baz", "qux"]),
- R = lists:sort(rebar_dir:all_src_dirs(State)).
+ R = lists:sort(rebar_dir:all_src_dirs(rebar_state:opts(State))).
diff --git a/test/rebar_profiles_SUITE.erl b/test/rebar_profiles_SUITE.erl
index 41bb535..d4c10c5 100644
--- a/test/rebar_profiles_SUITE.erl
+++ b/test/rebar_profiles_SUITE.erl
@@ -428,8 +428,7 @@ test_profile_applied_to_apps(Config) ->
Apps = rebar_state:project_apps(State),
lists:foreach(fun(App) ->
- AppState = rebar_app_info:state(App),
- Opts = rebar_state:opts(AppState),
+ Opts = rebar_app_info:opts(App),
ErlOpts = dict:fetch(erl_opts, Opts),
true = lists:member({d, 'TEST'}, ErlOpts)
end, Apps).
diff --git a/test/rebar_src_dirs_SUITE.erl b/test/rebar_src_dirs_SUITE.erl
index e322190..e29dcf0 100644
--- a/test/rebar_src_dirs_SUITE.erl
+++ b/test/rebar_src_dirs_SUITE.erl
@@ -49,7 +49,7 @@ src_dirs_at_root(Config) ->
{ok, State} = rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], return),
- ["foo", "bar", "baz"] = rebar_dir:src_dirs(State, []).
+ ["foo", "bar", "baz"] = rebar_dir:src_dirs(rebar_state:opts(State), []).
extra_src_dirs_at_root(Config) ->
AppDir = ?config(apps, Config),
@@ -62,7 +62,7 @@ extra_src_dirs_at_root(Config) ->
{ok, State} = rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], return),
- ["foo", "bar", "baz"] = rebar_dir:extra_src_dirs(State, []).
+ ["foo", "bar", "baz"] = rebar_dir:extra_src_dirs(rebar_state:opts(State), []).
src_dirs_in_erl_opts(Config) ->
AppDir = ?config(apps, Config),
@@ -75,7 +75,7 @@ src_dirs_in_erl_opts(Config) ->
{ok, State} = rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], return),
- ["foo", "bar", "baz"] = rebar_dir:src_dirs(State, []).
+ ["foo", "bar", "baz"] = rebar_dir:src_dirs(rebar_state:opts(State), []).
extra_src_dirs_in_erl_opts(Config) ->
AppDir = ?config(apps, Config),
@@ -88,7 +88,7 @@ extra_src_dirs_in_erl_opts(Config) ->
{ok, State} = rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], return),
- ["foo", "bar", "baz"] = rebar_dir:extra_src_dirs(State, []).
+ ["foo", "bar", "baz"] = rebar_dir:extra_src_dirs(rebar_state:opts(State), []).
src_dirs_at_root_and_in_erl_opts(Config) ->
AppDir = ?config(apps, Config),
@@ -101,7 +101,7 @@ src_dirs_at_root_and_in_erl_opts(Config) ->
{ok, State} = rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], return),
- ["baz", "qux", "foo", "bar"] = rebar_dir:src_dirs(State, []).
+ ["baz", "qux", "foo", "bar"] = rebar_dir:src_dirs(rebar_state:opts(State), []).
extra_src_dirs_at_root_and_in_erl_opts(Config) ->
AppDir = ?config(apps, Config),
@@ -114,7 +114,7 @@ extra_src_dirs_at_root_and_in_erl_opts(Config) ->
{ok, State} = rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], return),
- ["baz", "qux", "foo", "bar"] = rebar_dir:extra_src_dirs(State, []).
+ ["baz", "qux", "foo", "bar"] = rebar_dir:extra_src_dirs(rebar_state:opts(State), []).
build_basic_app(Config) ->
AppDir = ?config(apps, Config),