Quellcode durchsuchen

Merge pull request #505 from tsloughter/plugins_provider

plugins provider
pull/526/head
Fred Hebert vor 10 Jahren
Ursprung
Commit
70dbbf95c2
11 geänderte Dateien mit 470 neuen und 196 gelöschten Zeilen
  1. +2
    -0
      src/rebar.app.src
  2. +5
    -4
      src/rebar3.erl
  3. +1
    -1
      src/rebar_dir.erl
  4. +31
    -19
      src/rebar_plugins.erl
  5. +4
    -3
      src/rebar_prv_as.erl
  6. +27
    -20
      src/rebar_prv_install_deps.erl
  7. +67
    -0
      src/rebar_prv_plugins.erl
  8. +96
    -0
      src/rebar_prv_plugins_upgrade.erl
  9. +35
    -17
      src/rebar_state.erl
  10. +1
    -132
      test/rebar_compile_SUITE.erl
  11. +201
    -0
      test/rebar_plugins_SUITE.erl

+ 2
- 0
src/rebar.app.src Datei anzeigen

@ -44,6 +44,8 @@
rebar_prv_lock,
rebar_prv_new,
rebar_prv_packages,
rebar_prv_plugins,
rebar_prv_plugins_upgrade,
rebar_prv_release,
rebar_prv_report,
rebar_prv_shell,

+ 5
- 4
src/rebar3.erl Datei anzeigen

@ -95,12 +95,12 @@ run_aux(State, RawArgs) ->
%% 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,
filename:join(filename:absname(rebar_state:dir(State2)), BaseDir)),
filename:join(filename:absname(rebar_state:dir(State2)), BaseDir)),
{ok, Providers} = application:get_env(rebar, providers),
%% Providers can modify profiles stored in opts, so set default after initializing providers
State4 = rebar_state:create_logic_providers(Providers, State3),
State5 = rebar_plugins:install(State4),
State5 = rebar_plugins:project_apps_install(State4),
State6 = rebar_state:default(State5, rebar_state:opts(State5)),
{Task, Args} = parse_args(RawArgs),
@ -133,13 +133,14 @@ init_config() ->
%% We don't want to worry about global plugin install state effecting later
%% usage. So we throw away the global profile state used for plugin install.
GlobalConfigThrowAway = rebar_state:current_profiles(GlobalConfig, ["n>global"]),
GlobalConfigThrowAway = rebar_state:current_profiles(GlobalConfig, [global]),
GlobalState = rebar_plugins:handle_plugins(global,
rebar_state:get(GlobalConfigThrowAway, plugins, []),
GlobalConfigThrowAway),
GlobalPlugins = rebar_state:providers(GlobalState),
GlobalConfig2 = rebar_state:set(GlobalConfig, plugins, []),
rebar_state:providers(rebar_state:new(GlobalConfig2, Config1), GlobalPlugins);
GlobalConfig3 = rebar_state:set(GlobalConfig2, {plugins, global}, rebar_state:get(GlobalConfigThrowAway, plugins, [])),
rebar_state:providers(rebar_state:new(GlobalConfig3, Config1), GlobalPlugins);
false ->
rebar_state:new(Config1)
end,

+ 1
- 1
src/rebar_dir.erl Datei anzeigen

@ -35,6 +35,7 @@ base_dir(State) ->
profile_dir(State, Profiles) ->
{BaseDir, ProfilesStrings} = case [ec_cnv:to_list(P) || P <- Profiles] of
["global" | _] -> {?MODULE:global_cache_dir(State), [""]};
["bootstrap", "default"] -> {rebar_state:get(State, base_dir, ?DEFAULT_BASE_DIR), ["default"]};
["default"] -> {rebar_state:get(State, base_dir, ?DEFAULT_BASE_DIR), ["default"]};
%% drop `default` from the profile dir if it's implicit and reverse order
%% of profiles to match order passed to `as`
@ -43,7 +44,6 @@ profile_dir(State, Profiles) ->
ProfilesDir = string:join(ProfilesStrings, "+"),
filename:join(BaseDir, ProfilesDir).
-spec deps_dir(rebar_state:t()) -> file:filename_all().
deps_dir(State) ->
filename:join(base_dir(State), rebar_state:get(State, deps_dir, ?DEFAULT_DEPS_DIR)).

+ 31
- 19
src/rebar_plugins.erl Datei anzeigen

@ -3,7 +3,10 @@
-module(rebar_plugins).
-export([install/1, handle_plugins/2, handle_plugins/3]).
-export([project_apps_install/1
,install/1
,handle_plugins/3
,handle_plugins/4]).
-include("rebar.hrl").
@ -11,26 +14,35 @@
%% Public API
%% ===================================================================
-spec install(rebar_state:t()) -> rebar_state:t().
install(State) ->
Plugins = rebar_state:get(State, plugins, []),
-spec project_apps_install(rebar_state:t()) -> rebar_state:t().
project_apps_install(State) ->
Profiles = rebar_state:current_profiles(State),
ProjectApps = rebar_state:project_apps(State),
OtherPlugins = lists:flatmap(fun(App) ->
AppDir = rebar_app_info:dir(App),
C = rebar_config:consult(AppDir),
S = rebar_state:new(rebar_state:new(), C, AppDir),
rebar_state:get(S, plugins, [])
end, ProjectApps),
handle_plugins(Plugins++OtherPlugins, State).
lists:foldl(fun(Profile, StateAcc) ->
Plugins = rebar_state:get(State, {plugins, Profile}, []),
handle_plugins(Profile, Plugins, StateAcc),
lists:foldl(fun(App, StateAcc1) ->
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}, []),
handle_plugins(Profile, Plugins2, StateAcc1)
end, StateAcc, ProjectApps)
end, State, Profiles).
-spec handle_plugins([rebar_prv_install_deps:dep()], rebar_state:t()) -> rebar_state:t().
handle_plugins(Plugins, State) ->
handle_plugins(default, Plugins, State).
-spec install(rebar_state:t()) -> rebar_state:t().
install(State) ->
Profiles = rebar_state:current_profiles(State),
lists:foldl(fun(Profile, StateAcc) ->
Plugins = rebar_state:get(State, {plugins, Profile}, []),
handle_plugins(Profile, Plugins, StateAcc)
end, State, Profiles).
handle_plugins(Profile, Plugins, State) ->
handle_plugins(Profile, Plugins, State, false).
handle_plugins(Profile, Plugins, State, Upgrade) ->
%% 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),
@ -39,7 +51,7 @@ handle_plugins(Profile, Plugins, State) ->
%% 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),
{NewPlugins, NewState} = handle_plugin(Profile, Plugin, StateAcc, Upgrade),
{PluginAcc++NewPlugins, NewState}
end, {[], State1}, Plugins),
@ -49,9 +61,9 @@ handle_plugins(Profile, Plugins, State) ->
rebar_state:create_logic_providers(PluginProviders, State4).
handle_plugin(Profile, Plugin, State) ->
handle_plugin(Profile, Plugin, State, Upgrade) ->
try
{ok, Apps, State2} = rebar_prv_install_deps:handle_deps(Profile, State, [Plugin]),
{ok, Apps, State2} = rebar_prv_install_deps:handle_deps(Profile, State, [Plugin], Upgrade),
{no_cycle, Sorted} = rebar_prv_install_deps:find_cycles(Apps),
ToBuild = rebar_prv_install_deps:cull_compile(Sorted, []),

+ 4
- 3
src/rebar_prv_as.erl Datei anzeigen

@ -38,13 +38,14 @@ do(State) ->
{error, "At least one profile must be specified when using `as`"};
_ ->
State1 = rebar_state:apply_profiles(State, [list_to_atom(X) || X <- Profiles]),
State2 = rebar_plugins:project_apps_install(State1),
{FirstTask, FirstTaskArgs} = hd(Tasks),
FirstTaskAtom = list_to_atom(FirstTask),
case rebar_core:process_namespace(State1, FirstTaskAtom) of
{ok, State2, NewTask} ->
case rebar_core:process_namespace(State2, FirstTaskAtom) of
{ok, State3, NewTask} ->
rebar_prv_do:do_tasks(
[{atom_to_list(NewTask),FirstTaskArgs}|tl(Tasks)],
State2
State3
);
{error, Reason} ->
{error, Reason}

+ 27
- 20
src/rebar_prv_install_deps.erl Datei anzeigen

@ -234,22 +234,26 @@ handle_pkg_dep(Profile, Pkg, Packages, Upgrade, DepsDir, Fetched, Seen, Locks, S
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),
S2 = rebar_state:apply_overrides(S1, Name),
Plugins = rebar_state:get(S2, plugins, []),
S3 = rebar_state:set(S2, {plugins, Profile}, Plugins),
S4 = rebar_state:apply_profiles(S3, Profiles),
AppInfo2 = rebar_app_info:state(AppInfo1, S4),
%% 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),
S5 = rebar_plugins:install(S4),
AppInfo3 = rebar_app_info:state(AppInfo2, S5),
{[AppInfo3 | Fetched], NewSeen, NewState}.
maybe_lock(Profile, AppInfo, Seen, State, Level) ->
Name = rebar_app_info:name(AppInfo),
case rebar_app_info:is_checkout(AppInfo) of
false ->
case Profile of
default ->
Name = rebar_app_info:name(AppInfo),
case sets:is_element(Name, Seen) of
false ->
Locks = rebar_state:lock(State),
@ -264,10 +268,10 @@ maybe_lock(Profile, AppInfo, Seen, State, Level) ->
{Seen, State}
end;
_ ->
{Seen, State}
{sets:add_element(Name, Seen), State}
end;
true ->
{Seen, State}
{sets:add_element(Name, Seen), State}
end.
package_to_app(DepsDir, Packages, {Name, Vsn, Level}, IsLock, State) ->
@ -367,7 +371,6 @@ handle_upgrade(AppInfo, Profile, SrcDeps, PkgDeps, SrcApps, Level, State, Locks)
{true, AppInfo1} ->
handle_dep(AppInfo1, Profile, SrcDeps, PkgDeps, SrcApps,
Level, State, Locks);
{false, AppInfo1} ->
{[AppInfo1|SrcDeps], PkgDeps, SrcApps, State, Locks}
end;
@ -378,7 +381,7 @@ handle_upgrade(AppInfo, Profile, SrcDeps, PkgDeps, SrcApps, Level, State, Locks)
handle_dep(AppInfo, Profile, SrcDeps, PkgDeps, SrcApps, Level, State, Locks) ->
DepsDir = profile_dep_dir(State, Profile),
{AppInfo1, NewSrcDeps, NewPkgDeps, NewLocks, State1} =
handle_dep(State, DepsDir, AppInfo, Locks, Level),
handle_dep(State, Profile, DepsDir, AppInfo, Locks, Level),
AppInfo2 = rebar_app_info:dep_level(AppInfo1, Level),
{NewSrcDeps ++ SrcDeps
,NewPkgDeps++PkgDeps
@ -386,9 +389,9 @@ handle_dep(AppInfo, Profile, SrcDeps, PkgDeps, SrcApps, Level, State, Locks) ->
,State1
,NewLocks}.
-spec handle_dep(rebar_state:t(), file:filename_all(), rebar_app_info:t(), list(), integer()) ->
-spec handle_dep(rebar_state:t(), atom(), file:filename_all(), rebar_app_info:t(), list(), integer()) ->
{rebar_app_info:t(), [rebar_app_info:t()], [pkg_dep()], [integer()]}.
handle_dep(State, DepsDir, AppInfo, Locks, Level) ->
handle_dep(State, Profile, DepsDir, AppInfo, Locks, Level) ->
Profiles = rebar_state:current_profiles(State),
Name = rebar_app_info:name(AppInfo),
@ -396,20 +399,24 @@ handle_dep(State, DepsDir, AppInfo, Locks, Level) ->
S = rebar_app_info:state(AppInfo),
S1 = rebar_state:new(S, C, rebar_app_info:dir(AppInfo)),
S2 = rebar_state:apply_profiles(S1, Profiles),
S3 = rebar_state:apply_overrides(S2, Name),
AppInfo1 = rebar_app_info:state(AppInfo, S3),
S2 = rebar_state:apply_overrides(S1, Name),
Plugins = rebar_state:get(S2, plugins, []),
S3 = rebar_state:set(S2, {plugins, Profile}, Plugins),
S4 = rebar_state:apply_profiles(S3, Profiles),
AppInfo1 = rebar_app_info:state(AppInfo, S4),
%% Dep may have plugins to install. Find and install here.
S4 = rebar_plugins:handle_plugins(rebar_state:get(S3, plugins, []), S3),
AppInfo2 = rebar_app_info:state(AppInfo1, S4),
S5 = rebar_plugins:install(S4),
AppInfo2 = rebar_app_info:state(AppInfo1, S5),
%% Upgrade lock level to be the level the dep will have in this dep tree
Deps = rebar_state:get(S4, deps, []),
Deps = rebar_state:get(S5, deps, []),
NewLocks = [{DepName, Source, LockLevel+Level} ||
{DepName, Source, LockLevel} <- rebar_state:get(S4, {locks, default}, [])],
{DepName, Source, LockLevel} <- rebar_state:get(S5, {locks, default}, [])],
AppInfo3 = rebar_app_info:deps(AppInfo2, rebar_state:deps_names(Deps)),
{SrcDeps, PkgDeps} = parse_deps(DepsDir, Deps, S4, Locks, Level+1),
{SrcDeps, PkgDeps} = parse_deps(DepsDir, Deps, S5, Locks, Level+1),
{AppInfo3, SrcDeps, PkgDeps, Locks++NewLocks, State}.
-spec maybe_fetch(rebar_app_info:t(), atom(), boolean(),

+ 67
- 0
src/rebar_prv_plugins.erl Datei anzeigen

@ -0,0 +1,67 @@
-module(rebar_prv_plugins).
-behaviour(provider).
-export([init/1,
do/1,
format_error/1]).
-include("rebar.hrl").
-include_lib("providers/include/providers.hrl").
-define(PROVIDER, list).
-define(NAMESPACE, plugins).
-define(DEPS, []).
-spec init(rebar_state:t()) -> {ok, rebar_state:t()}.
init(State) ->
State1 = rebar_state:add_provider(
State,
providers:create([
{name, ?PROVIDER},
{module, ?MODULE},
{namespace, ?NAMESPACE},
{bare, true},
{deps, ?DEPS},
{example, "rebar3 plugins list"},
{short_desc, "List local and global plugins for this project"},
{desc, "List local and global plugins for this project"},
{opts, []}])),
{ok, State1}.
-spec do(rebar_state:t()) -> {ok, rebar_state:t()} | {error, string()}.
do(State) ->
GlobalConfigFile = rebar_dir:global_config(),
GlobalConfig = rebar_state:new(rebar_config:consult_file(GlobalConfigFile)),
GlobalPlugins = rebar_state:get(GlobalConfig, plugins, []),
GlobalPluginsDir = filename:join(rebar_dir:global_cache_dir(State), "plugins"),
display_plugins("Global plugins", GlobalPluginsDir, GlobalPlugins),
Plugins = rebar_state:get(State, plugins, []),
PluginsDir =rebar_dir:plugins_dir(State),
display_plugins("Local plugins", PluginsDir, Plugins),
{ok, State}.
-spec format_error(any()) -> iolist().
format_error(Reason) ->
io_lib:format("~p", [Reason]).
display_plugins(_Header, _Dir, []) ->
ok;
display_plugins(Header, Dir, Plugins) ->
?CONSOLE("--- ~s ---", [Header]),
display_plugins(Dir, Plugins),
?CONSOLE("", []).
display_plugins(Dir, Plugins) ->
lists:foreach(fun(Plugin) ->
Name = if is_atom(Plugin) -> Plugin;
is_tuple(Plugin) -> element(1, Plugin)
end,
case rebar_app_info:discover(filename:join(Dir, Name)) of
{ok, _App} ->
?CONSOLE("~s", [Name]);
not_found ->
?DEBUG("Unable to find plugin ~s", [Name])
end
end, Plugins).

+ 96
- 0
src/rebar_prv_plugins_upgrade.erl Datei anzeigen

@ -0,0 +1,96 @@
-module(rebar_prv_plugins_upgrade).
-behaviour(provider).
-export([init/1,
do/1,
format_error/1]).
-include("rebar.hrl").
-include_lib("providers/include/providers.hrl").
-define(PROVIDER, upgrade).
-define(NAMESPACE, plugins).
-define(DEPS, []).
-spec init(rebar_state:t()) -> {ok, rebar_state:t()}.
init(State) ->
State1 = rebar_state:add_provider(
State,
providers:create([
{name, ?PROVIDER},
{module, ?MODULE},
{namespace, ?NAMESPACE},
{bare, true},
{deps, ?DEPS},
{example, "rebar3 plugins upgrade <plugin>"},
{short_desc, "Uprade plugins"},
{desc, "List or upgrade plugins"},
{opts, [{plugin, undefined, undefined, string,
"Plugin to upgrade"}]}])),
{ok, State1}.
-spec do(rebar_state:t()) -> {ok, rebar_state:t()} | {error, string()}.
do(State) ->
{Args, _} = rebar_state:command_parsed_args(State),
Plugin = proplists:get_value(plugin, Args, <<"">>),
upgrade(Plugin, State).
-spec format_error(any()) -> iolist().
format_error({not_found, Plugin}) ->
io_lib:format("Plugin to upgrade not found: ~s", [Plugin]);
format_error(Reason) ->
io_lib:format("~p", [Reason]).
upgrade(Plugin, State) ->
Profiles = rebar_state:current_profiles(State),
Dep = ec_lists:search(fun(Profile) ->
Plugins = rebar_state:get(State, {plugins, Profile}, []),
case find(list_to_atom(Plugin), Plugins) of
false ->
not_found;
P ->
{ok, P}
end
end, Profiles),
case Dep of
not_found ->
?PRV_ERROR({not_found, Plugin});
{ok, P, Profile} ->
State1 = rebar_state:set(State, deps_dir, ?DEFAULT_PLUGINS_DIR),
{ok, Apps, _State2} = rebar_prv_install_deps:handle_deps(Profile
,State1
,[P]
,true),
{no_cycle, Sorted} = rebar_prv_install_deps:find_cycles(Apps),
ToBuild = rebar_prv_install_deps:cull_compile(Sorted, []),
%% 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, Apps, State) || AppInfo <- ToBuild],
{ok, State}
end.
find(_Plugin, []) ->
false;
find(Plugin, [Plugin | _Plugins]) ->
Plugin;
find(Plugin, [Plugin1 | Plugins]) when is_tuple(Plugin1) ->
case element(1, Plugin1) =:= Plugin of
true ->
Plugin1;
false ->
find(Plugin, Plugins)
end.
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, AppDir),
rebar_prv_compile:compile(S, Providers, AppInfo).

+ 35
- 17
src/rebar_state.erl Datei anzeigen

@ -82,7 +82,8 @@ new() ->
new(Config) when is_list(Config) ->
BaseState = base_state(),
Deps = proplists:get_value(deps, Config, []),
Terms = [{{deps, default}, Deps} | Config],
Plugins = proplists:get_value(plugins, Config, []),
Terms = [{{deps, default}, Deps}, {{plugins, default}, Plugins} | Config],
true = rebar_config:verify_config_format(Terms),
Opts = dict:from_list(Terms),
BaseState#state_t { dir = rebar_dir:get_cwd(),
@ -95,7 +96,8 @@ new(Profile, Config) when is_atom(Profile)
BaseState = base_state(),
Deps = proplists:get_value(deps, Config, []),
Terms = [{{deps, default}, Deps} | Config],
Plugins = proplists:get_value(plugins, Config, []),
Terms = [{{deps, default}, Deps}, {{plugins, default}, Plugins} | Config],
true = rebar_config:verify_config_format(Terms),
Opts = dict:from_list(Terms),
BaseState#state_t { dir = rebar_dir:get_cwd(),
@ -112,18 +114,19 @@ new(ParentState, Config, Dir) ->
Opts = ParentState#state_t.opts,
LocalOpts = 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],
Terms = [{{locks, default}, D}, {{deps, default}, Deps} | Config],
true = rebar_config:verify_config_format(Terms),
dict:from_list(Terms);
%% 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],
Plugins = proplists:get_value(plugins, Config, []),
Terms = [{{locks, default}, D}, {{deps, default}, Deps}, {{plugins, default}, Plugins} | Config],
true = rebar_config:verify_config_format(Terms),
dict:from_list(Terms);
_ ->
D = proplists:get_value(deps, Config, []),
Terms = [{{deps, default}, D} | Config],
true = rebar_config:verify_config_format(Terms),
dict:from_list(Terms)
D = proplists:get_value(deps, Config, []),
Plugins = proplists:get_value(plugins, Config, []),
Terms = [{{deps, default}, D}, {{plugins, default}, Plugins} | Config],
true = rebar_config:verify_config_format(Terms),
dict:from_list(Terms)
end,
NewOpts = merge_opts(LocalOpts, Opts),
@ -257,14 +260,17 @@ apply_overrides(State=#state_t{overrides=Overrides}, AppName) ->
StateAcc
end, State1, Overrides),
lists:foldl(fun({add, N, O}, StateAcc) when N =:= Name ->
State3 = lists:foldl(fun({add, N, O}, StateAcc) when N =:= Name ->
lists:foldl(fun({Key, Value}, StateAcc1) ->
OldValue = rebar_state:get(StateAcc1, Key, []),
rebar_state:set(StateAcc1, Key, Value++OldValue)
end, StateAcc, O);
(_, StateAcc) ->
StateAcc
end, State2, Overrides).
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, []),
@ -280,6 +286,7 @@ apply_profiles(State, [default]) ->
apply_profiles(State=#state_t{default = Defaults, current_profiles=CurrentProfiles}, Profiles) ->
AppliedProfiles = deduplicate(CurrentProfiles ++ Profiles),
ConfigProfiles = rebar_state:get(State, profiles, []),
NewOpts =
lists:foldl(fun(default, OptsAcc) ->
OptsAcc;
@ -303,11 +310,18 @@ do_deduplicate([Head | Rest], Acc) ->
merge_opts(Profile, NewOpts, OldOpts) ->
Opts = merge_opts(NewOpts, OldOpts),
case dict:find(deps, NewOpts) of
Opts2 = case dict:find(plugins, NewOpts) of
{ok, Value} ->
dict:store({deps, Profile}, Value, Opts);
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) ->
@ -315,6 +329,10 @@ merge_opts(NewOpts, OldOpts) ->
NewValue;
({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) ->

+ 1
- 132
test/rebar_compile_SUITE.erl Datei anzeigen

@ -18,9 +18,6 @@
deps_in_path/1,
delete_beam_if_source_deleted/1,
checkout_priority/1,
compile_plugins/1,
compile_global_plugins/1,
complex_plugins/1,
highest_version_of_pkg_dep/1,
parse_transform_test/1]).
@ -49,8 +46,7 @@ all() ->
build_all_srcdirs, recompile_when_hrl_changes,
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,
complex_plugins, highest_version_of_pkg_dep, parse_transform_test].
deps_in_path, checkout_priority, highest_version_of_pkg_dep, parse_transform_test].
build_basic_app(Config) ->
AppDir = ?config(apps, Config),
@ -399,133 +395,6 @@ checkout_priority(Config) ->
?assertEqual(Vsn2, proplists:get_value(vsn, DepProps)),
?assertEqual(Vsn2, proplists:get_value(vsn, PkgProps)).
%% Tests that compiling a project installs and compiles the plugins of deps
compile_plugins(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]),
DepName = rebar_test_utils:create_random_name("dep1_"),
PluginName = rebar_test_utils:create_random_name("plugin1_"),
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)
]}]),
{ok, RConf} = file:consult(RConfFile),
%% Build with deps.
rebar_test_utils:run_and_check(
Config, RConf, ["compile"],
{ok, [{app, Name}, {plugin, PluginName}, {dep, DepName}]}
).
%% Tests that compiling a project installs and compiles the global plugins
compile_global_plugins(Config) ->
AppDir = ?config(apps, Config),
GlobalDir = filename:join(AppDir, "global"),
GlobalConfigDir = filename:join([GlobalDir, ".config", "rebar3"]),
GlobalConfig = filename:join([GlobalDir, ".config", "rebar3", "rebar.config"]),
meck:new(rebar_dir, [passthrough]),
meck:expect(rebar_dir, global_config, fun() -> GlobalConfig end),
meck:expect(rebar_dir, global_cache_dir, fun(_) -> GlobalDir end),
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_"),
PluginName = rebar_test_utils:create_random_name("plugin1_"),
mock_git_resource:mock([{deps, [{list_to_atom(PluginName), Vsn},
{list_to_atom(PluginName), Vsn2},
{{iolist_to_binary(DepName), iolist_to_binary(Vsn)}, []}]}]),
rebar_test_utils:create_config(GlobalConfigDir,
[{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}}}
]},
{plugins, [
{list_to_atom(PluginName), {git, "http://site.com/user/"++PluginName++".git", {tag, Vsn2}}}
]}]),
{ok, RConf} = file:consult(RConfFile),
%% Runs global plugin install
rebar3:init_config(),
%% Build with deps.
rebar_test_utils:run_and_check(
Config, RConf, ["compile"],
{ok, [{app, Name},
{global_plugin, PluginName, Vsn},
{plugin, PluginName, Vsn2},
{dep, DepName}]}
),
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),

+ 201
- 0
test/rebar_plugins_SUITE.erl Datei anzeigen

@ -0,0 +1,201 @@
-module(rebar_plugins_SUITE).
-export([suite/0,
init_per_suite/1,
end_per_suite/1,
init_per_testcase/2,
end_per_testcase/2,
all/0,
compile_plugins/1,
compile_global_plugins/1,
complex_plugins/1,
upgrade/1]).
-include_lib("common_test/include/ct.hrl").
-include_lib("eunit/include/eunit.hrl").
-include_lib("kernel/include/file.hrl").
suite() ->
[].
init_per_suite(Config) ->
Config.
end_per_suite(_Config) ->
ok.
init_per_testcase(_, Config) ->
rebar_test_utils:init_rebar_state(Config).
end_per_testcase(_, _Config) ->
catch meck:unload().
all() ->
[compile_plugins, compile_global_plugins, complex_plugins, upgrade].
%% Tests that compiling a project installs and compiles the plugins of deps
compile_plugins(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]),
DepName = rebar_test_utils:create_random_name("dep1_"),
PluginName = rebar_test_utils:create_random_name("plugin1_"),
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)
]}]),
{ok, RConf} = file:consult(RConfFile),
%% Build with deps.
rebar_test_utils:run_and_check(
Config, RConf, ["compile"],
{ok, [{app, Name}, {plugin, PluginName}, {dep, DepName}]}
).
%% Tests that compiling a project installs and compiles the global plugins
compile_global_plugins(Config) ->
AppDir = ?config(apps, Config),
GlobalDir = filename:join(AppDir, "global"),
GlobalConfigDir = filename:join([GlobalDir, ".config", "rebar3"]),
GlobalConfig = filename:join([GlobalDir, ".config", "rebar3", "rebar.config"]),
meck:new(rebar_dir, [passthrough]),
meck:expect(rebar_dir, global_config, fun() -> GlobalConfig end),
meck:expect(rebar_dir, global_cache_dir, fun(_) -> GlobalDir end),
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_"),
PluginName = rebar_test_utils:create_random_name("plugin1_"),
mock_git_resource:mock([{deps, [{list_to_atom(PluginName), Vsn},
{list_to_atom(PluginName), Vsn2},
{{iolist_to_binary(DepName), iolist_to_binary(Vsn)}, []}]}]),
rebar_test_utils:create_config(GlobalConfigDir,
[{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}}}
]},
{plugins, [
{list_to_atom(PluginName), {git, "http://site.com/user/"++PluginName++".git", {tag, Vsn2}}}
]}]),
{ok, RConf} = file:consult(RConfFile),
%% Runs global plugin install
rebar3:init_config(),
%% Build with deps.
rebar_test_utils:run_and_check(
Config, RConf, ["compile"],
{ok, [{app, Name},
{global_plugin, PluginName, Vsn},
{plugin, PluginName, Vsn2},
{dep, DepName}]}
),
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).
upgrade(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]),
PkgName = rebar_test_utils:create_random_name("pkg1_"),
mock_git_resource:mock([]),
mock_pkg_resource:mock([
{pkgdeps, [{{iolist_to_binary(PkgName), <<"0.1.0">>}, []},
{{iolist_to_binary(PkgName), <<"0.0.1">>}, []},
{{iolist_to_binary(PkgName), <<"0.1.1">>}, []}]}
]),
RConfFile = rebar_test_utils:create_config(AppDir, [{plugins, [list_to_atom(PkgName)]}]),
{ok, RConf} = file:consult(RConfFile),
%% Build with deps.
rebar_test_utils:run_and_check(
Config, RConf, ["compile"],
{ok, [{app, Name}, {plugin, PkgName, <<"0.1.1">>}]}
),
catch mock_pkg_resource:unmock(),
mock_pkg_resource:mock([
{pkgdeps, [{{iolist_to_binary(PkgName), <<"0.1.0">>}, []},
{{iolist_to_binary(PkgName), <<"0.0.1">>}, []},
{{iolist_to_binary(PkgName), <<"0.1.3">>}, []},
{{iolist_to_binary(PkgName), <<"0.1.1">>}, []}]},
{upgrade, [PkgName]}
]),
%% Build with deps.
rebar_test_utils:run_and_check(
Config, RConf, ["plugins", "upgrade", PkgName],
{ok, [{app, Name}, {plugin, PkgName, <<"0.1.3">>}]}
).

Laden…
Abbrechen
Speichern