summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/rebar3.erl23
-rw-r--r--src/rebar_dir.erl6
-rw-r--r--src/rebar_prv_common_test.erl2
-rw-r--r--src/rebar_prv_dialyzer.erl21
-rw-r--r--src/rebar_prv_eunit.erl70
-rw-r--r--src/rebar_utils.erl12
6 files changed, 78 insertions, 56 deletions
diff --git a/src/rebar3.erl b/src/rebar3.erl
index e55db71..2b73844 100644
--- a/src/rebar3.erl
+++ b/src/rebar3.erl
@@ -96,7 +96,7 @@ run(RawArgs) ->
run_aux(BaseState2, RawArgs).
run_aux(State, RawArgs) ->
- State2 = case os:getenv("REBAR_PROFILE") of
+ State1 = case os:getenv("REBAR_PROFILE") of
false ->
State;
"" ->
@@ -105,6 +105,9 @@ run_aux(State, RawArgs) ->
rebar_state:apply_profiles(State, [list_to_atom(Profile)])
end,
+ %% bootstrap test profile
+ State2 = rebar_state:add_to_profile(State1, test, test_state(State1)),
+
%% Process each command, resetting any state between each one
BaseDir = rebar_state:get(State, base_dir, ?DEFAULT_BASE_DIR),
State3 = rebar_state:set(State2, base_dir,
@@ -319,3 +322,21 @@ state_from_global_config(Config, GlobalConfigFile) ->
GlobalConfig2 = rebar_state:set(GlobalConfig, plugins, []),
GlobalConfig3 = rebar_state:set(GlobalConfig2, {plugins, global}, rebar_state:get(GlobalConfigThrowAway, plugins, [])),
rebar_state:providers(rebar_state:new(GlobalConfig3, Config), GlobalPlugins).
+
+test_state(State) ->
+ ErlOpts = rebar_state:get(State, erl_opts, []),
+ TestOpts = safe_define_test_macro(ErlOpts),
+ [{extra_src_dirs, ["test"]}, {erl_opts, TestOpts}].
+
+safe_define_test_macro(Opts) ->
+ %% defining a compile macro twice results in an exception so
+ %% make sure 'TEST' is only defined once
+ case test_defined(Opts) of
+ true -> [];
+ false -> [{d, 'TEST'}]
+ end.
+
+test_defined([{d, 'TEST'}|_]) -> true;
+test_defined([{d, 'TEST', true}|_]) -> true;
+test_defined([_|Rest]) -> test_defined(Rest);
+test_defined([]) -> false. \ No newline at end of file
diff --git a/src/rebar_dir.erl b/src/rebar_dir.erl
index 364e197..09e3114 100644
--- a/src/rebar_dir.erl
+++ b/src/rebar_dir.erl
@@ -139,7 +139,7 @@ src_dirs(Opts, Default) ->
Vs = proplists:get_all_values(src_dirs, ErlOpts),
case lists:append([rebar_opts:get(Opts, src_dirs, []) | Vs]) of
[] -> Default;
- Dirs -> Dirs
+ Dirs -> lists:usort(Dirs)
end.
-spec extra_src_dirs(rebar_dict()) -> list(file:filename_all()).
@@ -151,7 +151,7 @@ extra_src_dirs(Opts, Default) ->
Vs = proplists:get_all_values(extra_src_dirs, ErlOpts),
case lists:append([rebar_opts:get(Opts, extra_src_dirs, []) | Vs]) of
[] -> Default;
- Dirs -> Dirs
+ Dirs -> lists:usort(Dirs)
end.
-spec all_src_dirs(rebar_dict()) -> list(file:filename_all()).
@@ -160,7 +160,7 @@ all_src_dirs(Opts) -> all_src_dirs(Opts, [], []).
-spec all_src_dirs(rebar_dict(), list(file:filename_all()), list(file:filename_all())) ->
list(file:filename_all()).
all_src_dirs(Opts, SrcDefault, ExtraDefault) ->
- src_dirs(Opts, SrcDefault) ++ extra_src_dirs(Opts, ExtraDefault).
+ lists:usort(src_dirs(Opts, SrcDefault) ++ extra_src_dirs(Opts, ExtraDefault)).
%% given a path if that path is an ancestor of an app dir return the path relative to that
%% apps outdir. if the path is not an ancestor to any app dirs but is an ancestor of the
diff --git a/src/rebar_prv_common_test.erl b/src/rebar_prv_common_test.erl
index 1f4c02d..32d4433 100644
--- a/src/rebar_prv_common_test.erl
+++ b/src/rebar_prv_common_test.erl
@@ -38,7 +38,7 @@ init(State) ->
-spec do(rebar_state:t()) -> {ok, rebar_state:t()} | {error, string()}.
do(State) ->
?INFO("Running Common Test suites...", []),
- rebar_utils:update_code(rebar_state:code_paths(State, all_deps)),
+ rebar_utils:update_code(rebar_state:code_paths(State, all_deps), [soft_purge]),
%% Run ct provider prehooks
Providers = rebar_state:providers(State),
diff --git a/src/rebar_prv_dialyzer.erl b/src/rebar_prv_dialyzer.erl
index 487e9d1..2e5728a 100644
--- a/src/rebar_prv_dialyzer.erl
+++ b/src/rebar_prv_dialyzer.erl
@@ -173,7 +173,7 @@ do_update_proj_plt(State, Plt, Output) ->
case read_plt(State, Plt) of
{ok, OldFiles} ->
check_plt(State, Plt, Output, OldFiles, Files);
- {error, no_such_file} ->
+ error ->
build_proj_plt(State, Plt, Output, Files)
end.
@@ -252,14 +252,25 @@ read_plt(_State, Plt) ->
case dialyzer:plt_info(Plt) of
{ok, Info} ->
Files = proplists:get_value(files, Info, []),
- {ok, Files};
- {error, no_such_file} = Error ->
- Error;
+ read_plt_files(Plt, Files);
+ {error, no_such_file} ->
+ error;
{error, read_error} ->
Error = io_lib:format("Could not read the PLT file ~p", [Plt]),
throw({dialyzer_error, Error})
end.
+%% If any file no longer exists dialyzer will fail when updating the PLT.
+read_plt_files(Plt, Files) ->
+ case [File || File <- Files, not filelib:is_file(File)] of
+ [] ->
+ {ok, Files};
+ Missing ->
+ ?INFO("Could not find ~p files in ~p...", [length(Missing), Plt]),
+ ?DEBUG("Could not find files: ~p", [Missing]),
+ error
+ end.
+
check_plt(State, Plt, Output, OldList, FilesList) ->
Old = sets:from_list(OldList),
Files = sets:from_list(FilesList),
@@ -337,7 +348,7 @@ update_base_plt(State, BasePlt, Output, BaseFiles) ->
case read_plt(State, BasePlt) of
{ok, OldBaseFiles} ->
check_plt(State, BasePlt, Output, OldBaseFiles, BaseFiles);
- {error, no_such_file} ->
+ error ->
_ = filelib:ensure_dir(BasePlt),
build_plt(State, BasePlt, Output, BaseFiles)
end.
diff --git a/src/rebar_prv_eunit.erl b/src/rebar_prv_eunit.erl
index b748b06..d5612e8 100644
--- a/src/rebar_prv_eunit.erl
+++ b/src/rebar_prv_eunit.erl
@@ -9,7 +9,7 @@
do/1,
format_error/1]).
%% exported solely for tests
--export([compile/2, prepare_tests/1, eunit_opts/1]).
+-export([compile/2, prepare_tests/1, eunit_opts/1, validate_tests/2]).
-include("rebar.hrl").
-include_lib("providers/include/providers.hrl").
@@ -34,8 +34,7 @@ init(State) ->
{opts, eunit_opts(State)},
{profiles, [test]}]),
State1 = rebar_state:add_provider(State, Provider),
- State2 = rebar_state:add_to_profile(State1, test, test_state(State1)),
- {ok, State2}.
+ {ok, State1}.
-spec do(rebar_state:t()) -> {ok, rebar_state:t()} | {error, string()}.
do(State) ->
@@ -50,14 +49,14 @@ do(State) ->
do(State, Tests) ->
?INFO("Performing EUnit tests...", []),
- rebar_utils:update_code(rebar_state:code_paths(State, all_deps)),
+ rebar_utils:update_code(rebar_state:code_paths(State, all_deps), [soft_purge]),
%% Run eunit provider prehooks
Providers = rebar_state:providers(State),
Cwd = rebar_dir:get_cwd(),
rebar_hooks:run_all_hooks(Cwd, pre, ?PROVIDER, Providers, State),
- case Tests of
+ case validate_tests(State, Tests) of
{ok, T} ->
case run_tests(State, T) of
{ok, State1} ->
@@ -103,19 +102,6 @@ format_error({error, Error}) ->
%% Internal functions
%% ===================================================================
-test_state(State) ->
- ErlOpts = rebar_state:get(State, erl_opts, []),
- TestOpts = safe_define_test_macro(ErlOpts),
- [{extra_src_dirs, ["test"]}, {erl_opts, TestOpts}].
-
-safe_define_test_macro(Opts) ->
- %% defining a compile macro twice results in an exception so
- %% make sure 'TEST' is only defined once
- case test_defined(Opts) of
- true -> Opts;
- false -> [{d, 'TEST'}] ++ Opts
- end.
-
compile(State, {ok, Tests}) ->
%% inject `eunit_first_files`, `eunit_compile_opts` and any
%% directories required by tests into the applications
@@ -191,11 +177,6 @@ inject_test_dir(Opts, Dir) ->
ExtraSrcDirs = rebar_opts:get(Opts, extra_src_dirs, []),
rebar_opts:set(Opts, extra_src_dirs, ExtraSrcDirs ++ [Dir]).
-test_defined([{d, 'TEST'}|_]) -> true;
-test_defined([{d, 'TEST', true}|_]) -> true;
-test_defined([_|Rest]) -> test_defined(Rest);
-test_defined([]) -> false.
-
prepare_tests(State) ->
%% parse and translate command line tests
CmdTests = resolve_tests(State),
@@ -204,11 +185,7 @@ prepare_tests(State) ->
%% prioritize tests to run first trying any command line specified
%% tests falling back to tests specified in the config file finally
%% running a default set if no other tests are present
- Tests = select_tests(State, ProjectApps, CmdTests, CfgTests),
- %% check applications for existence in project, modules for existence
- %% in applications, files and dirs for existence on disk and allow
- %% any unrecognized tests through for eunit to handle
- validate_tests(State, ProjectApps, Tests).
+ select_tests(State, ProjectApps, CmdTests, CfgTests).
resolve_tests(State) ->
{RawOpts, _} = rebar_state:command_parsed_args(State),
@@ -231,9 +208,9 @@ resolve(Flag, EUnitKey, RawOpts) ->
normalize(Key, Value) when Key == dir; Key == file -> {Key, Value};
normalize(Key, Value) -> {Key, list_to_atom(Value)}.
-select_tests(State, ProjectApps, [], []) -> default_tests(State, ProjectApps);
-select_tests(_State, _ProjectApps, [], Tests) -> Tests;
-select_tests(_State, _ProjectApps, Tests, _) -> Tests.
+select_tests(State, ProjectApps, [], []) -> {ok, default_tests(State, ProjectApps)};
+select_tests(_State, _ProjectApps, [], Tests) -> {ok, Tests};
+select_tests(_State, _ProjectApps, Tests, _) -> {ok, Tests}.
default_tests(State, Apps) ->
Tests = set_apps(Apps, []),
@@ -252,8 +229,9 @@ set_apps([App|Rest], Acc) ->
AppName = list_to_atom(binary_to_list(rebar_app_info:name(App))),
set_apps(Rest, [{application, AppName}|Acc]).
-validate_tests(State, ProjectApps, Tests) ->
- gather_tests(fun(Elem) -> validate(State, ProjectApps, Elem) end, Tests, []).
+validate_tests(State, {ok, Tests}) ->
+ gather_tests(fun(Elem) -> validate(State, Elem) end, Tests, []);
+validate_tests(_State, Error) -> Error.
gather_tests(_F, [], Acc) -> {ok, lists:reverse(Acc)};
gather_tests(F, [Test|Rest], Acc) ->
@@ -270,27 +248,31 @@ gather_errors(F, [Test|Rest], Acc) ->
{error, Error} -> gather_errors(F, Rest, [Error|Acc])
end.
-validate(State, ProjectApps, {application, App}) ->
- validate_app(State, ProjectApps, App);
-validate(State, _ProjectApps, {dir, Dir}) ->
+validate(State, {application, App}) ->
+ validate_app(State, App);
+validate(State, {dir, Dir}) ->
validate_dir(State, Dir);
-validate(State, _ProjectApps, {file, File}) ->
+validate(State, {file, File}) ->
validate_file(State, File);
-validate(State, _ProjectApps, {module, Module}) ->
+validate(State, {module, Module}) ->
validate_module(State, Module);
-validate(State, _ProjectApps, {suite, Module}) ->
+validate(State, {suite, Module}) ->
validate_module(State, Module);
-validate(State, _ProjectApps, Module) when is_atom(Module) ->
+validate(State, Module) when is_atom(Module) ->
validate_module(State, Module);
-validate(State, ProjectApps, Path) when is_list(Path) ->
+validate(State, Path) when is_list(Path) ->
case ec_file:is_dir(Path) of
- true -> validate(State, ProjectApps, {dir, Path});
- false -> validate(State, ProjectApps, {file, Path})
+ true -> validate(State, {dir, Path});
+ false -> validate(State, {file, Path})
end;
%% unrecognized tests should be included. if they're invalid eunit will error
%% and rebar.config may contain arbitrarily complex tests that are effectively
%% unvalidatable
-validate(_State, _ProjectApps, _Test) -> ok.
+validate(_State, _Test) -> ok.
+
+validate_app(State, AppName) ->
+ ProjectApps = rebar_state:project_apps(State),
+ validate_app(State, ProjectApps, AppName).
validate_app(_State, [], AppName) ->
{error, lists:concat(["Application `", AppName, "' not found in project."])};
diff --git a/src/rebar_utils.erl b/src/rebar_utils.erl
index 4fd4bd1..ea60e42 100644
--- a/src/rebar_utils.erl
+++ b/src/rebar_utils.erl
@@ -47,6 +47,7 @@
deprecated/4,
indent/1,
update_code/1,
+ update_code/2,
remove_from_code_path/1,
cleanup_code_path/1,
args_to_tasks/1,
@@ -644,7 +645,9 @@ indent(Amount) when erlang:is_integer(Amount) ->
%% Replace code paths with new paths for existing apps and
%% purge code of the old modules from those apps.
-update_code(Paths) ->
+update_code(Paths) -> update_code(Paths, []).
+
+update_code(Paths, Opts) ->
lists:foreach(fun(Path) ->
Name = filename:basename(Path, "/ebin"),
App = list_to_atom(Name),
@@ -660,7 +663,12 @@ update_code(Paths) ->
%code:replace_path(App, Path),
code:del_path(App),
code:add_patha(Path),
- [begin code:purge(M), code:delete(M) end || M <- Modules]
+ case lists:member(soft_purge, Opts) of
+ true ->
+ [begin code:soft_purge(M), code:delete(M) end || M <- Modules];
+ false ->
+ [begin code:purge(M), code:delete(M) end || M <- Modules]
+ end
end
end, Paths).