summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/rebar_app_discover.erl27
-rw-r--r--src/rebar_app_info.erl9
-rw-r--r--src/rebar_core.erl1
-rw-r--r--src/rebar_dir.erl4
-rw-r--r--src/rebar_hooks.erl10
-rw-r--r--src/rebar_plugins.erl43
-rw-r--r--src/rebar_prv_clean.erl9
-rw-r--r--src/rebar_prv_compile.erl12
-rw-r--r--src/rebar_prv_eunit.erl9
-rw-r--r--src/rebar_prv_install_deps.erl48
-rw-r--r--src/rebar_prv_shell.erl6
-rw-r--r--src/rebar_prv_tar.erl2
-rw-r--r--src/rebar_prv_upgrade.erl21
-rw-r--r--src/rebar_state.erl11
-rw-r--r--src/rebar_utils.erl17
-rw-r--r--test/mock_pkg_resource.erl6
-rw-r--r--test/rebar_compile_SUITE.erl63
-rw-r--r--test/rebar_disable_app_SUITE.erl49
-rw-r--r--test/rebar_src_dirs_SUITE.erl (renamed from test/rebar_extra_src_dirs_SUITE.erl)95
-rw-r--r--test/rebar_test_utils.erl7
-rw-r--r--test/rebar_upgrade_SUITE.erl34
21 files changed, 394 insertions, 89 deletions
diff --git a/src/rebar_app_discover.erl b/src/rebar_app_discover.erl
index e2ef179..332efb0 100644
--- a/src/rebar_app_discover.erl
+++ b/src/rebar_app_discover.erl
@@ -20,13 +20,19 @@ do(State, LibDirs) ->
%% Sort apps so we get the same merged deps config everytime
SortedApps = rebar_utils:sort_deps(Apps),
lists:foldl(fun(AppInfo, StateAcc) ->
- {AppInfo1, StateAcc1} = merge_deps(AppInfo, StateAcc),
- Name = rebar_app_info:name(AppInfo),
- OutDir = filename:join(DepsDir, Name),
- AppInfo2 = rebar_app_info:out_dir(AppInfo1, OutDir),
- ProjectDeps1 = lists:delete(Name, ProjectDeps),
- rebar_state:project_apps(StateAcc1
- ,rebar_app_info:deps(AppInfo2, ProjectDeps1))
+ Name = rebar_app_info:name(AppInfo),
+ case enable(State, AppInfo) of
+ true ->
+ {AppInfo1, StateAcc1} = merge_deps(AppInfo, StateAcc),
+ OutDir = filename:join(DepsDir, Name),
+ AppInfo2 = rebar_app_info:out_dir(AppInfo1, OutDir),
+ ProjectDeps1 = lists:delete(Name, ProjectDeps),
+ rebar_state:project_apps(StateAcc1
+ ,rebar_app_info:deps(AppInfo2, ProjectDeps1));
+ false ->
+ ?INFO("Ignoring ~s", [Name]),
+ StateAcc
+ end
end, State, SortedApps).
format_error({module_list, File}) ->
@@ -211,3 +217,10 @@ try_handle_app_src_file(_, AppDir, [File], Validate) when Validate =:= invalid
end;
try_handle_app_src_file(_, _AppDir, Other, _Validate) ->
throw({error, {multiple_app_files, Other}}).
+
+enable(State, AppInfo) ->
+ not lists:member(to_atom(rebar_app_info:name(AppInfo)),
+ rebar_state:get(State, excluded_apps, [])).
+
+to_atom(Bin) ->
+ list_to_atom(binary_to_list(Bin)).
diff --git a/src/rebar_app_info.erl b/src/rebar_app_info.erl
index 1b87e0b..9db20e7 100644
--- a/src/rebar_app_info.erl
+++ b/src/rebar_app_info.erl
@@ -34,6 +34,7 @@
source/2,
state/1,
state/2,
+ state_or_new/2,
is_lock/1,
is_lock/2,
is_checkout/1,
@@ -260,6 +261,14 @@ state(AppInfo=#app_info_t{}, State) ->
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, AppDir);
+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}.
diff --git a/src/rebar_core.erl b/src/rebar_core.erl
index 7fe7332..c7cc45a 100644
--- a/src/rebar_core.erl
+++ b/src/rebar_core.erl
@@ -119,6 +119,7 @@ do([ProviderName | Rest], State) ->
,rebar_state:providers(State)
,rebar_state:namespace(State))
end,
+
case providers:do(Provider, State) of
{ok, State1} ->
do(Rest, State1);
diff --git a/src/rebar_dir.erl b/src/rebar_dir.erl
index e810912..cb643ab 100644
--- a/src/rebar_dir.erl
+++ b/src/rebar_dir.erl
@@ -132,7 +132,7 @@ src_dirs(State) -> src_dirs(State, []).
src_dirs(State, Default) ->
ErlOpts = rebar_utils:erl_opts(State),
Vs = proplists:get_all_values(src_dirs, ErlOpts),
- case lists:append(Vs) of
+ case lists:append([rebar_state:get(State, src_dirs, []) | Vs]) of
[] -> Default;
Dirs -> Dirs
end.
@@ -144,7 +144,7 @@ extra_src_dirs(State) -> extra_src_dirs(State, []).
extra_src_dirs(State, Default) ->
ErlOpts = rebar_utils:erl_opts(State),
Vs = proplists:get_all_values(extra_src_dirs, ErlOpts),
- case lists:append(Vs) of
+ case lists:append([rebar_state:get(State, extra_src_dirs, []) | Vs]) of
[] -> Default;
Dirs -> Dirs
end.
diff --git a/src/rebar_hooks.erl b/src/rebar_hooks.erl
index e144a8e..4ec46f7 100644
--- a/src/rebar_hooks.erl
+++ b/src/rebar_hooks.erl
@@ -10,11 +10,17 @@ run_all_hooks(Dir, Type, Command, Providers, State) ->
run_hooks(Dir, Type, Command, State).
run_provider_hooks(Dir, Type, Command, Providers, State) ->
- State1 = rebar_state:providers(rebar_state:dir(State, Dir), Providers),
+ 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),
AllHooks = rebar_state:get(State1, provider_hooks, []),
TypeHooks = proplists:get_value(Type, AllHooks, []),
HookProviders = proplists:get_all_values(Command, TypeHooks),
- rebar_core:do(HookProviders, State1).
+
+ State2 = rebar_core:do(HookProviders, State1),
+ rebar_utils:remove_from_code_path(PluginDepsPaths),
+ State2.
run_hooks(Dir, Type, Command, State) ->
Hooks = case Type of
diff --git a/src/rebar_plugins.erl b/src/rebar_plugins.erl
index 6d0a4dc..c4644dc 100644
--- a/src/rebar_plugins.erl
+++ b/src/rebar_plugins.erl
@@ -32,31 +32,50 @@ handle_plugins(Plugins, State) ->
handle_plugins(Profile, Plugins, State) ->
%% Set deps dir to plugins dir so apps are installed there
+ Locks = rebar_state:lock(State),
+ DepsDir = rebar_state:get(State, deps_dir, ?DEFAULT_DEPS_DIR),
State1 = rebar_state:set(State, deps_dir, ?DEFAULT_PLUGINS_DIR),
- PluginProviders = lists:flatmap(fun(Plugin) ->
- handle_plugin(Profile, Plugin, State1)
- end, Plugins),
+ %% Install each plugin individually so if one fails to install it doesn't effect the others
+ {PluginProviders, State2} =
+ lists:foldl(fun(Plugin, {PluginAcc, StateAcc}) ->
+ {NewPlugins, NewState} = handle_plugin(Profile, Plugin, StateAcc),
+ {PluginAcc++NewPlugins, NewState}
+ end, {[], State1}, Plugins),
%% reset deps dir
- State2 = rebar_state:set(State1, deps_dir, ?DEFAULT_DEPS_DIR),
+ State3 = rebar_state:set(State2, deps_dir, DepsDir),
+ State4 = rebar_state:lock(State3, Locks),
- rebar_state:create_logic_providers(PluginProviders, State2).
+ rebar_state:create_logic_providers(PluginProviders, State4).
handle_plugin(Profile, Plugin, State) ->
try
- {ok, _, State2} = rebar_prv_install_deps:handle_deps(Profile, State, [Plugin]),
+ {ok, Apps, State2} = rebar_prv_install_deps:handle_deps(Profile, State, [Plugin]),
+ {no_cycle, Sorted} = rebar_prv_install_deps:find_cycles(Apps),
+ ToBuild = rebar_prv_install_deps:cull_compile(Sorted, []),
- Apps = rebar_state:all_deps(State2),
- ToBuild = lists:dropwhile(fun rebar_app_info:valid/1, Apps),
+ %% Add already built plugin deps to the code path
+ CodePaths = [rebar_app_info:ebin_dir(A) || A <- Apps -- ToBuild],
+ code:add_pathsa(CodePaths),
+
+ %% Build plugin and its deps
[build_plugin(AppInfo) || AppInfo <- ToBuild],
- [true = code:add_patha(filename:join(rebar_app_info:dir(AppInfo), "ebin")) || AppInfo <- Apps],
- plugin_providers(Plugin)
+
+ %% Add newly built deps and plugin to code path
+ State3 = rebar_state:update_all_plugin_deps(State2, Apps),
+ NewCodePaths = [rebar_app_info:ebin_dir(A) || A <- ToBuild],
+ code:add_pathsa(CodePaths),
+
+ %% Store plugin code paths so we can remove them when compiling project apps
+ State4 = rebar_state:update_code_paths(State3, all_plugin_deps, CodePaths++NewCodePaths),
+
+ {plugin_providers(Plugin), State4}
catch
C:T ->
?DEBUG("~p ~p ~p", [C, T, erlang:get_stacktrace()]),
?WARN("Plugin ~p not available. It will not be used.", [Plugin]),
- []
+ {[], State}
end.
build_plugin(AppInfo) ->
@@ -65,6 +84,8 @@ build_plugin(AppInfo) ->
S = rebar_state:new(rebar_state:new(), C, AppDir),
rebar_prv_compile:compile(S, [], AppInfo).
+plugin_providers({Plugin, _, _, _}) when is_atom(Plugin) ->
+ validate_plugin(Plugin);
plugin_providers({Plugin, _, _}) when is_atom(Plugin) ->
validate_plugin(Plugin);
plugin_providers({Plugin, _}) when is_atom(Plugin) ->
diff --git a/src/rebar_prv_clean.erl b/src/rebar_prv_clean.erl
index 68acf36..e3cb84e 100644
--- a/src/rebar_prv_clean.erl
+++ b/src/rebar_prv_clean.erl
@@ -67,16 +67,9 @@ format_error(Reason) ->
clean_apps(State, Providers, Apps) ->
lists:foreach(fun(AppInfo) ->
AppDir = rebar_app_info:dir(AppInfo),
- S = case rebar_app_info:state(AppInfo) of
- undefined ->
- C = rebar_config:consult(AppDir),
- rebar_state:new(State, C, AppDir);
- AppState ->
- AppState
- end,
+ S = rebar_app_info:state_or_new(State, AppInfo),
?INFO("Cleaning out ~s...", [rebar_app_info:name(AppInfo)]),
- %% Legacy hook support
rebar_hooks:run_all_hooks(AppDir, pre, ?PROVIDER, Providers, S),
rebar_erlc_compiler:clean(State, rebar_app_info:out_dir(AppInfo)),
rebar_hooks:run_all_hooks(AppDir, post, ?PROVIDER, Providers, S)
diff --git a/src/rebar_prv_compile.erl b/src/rebar_prv_compile.erl
index 26d658e..37dc47d 100644
--- a/src/rebar_prv_compile.erl
+++ b/src/rebar_prv_compile.erl
@@ -32,6 +32,8 @@ init(State) ->
-spec do(rebar_state:t()) -> {ok, rebar_state:t()} | {error, string()}.
do(State) ->
DepsPaths = rebar_state:code_paths(State, all_deps),
+ PluginDepsPaths = rebar_state:code_paths(State, all_plugin_deps),
+ rebar_utils:remove_from_code_path(PluginDepsPaths),
code:add_pathsa(DepsPaths),
ProjectApps = rebar_state:project_apps(State),
@@ -71,17 +73,9 @@ 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 = case rebar_app_info:state(AppInfo) of
- undefined ->
- C = rebar_config:consult(AppDir),
- rebar_state:new(State, C, AppDir);
- AppState ->
- AppState
- end,
-
+ S = rebar_app_info:state_or_new(State, AppInfo),
compile(S, Providers, AppInfo).
compile(State, Providers, AppInfo) ->
diff --git a/src/rebar_prv_eunit.erl b/src/rebar_prv_eunit.erl
index ce93d33..28c0ed6 100644
--- a/src/rebar_prv_eunit.erl
+++ b/src/rebar_prv_eunit.erl
@@ -134,14 +134,7 @@ resolve_suites(State, Apps, RawOpts) ->
compile_tests(State, TestApps, Suites, RawOpts) ->
F = fun(AppInfo) ->
- AppDir = rebar_app_info:dir(AppInfo),
- S = case rebar_app_info:state(AppInfo) of
- undefined ->
- C = rebar_config:consult(AppDir),
- rebar_state:new(State, C, AppDir);
- AppState ->
- AppState
- end,
+ S = rebar_app_info:state_or_new(State, AppInfo),
ok = rebar_erlc_compiler:compile(replace_src_dirs(S),
ec_cnv:to_list(rebar_app_info:out_dir(AppInfo)))
end,
diff --git a/src/rebar_prv_install_deps.erl b/src/rebar_prv_install_deps.erl
index 3cdf784..d8b9000 100644
--- a/src/rebar_prv_install_deps.erl
+++ b/src/rebar_prv_install_deps.erl
@@ -37,7 +37,10 @@
-export([handle_deps/3,
handle_deps/4,
- handle_deps/5]).
+ handle_deps/5,
+
+ find_cycles/1,
+ cull_compile/2]).
-export_type([dep/0]).
@@ -76,6 +79,10 @@ do(State) ->
{Apps, State1} =
lists:foldl(fun deps_per_profile/2, {[], State}, lists:reverse(Profiles)),
+ State2 = rebar_state:update_all_deps(State1, Apps),
+ CodePaths = [rebar_app_info:ebin_dir(A) || A <- Apps],
+ State3 = rebar_state:update_code_paths(State2, all_deps, CodePaths),
+
Source = ProjectApps ++ Apps,
case find_cycles(Source) of
{cycles, Cycles} ->
@@ -84,7 +91,7 @@ do(State) ->
{error, Error};
{no_cycle, Sorted} ->
ToCompile = cull_compile(Sorted, ProjectApps),
- {ok, rebar_state:deps_to_build(State1, ToCompile)}
+ {ok, rebar_state:deps_to_build(State3, ToCompile)}
end
catch
%% maybe_fetch will maybe_throw an exception to break out of some loops
@@ -158,11 +165,7 @@ handle_deps(Profile, State0, Deps, Upgrade, Locks) ->
,lists:ukeysort(2, SrcApps)
,lists:ukeysort(2, Solved)),
- State5 = rebar_state:update_all_deps(State4, AllDeps),
- CodePaths = [rebar_app_info:ebin_dir(A) || A <- AllDeps],
- State6 = rebar_state:update_code_paths(State5, all_deps, CodePaths),
-
- {ok, AllDeps, State6}.
+ {ok, AllDeps, State4}.
%% ===================================================================
%% Internal functions
@@ -224,7 +227,22 @@ handle_pkg_dep(Profile, Pkg, Packages, Upgrade, DepsDir, Fetched, Seen, Locks, S
Level = rebar_app_info:dep_level(AppInfo),
{NewSeen, NewState} = maybe_lock(Profile, AppInfo, Seen, State, Level),
{_, AppInfo1} = maybe_fetch(AppInfo, Profile, Upgrade, Seen, NewState),
- {[AppInfo1 | Fetched], NewSeen, NewState}.
+
+ Profiles = rebar_state:current_profiles(State),
+ Name = rebar_app_info:name(AppInfo1),
+ C = rebar_config:consult(rebar_app_info:dir(AppInfo1)),
+ BaseDir = rebar_state:get(State, base_dir, []),
+ S1 = rebar_state:new(rebar_state:set(rebar_state:new(), base_dir, BaseDir),
+ C, rebar_app_info:dir(AppInfo1)),
+ S2 = rebar_state:apply_profiles(S1, Profiles),
+ S3 = rebar_state:apply_overrides(S2, Name),
+ AppInfo2 = rebar_app_info:state(AppInfo1, S3),
+
+ %% Dep may have plugins to install. Find and install here.
+ S4 = rebar_plugins:handle_plugins(rebar_state:get(S3, plugins, []), S3),
+ AppInfo3 = rebar_app_info:state(AppInfo2, S4),
+
+ {[AppInfo3 | Fetched], NewSeen, NewState}.
maybe_lock(Profile, AppInfo, Seen, State, Level) ->
case rebar_app_info:is_checkout(AppInfo) of
@@ -383,14 +401,16 @@ handle_dep(State, DepsDir, AppInfo, Locks, Level) ->
AppInfo1 = rebar_app_info:state(AppInfo, S3),
%% Dep may have plugins to install. Find and install here.
- State1 = rebar_plugins:handle_plugins(rebar_state:get(S3, plugins, []), State),
- Deps = rebar_state:get(S3, deps, []),
+ S4 = rebar_plugins:handle_plugins(rebar_state:get(S3, plugins, []), S3),
+ AppInfo2 = rebar_app_info:state(AppInfo1, S4),
+
%% Upgrade lock level to be the level the dep will have in this dep tree
+ Deps = rebar_state:get(S4, deps, []),
NewLocks = [{DepName, Source, LockLevel+Level} ||
- {DepName, Source, LockLevel} <- rebar_state:get(S3, {locks, default}, [])],
- AppInfo2 = rebar_app_info:deps(AppInfo1, rebar_state:deps_names(Deps)),
- {SrcDeps, PkgDeps} = parse_deps(DepsDir, Deps, S3, Locks, Level+1),
- {AppInfo2, SrcDeps, PkgDeps, Locks++NewLocks, State1}.
+ {DepName, Source, LockLevel} <- rebar_state:get(S4, {locks, default}, [])],
+ AppInfo3 = rebar_app_info:deps(AppInfo2, rebar_state:deps_names(Deps)),
+ {SrcDeps, PkgDeps} = parse_deps(DepsDir, Deps, S4, Locks, Level+1),
+ {AppInfo3, SrcDeps, PkgDeps, Locks++NewLocks, State}.
-spec maybe_fetch(rebar_app_info:t(), atom(), boolean(),
sets:set(binary()), rebar_state:t()) -> {boolean(), rebar_app_info:t()}.
diff --git a/src/rebar_prv_shell.erl b/src/rebar_prv_shell.erl
index 5e87f02..bd49ee1 100644
--- a/src/rebar_prv_shell.erl
+++ b/src/rebar_prv_shell.erl
@@ -107,8 +107,10 @@ setup_shell() ->
%% wait until user_drv and user have been registered (max 3 seconds)
ok = wait_until_user_started(3000),
%% set any process that had a reference to the old user's group leader to the
- %% new user process
- _ = [erlang:group_leader(whereis(user), Pid) || Pid <- NeedsUpdate],
+ %% new user process. Catch the race condition when the Pid exited after the
+ %% liveness check.
+ _ = [catch erlang:group_leader(whereis(user), Pid) || Pid <- NeedsUpdate,
+ is_process_alive(Pid)],
%% enable error_logger's tty output
ok = error_logger:swap_handler(tty),
%% disable the simple error_logger (which may have been added multiple
diff --git a/src/rebar_prv_tar.erl b/src/rebar_prv_tar.erl
index 852ba87..84fe395 100644
--- a/src/rebar_prv_tar.erl
+++ b/src/rebar_prv_tar.erl
@@ -47,7 +47,7 @@ do(State) ->
,{caller, Caller}], AllOptions);
Config ->
relx:main([{lib_dirs, LibDirs}
- ,{config, Config}
+ ,{config, lists:reverse(Config)}
,{output_dir, OutputDir}
,{caller, Caller}], AllOptions)
end,
diff --git a/src/rebar_prv_upgrade.erl b/src/rebar_prv_upgrade.erl
index b86cbe3..49d5674 100644
--- a/src/rebar_prv_upgrade.erl
+++ b/src/rebar_prv_upgrade.erl
@@ -94,10 +94,15 @@ prepare_locks([Name|Names], Deps, Locks, Unlocks) ->
AtomName = binary_to_atom(Name, utf8),
case lists:keyfind(Name, 1, Locks) of
{_, _, 0} = Lock ->
- case lists:keyfind(AtomName, 1, Deps) of
- false ->
+ case {lists:keyfind(AtomName, 1, Deps), lists:member(AtomName, Deps)} of
+ {false, false} ->
?PRV_ERROR({unknown_dependency, Name});
- Dep ->
+ {Dep, false} ->
+ {Source, NewLocks, NewUnlocks} = prepare_lock(Dep, Lock, Locks),
+ prepare_locks(Names, Deps, NewLocks,
+ [{Name, Source, 0} | NewUnlocks ++ Unlocks]);
+ {false, true} -> % package as a single atom
+ Dep = AtomName,
{Source, NewLocks, NewUnlocks} = prepare_lock(Dep, Lock, Locks),
prepare_locks(Names, Deps, NewLocks,
[{Name, Source, 0} | NewUnlocks ++ Unlocks])
@@ -116,9 +121,13 @@ prepare_locks([Name|Names], Deps, Locks, Unlocks) ->
end.
prepare_lock(Dep, Lock, Locks) ->
- Source = Source = case Dep of
- {_, Src} -> Src;
- {_, _, Src} -> Src
+ Source = case Dep of
+ {_, SrcOrVsn} -> SrcOrVsn;
+ {_, _, Src} -> Src;
+ _ when is_atom(Dep) ->
+ %% version-free package. Must unlock whatever matches in locks
+ {_, Vsn, _} = lists:keyfind(ec_cnv:to_binary(Dep), 1, Locks),
+ Vsn
end,
{NewLocks, NewUnlocks} = unlock_higher_than(0, Locks -- [Lock]),
{Source, NewLocks, NewUnlocks}.
diff --git a/src/rebar_state.erl b/src/rebar_state.erl
index 18d6be7..96daf39 100644
--- a/src/rebar_state.erl
+++ b/src/rebar_state.erl
@@ -24,6 +24,7 @@
project_apps/1, project_apps/2,
deps_to_build/1, deps_to_build/2,
+ all_plugin_deps/1, all_plugin_deps/2, update_all_plugin_deps/2,
all_deps/1, all_deps/2, update_all_deps/2,
namespace/1, namespace/2,
@@ -55,6 +56,7 @@
project_apps = [] :: [rebar_app_info:t()],
deps_to_build = [] :: [rebar_app_info:t()],
+ all_plugin_deps = [] :: [rebar_app_info:t()],
all_deps = [] :: [rebar_app_info:t()],
packages = undefined :: {rebar_dict(), rebar_digraph()} | undefined,
@@ -347,6 +349,15 @@ all_deps(#state_t{all_deps=Apps}) ->
all_deps(State=#state_t{}, NewApps) ->
State#state_t{all_deps=NewApps}.
+all_plugin_deps(#state_t{all_plugin_deps=Apps}) ->
+ Apps.
+
+all_plugin_deps(State=#state_t{}, NewApps) ->
+ State#state_t{all_plugin_deps=NewApps}.
+
+update_all_plugin_deps(State=#state_t{all_plugin_deps=Apps}, NewApps) ->
+ State#state_t{all_plugin_deps=Apps++NewApps}.
+
update_all_deps(State=#state_t{all_deps=Apps}, NewApps) ->
State#state_t{all_deps=Apps++NewApps}.
diff --git a/src/rebar_utils.erl b/src/rebar_utils.erl
index ffa29e6..cc59ed0 100644
--- a/src/rebar_utils.erl
+++ b/src/rebar_utils.erl
@@ -48,6 +48,7 @@
erl_opts/1,
indent/1,
update_code/1,
+ remove_from_code_path/1,
cleanup_code_path/1,
args_to_tasks/1,
expand_env_variable/3,
@@ -581,6 +582,22 @@ update_code(Paths) ->
end
end, Paths).
+remove_from_code_path(Paths) ->
+ lists:foreach(fun(Path) ->
+ Name = filename:basename(Path, "/ebin"),
+ App = list_to_atom(Name),
+ application:load(App),
+ case application:get_key(App, modules) of
+ undefined ->
+ application:unload(App),
+ ok;
+ {ok, Modules} ->
+ application:unload(App),
+ [begin code:purge(M), code:delete(M) end || M <- Modules]
+ end,
+ code:del_path(Path)
+ end, Paths).
+
cleanup_code_path(OrigPath) ->
CurrentPath = code:get_path(),
AddedPaths = CurrentPath -- OrigPath,
diff --git a/test/mock_pkg_resource.erl b/test/mock_pkg_resource.erl
index 9ed0962..eda863b 100644
--- a/test/mock_pkg_resource.erl
+++ b/test/mock_pkg_resource.erl
@@ -15,7 +15,7 @@ mock() -> mock([]).
%% Specific config options are explained in each of the private functions.
-spec mock(Opts) -> ok when
Opts :: [Option],
- Option :: {update, [App]}
+ Option :: {upgrade, [App]}
| {cache_dir, string()}
| {default_vsn, Vsn}
| {override_vsn, [{App, Vsn}]}
@@ -73,6 +73,7 @@ mock_vsn(_Opts) ->
%% into a `rebar.config' file to describe dependencies.
mock_download(Opts) ->
Deps = proplists:get_value(pkgdeps, Opts, []),
+ Config = proplists:get_value(config, Opts, []),
meck:expect(
?MOD, download,
fun (Dir, {pkg, AppBin, Vsn}, _) ->
@@ -83,7 +84,7 @@ mock_download(Opts) ->
Dir, App, binary_to_list(Vsn),
[kernel, stdlib] ++ [element(1,D) || D <- AppDeps]
),
- rebar_test_utils:create_config(Dir, [{deps, AppDeps}]),
+ rebar_test_utils:create_config(Dir, [{deps, AppDeps}]++Config),
TarApp = App++"-"++binary_to_list(Vsn)++".tar",
Tarball = filename:join([Dir, TarApp]),
Contents = filename:join([Dir, "contents.tar.gz"]),
@@ -120,7 +121,6 @@ mock_pkg_index(Opts) ->
meck:expect(rebar_packages, get_packages,
fun(_State) -> {Dict, Digraph} end).
-
%%%%%%%%%%%%%%%
%%% Helpers %%%
%%%%%%%%%%%%%%%
diff --git a/test/rebar_compile_SUITE.erl b/test/rebar_compile_SUITE.erl
index 2dc57c5..7025eef 100644
--- a/test/rebar_compile_SUITE.erl
+++ b/test/rebar_compile_SUITE.erl
@@ -20,6 +20,7 @@
checkout_priority/1,
compile_plugins/1,
compile_global_plugins/1,
+ complex_plugins/1,
highest_version_of_pkg_dep/1,
parse_transform_test/1]).
@@ -49,7 +50,7 @@ all() ->
recompile_when_opts_change, dont_recompile_when_opts_dont_change,
dont_recompile_yrl_or_xrl, delete_beam_if_source_deleted,
deps_in_path, checkout_priority, compile_plugins, compile_global_plugins,
- highest_version_of_pkg_dep, parse_transform_test].
+ complex_plugins, highest_version_of_pkg_dep, parse_transform_test].
build_basic_app(Config) ->
AppDir = ?config(apps, Config),
@@ -408,17 +409,20 @@ compile_plugins(Config) ->
DepName = rebar_test_utils:create_random_name("dep1_"),
PluginName = rebar_test_utils:create_random_name("plugin1_"),
- mock_git_resource:mock([{config, [{plugins, [
- {list_to_atom(PluginName), Vsn}
- ]}]}]),
- mock_pkg_resource:mock([
- {pkgdeps, [{{iolist_to_binary(PluginName), iolist_to_binary(Vsn)}, []}]}
- ]),
+
+ Plugins = rebar_test_utils:expand_deps(git, [{PluginName, Vsn, []}]),
+ mock_git_resource:mock([{deps, rebar_test_utils:flat_deps(Plugins)}]),
+
+ mock_pkg_resource:mock([{pkgdeps, [{{list_to_binary(DepName), list_to_binary(Vsn)}, []}]},
+ {config, [{plugins, [
+ {list_to_atom(PluginName),
+ {git, "http://site.com/user/"++PluginName++".git",
+ {tag, Vsn}}}]}]}]),
RConfFile =
rebar_test_utils:create_config(AppDir,
[{deps, [
- {list_to_atom(DepName), {git, "http://site.com/user/"++DepName++".git", {tag, Vsn}}}
+ list_to_atom(DepName)
]}]),
{ok, RConf} = file:consult(RConfFile),
@@ -480,6 +484,49 @@ compile_global_plugins(Config) ->
meck:unload(rebar_dir).
+%% Tests installing of plugin with transitive deps
+complex_plugins(Config) ->
+ AppDir = ?config(apps, Config),
+
+ meck:new(rebar_dir, [passthrough]),
+
+ Name = rebar_test_utils:create_random_name("app1_"),
+ Vsn = rebar_test_utils:create_random_vsn(),
+ Vsn2 = rebar_test_utils:create_random_vsn(),
+ rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]),
+
+ DepName = rebar_test_utils:create_random_name("dep1_"),
+ DepName2 = rebar_test_utils:create_random_name("dep2_"),
+ DepName3 = rebar_test_utils:create_random_name("dep3_"),
+ PluginName = rebar_test_utils:create_random_name("plugin1_"),
+
+ Deps = rebar_test_utils:expand_deps(git, [{PluginName, Vsn2, [{DepName2, Vsn,
+ [{DepName3, Vsn, []}]}]}
+ ,{DepName, Vsn, []}]),
+ mock_git_resource:mock([{deps, rebar_test_utils:flat_deps(Deps)}]),
+
+ RConfFile =
+ rebar_test_utils:create_config(AppDir,
+ [{deps, [
+ {list_to_atom(DepName), {git, "http://site.com/user/"++DepName++".git", {tag, Vsn}}}
+ ]},
+ {plugins, [
+ {list_to_atom(PluginName), {git, "http://site.com/user/"++PluginName++".git", {tag, Vsn2}}}
+ ]}]),
+ {ok, RConf} = file:consult(RConfFile),
+
+ %% Build with deps.
+ rebar_test_utils:run_and_check(
+ Config, RConf, ["compile"],
+ {ok, [{app, Name},
+ {plugin, PluginName, Vsn2},
+ {plugin, DepName2},
+ {plugin, DepName3},
+ {dep, DepName}]}
+ ),
+
+ meck:unload(rebar_dir).
+
highest_version_of_pkg_dep(Config) ->
AppDir = ?config(apps, Config),
diff --git a/test/rebar_disable_app_SUITE.erl b/test/rebar_disable_app_SUITE.erl
new file mode 100644
index 0000000..dd71ffb
--- /dev/null
+++ b/test/rebar_disable_app_SUITE.erl
@@ -0,0 +1,49 @@
+-module(rebar_disable_app_SUITE).
+-compile(export_all).
+-include_lib("common_test/include/ct.hrl").
+-include_lib("eunit/include/eunit.hrl").
+
+-define(MOD(Name),
+ io_lib:format("-module(~s).~n-export([x/0]).~nx() -> ok.~n", [Name])).
+
+all() -> [disable_app].
+
+init_per_testcase(_, Config) ->
+ rebar_test_utils:init_rebar_state(Config).
+
+end_per_testcase(_, _Config) ->
+ ok.
+
+disable_app(Config) ->
+ AppDir = ?config(apps, Config),
+
+ Name1 = create_random_app(AppDir, "app1_"),
+ Name2 = create_random_app(AppDir, "app2_"),
+
+ RebarConfig = [{excluded_apps, [list_to_atom(Name1)]}],
+ %RebarConfig = [],
+
+ rebar_test_utils:run_and_check(
+ Config, RebarConfig, ["compile"],
+ {ok, [{app, Name2}]}),
+
+ App1 = filename:join([AppDir, "_build", "default", "lib", Name1, "ebin", Name1 ++ ".app"]),
+ ?assertEqual(filelib:is_file(App1), false),
+
+ App2 = filename:join([AppDir, "_build", "default", "lib", Name2, "ebin", Name2 ++ ".app"]),
+ ?assertEqual(filelib:is_file(App2), true).
+
+%%
+%% Utils
+%%
+create_random_app(AppDir, Prefix) ->
+ Name = rebar_test_utils:create_random_name(Prefix),
+ Vsn = rebar_test_utils:create_random_vsn(),
+ rebar_test_utils:create_empty_app(filename:join([AppDir, "apps", Name]), Name, Vsn, [kernel, stdlib]),
+
+ ModName = rebar_test_utils:create_random_name("mod1_"),
+ Mod = filename:join([AppDir, "apps", Name, "src", ModName ++ ".erl"]),
+ ok = filelib:ensure_dir(Mod),
+ Src = ?MOD(ModName),
+ ok = ec_file:write(Mod, Src),
+ Name.
diff --git a/test/rebar_extra_src_dirs_SUITE.erl b/test/rebar_src_dirs_SUITE.erl
index a00bb2d..1804fbf 100644
--- a/test/rebar_extra_src_dirs_SUITE.erl
+++ b/test/rebar_src_dirs_SUITE.erl
@@ -1,4 +1,4 @@
--module(rebar_extra_src_dirs_SUITE).
+-module(rebar_src_dirs_SUITE).
-export([suite/0,
init_per_suite/1,
@@ -6,9 +6,15 @@
init_per_testcase/2,
end_per_testcase/2,
all/0,
+ src_dirs_at_root/1,
+ extra_src_dirs_at_root/1,
+ src_dirs_in_erl_opts/1,
+ extra_src_dirs_in_erl_opts/1,
+ src_dirs_at_root_and_in_erl_opts/1,
+ extra_src_dirs_at_root_and_in_erl_opts/1,
build_basic_app/1,
build_multi_apps/1,
- src_dir_takes_precedence/1]).
+ src_dir_takes_precedence_over_extra/1]).
-include_lib("common_test/include/ct.hrl").
@@ -27,7 +33,88 @@ init_per_testcase(_, Config) ->
end_per_testcase(_, _Config) -> ok.
all() ->
- [build_basic_app, build_multi_apps, src_dir_takes_precedence].
+ [src_dirs_at_root, extra_src_dirs_at_root,
+ src_dirs_in_erl_opts, extra_src_dirs_in_erl_opts,
+ src_dirs_at_root_and_in_erl_opts, extra_src_dirs_at_root_and_in_erl_opts,
+ build_basic_app, build_multi_apps, src_dir_takes_precedence_over_extra].
+
+src_dirs_at_root(Config) ->
+ AppDir = ?config(apps, Config),
+
+ Name = rebar_test_utils:create_random_name("app1_"),
+ Vsn = rebar_test_utils:create_random_vsn(),
+ rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]),
+
+ RebarConfig = [{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, []).
+
+extra_src_dirs_at_root(Config) ->
+ AppDir = ?config(apps, Config),
+
+ Name = rebar_test_utils:create_random_name("app1_"),
+ Vsn = rebar_test_utils:create_random_vsn(),
+ rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]),
+
+ RebarConfig = [{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, []).
+
+src_dirs_in_erl_opts(Config) ->
+ AppDir = ?config(apps, Config),
+
+ Name = rebar_test_utils:create_random_name("app1_"),
+ Vsn = rebar_test_utils:create_random_vsn(),
+ rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]),
+
+ 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, []).
+
+extra_src_dirs_in_erl_opts(Config) ->
+ AppDir = ?config(apps, Config),
+
+ Name = rebar_test_utils:create_random_name("app1_"),
+ Vsn = rebar_test_utils:create_random_vsn(),
+ rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]),
+
+ 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, []).
+
+src_dirs_at_root_and_in_erl_opts(Config) ->
+ AppDir = ?config(apps, Config),
+
+ Name = rebar_test_utils:create_random_name("app1_"),
+ Vsn = rebar_test_utils:create_random_vsn(),
+ rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]),
+
+ RebarConfig = [{erl_opts, [{src_dirs, ["foo", "bar"]}]}, {src_dirs, ["baz", "qux"]}],
+
+ {ok, State} = rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], return),
+
+ ["baz", "qux", "foo", "bar"] = rebar_dir:src_dirs(State, []).
+
+extra_src_dirs_at_root_and_in_erl_opts(Config) ->
+ AppDir = ?config(apps, Config),
+
+ Name = rebar_test_utils:create_random_name("app1_"),
+ Vsn = rebar_test_utils:create_random_vsn(),
+ rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]),
+
+ RebarConfig = [{erl_opts, [{extra_src_dirs, ["foo", "bar"]}]}, {extra_src_dirs, ["baz", "qux"]}],
+
+ {ok, State} = rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], return),
+
+ ["baz", "qux", "foo", "bar"] = rebar_dir:extra_src_dirs(State, []).
build_basic_app(Config) ->
AppDir = ?config(apps, Config),
@@ -118,7 +205,7 @@ build_multi_apps(Config) ->
Mods2 = proplists:get_value(modules, KVs2),
false = lists:member(extra2, Mods2).
-src_dir_takes_precedence(Config) ->
+src_dir_takes_precedence_over_extra(Config) ->
AppDir = ?config(apps, Config),
Name = rebar_test_utils:create_random_name("app1_"),
diff --git a/test/rebar_test_utils.erl b/test/rebar_test_utils.erl
index 68e0603..f53ba20 100644
--- a/test/rebar_test_utils.erl
+++ b/test/rebar_test_utils.erl
@@ -70,7 +70,8 @@ run_and_check(Config, RebarConfig, Command, Expect) ->
%% - src/<file>.app.src
%% And returns a `rebar_app_info' object.
create_app(AppDir, Name, Vsn, Deps) ->
- write_src_file(AppDir, Name),
+ write_src_file(AppDir, Name ++ ".erl"),
+ write_src_file(AppDir, "not_a_real_src_" ++ Name ++ ".erl"),
write_app_src_file(AppDir, Name, Vsn, Deps),
rebar_app_info:new(Name, Vsn, AppDir, Deps).
@@ -297,9 +298,9 @@ check_results(AppDir, Expected) ->
end, Expected).
write_src_file(Dir, Name) ->
- Erl = filename:join([Dir, "src", "not_a_real_src_" ++ Name ++ ".erl"]),
+ Erl = filename:join([Dir, "src", Name]),
ok = filelib:ensure_dir(Erl),
- ok = ec_file:write(Erl, erl_src_file("not_a_real_src_" ++ Name ++ ".erl")).
+ ok = ec_file:write(Erl, erl_src_file(Name)).
write_eunitized_src_file(Dir, Name) ->
Erl = filename:join([Dir, "src", "not_a_real_src_" ++ Name ++ ".erl"]),
diff --git a/test/rebar_upgrade_SUITE.erl b/test/rebar_upgrade_SUITE.erl
index 793f10a..79cf29e 100644
--- a/test/rebar_upgrade_SUITE.erl
+++ b/test/rebar_upgrade_SUITE.erl
@@ -3,7 +3,7 @@
-include_lib("eunit/include/eunit.hrl").
-compile(export_all).
-all() -> [{group, git}, {group, pkg}].
+all() -> [{group, git}, {group, pkg}, novsn_pkg].
groups() ->
[{all, [], [top_a, top_b, top_c, top_d1, top_d2, top_e,
@@ -31,6 +31,26 @@ init_per_group(_, Config) ->
end_per_group(_, Config) ->
Config.
+init_per_testcase(novsn_pkg, Config0) ->
+ Config = rebar_test_utils:init_rebar_state(Config0, "novsn_pkg_"),
+ AppDir = ?config(apps, Config),
+ RebarConf = rebar_test_utils:create_config(AppDir, [{deps, [fakeapp]}]),
+
+ Deps = [{{<<"fakeapp">>, <<"1.0.0">>}, []}],
+ UpDeps = [{{<<"fakeapp">>, <<"1.1.0">>}, []}],
+ Upgrades = ["fakeapp"],
+
+ [{rebarconfig, RebarConf},
+ {mock, fun() ->
+ catch mock_pkg_resource:unmock(),
+ mock_pkg_resource:mock([{pkgdeps, Deps}, {upgrade, []}])
+ end},
+ {mock_update, fun() ->
+ catch mock_pkg_resource:unmock(),
+ mock_pkg_resource:mock([{pkgdeps, UpDeps}, {upgrade, Upgrades}])
+ end},
+ {expected, {ok, [{dep, "fakeapp", "1.1.0"}, {lock, "fakeapp", "1.1.0"}]}}
+ | Config];
init_per_testcase(Case, Config) ->
DepsType = ?config(deps_type, Config),
{Deps, UpDeps, ToUp, Expectations} = upgrades(Case),
@@ -517,6 +537,18 @@ run(Config) ->
Config, NewRebarConfig, ["upgrade", App], Expectation
).
+novsn_pkg(Config) ->
+ apply(?config(mock, Config), []),
+ {ok, RebarConfig} = file:consult(?config(rebarconfig, Config)),
+ %% Install dependencies before re-mocking for an upgrade
+ rebar_test_utils:run_and_check(Config, RebarConfig, ["lock"], {ok, []}),
+ Expectation = ?config(expected, Config),
+ apply(?config(mock_update, Config), []),
+ rebar_test_utils:run_and_check(
+ Config, RebarConfig, ["upgrade"], Expectation
+ ),
+ ok.
+
rewrite_locks({ok, Expectations}, Config) ->
AppDir = ?config(apps, Config),
LockFile = filename:join([AppDir, "rebar.lock"]),