aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/rlx_app_discovery.erl11
-rw-r--r--src/rlx_config.erl2
-rw-r--r--src/rlx_prv_assembler.erl44
-rw-r--r--src/rlx_state.erl12
-rw-r--r--test/rlx_release_SUITE.erl30
5 files changed, 94 insertions, 5 deletions
diff --git a/src/rlx_app_discovery.erl b/src/rlx_app_discovery.erl
index 6ac8d11..3d58185 100644
--- a/src/rlx_app_discovery.erl
+++ b/src/rlx_app_discovery.erl
@@ -118,8 +118,10 @@ resolve_app_metadata(State, LibDirs) ->
end] of
[] ->
SkipApps = rlx_state:skip_apps(State),
- AppMeta1 = [App || {ok, App} <- setup_overrides(State, AppMeta0),
- not lists:keymember(rlx_app_info:name(App), 1, SkipApps)],
+ ExcludeApps = rlx_state:exclude_apps(State),
+ AppMeta1 = [rm_exclude_apps(App, ExcludeApps) ||
+ {ok, App} <- setup_overrides(State, AppMeta0),
+ not lists:keymember(rlx_app_info:name(App), 1, SkipApps++ExcludeApps)],
ec_cmd_log:debug(rlx_state:log(State),
fun() ->
["Resolved the following OTP Applications from the system: \n",
@@ -129,6 +131,11 @@ resolve_app_metadata(State, LibDirs) ->
Errors ->
?RLX_ERROR(Errors)
end.
+%% Apps listed in {exclude_apps, [...]} must be removed from applications lists
+rm_exclude_apps(App, ExcludeApps) ->
+ ActiveApps = lists:subtract(rlx_app_info:active_deps(App), ExcludeApps),
+ LibraryApps = lists:subtract(rlx_app_info:library_deps(App), ExcludeApps),
+ rlx_app_info:library_deps(rlx_app_info:active_deps(App, ActiveApps), LibraryApps).
app_name({warning, _}) ->
undefined;
diff --git a/src/rlx_config.erl b/src/rlx_config.erl
index 045bf33..df08342 100644
--- a/src/rlx_config.erl
+++ b/src/rlx_config.erl
@@ -182,6 +182,8 @@ load_terms({add_providers, Providers0}, {ok, State0}) ->
end;
load_terms({skip_apps, SkipApps0}, {ok, State0}) ->
{ok, rlx_state:skip_apps(State0, SkipApps0)};
+load_terms({exclude_apps, ExcludeApps0}, {ok, State0}) ->
+ {ok, rlx_state:exclude_apps(State0, ExcludeApps0)};
load_terms({debug_info, DebugInfo}, {ok, State0}) ->
{ok, rlx_state:debug_info(State0, DebugInfo)};
load_terms({overrides, Overrides0}, {ok, State0}) ->
diff --git a/src/rlx_prv_assembler.erl b/src/rlx_prv_assembler.erl
index ee81631..9799204 100644
--- a/src/rlx_prv_assembler.erl
+++ b/src/rlx_prv_assembler.erl
@@ -203,9 +203,49 @@ copy_app_(App, AppDir, TargetDir, IncludeSrc) ->
remove_symlink_or_directory(TargetDir),
case rlx_app_info:link(App) of
true ->
- link_directory(AppDir, TargetDir);
+ link_directory(AppDir, TargetDir),
+ rewrite_app_file(App, AppDir);
false ->
- copy_directory(AppDir, TargetDir, IncludeSrc)
+ copy_directory(AppDir, TargetDir, IncludeSrc),
+ rewrite_app_file(App, TargetDir)
+ end.
+
+%% If excluded apps exist in this App's applications list we must write a new .app
+rewrite_app_file(App, TargetDir) ->
+ Name = rlx_app_info:name(App),
+ ActiveDeps = rlx_app_info:active_deps(App),
+ IncludedDeps = rlx_app_info:library_deps(App),
+ AppFile = filename:join([TargetDir, "ebin", ec_cnv:to_list(Name) ++ ".app"]),
+
+ {ok, [{application, AppName, AppData}]} = file:consult(AppFile),
+ OldActiveDeps = proplists:get_value(applications, AppData, []),
+ OldIncludedDeps = proplists:get_value(included_applications, AppData, []),
+
+ case {OldActiveDeps, OldIncludedDeps} of
+ {ActiveDeps, IncludedDeps} ->
+ ok;
+ _ ->
+ AppData1 = lists:keyreplace(applications
+ ,1
+ ,AppData
+ ,{applications, ActiveDeps}),
+ AppData2 = lists:keyreplace(included_applications
+ ,1
+ ,AppData1
+ ,{included_applications, IncludedDeps}),
+ Spec = io_lib:format("~p.\n", [{application, AppName, AppData2}]),
+ write_file_if_contents_differ(AppFile, Spec)
+ end.
+
+write_file_if_contents_differ(Filename, Bytes) ->
+ ToWrite = iolist_to_binary(Bytes),
+ case file:read_file(Filename) of
+ {ok, ToWrite} ->
+ ok;
+ {ok, _} ->
+ file:write_file(Filename, ToWrite);
+ {error, _} ->
+ file:write_file(Filename, ToWrite)
end.
remove_symlink_or_directory(TargetDir) ->
diff --git a/src/rlx_state.erl b/src/rlx_state.erl
index f21b682..3bd818a 100644
--- a/src/rlx_state.erl
+++ b/src/rlx_state.erl
@@ -36,6 +36,8 @@
overrides/2,
skip_apps/1,
skip_apps/2,
+ exclude_apps/1,
+ exclude_apps/2,
debug_info/1,
debug_info/2,
goals/1,
@@ -104,6 +106,7 @@
sys_config :: file:filename() | undefined,
overrides=[] :: [{AppName::atom(), Directory::file:filename()}],
skip_apps=[] :: [AppName::atom()],
+ exclude_apps=[] :: [AppName::atom()],
debug_info=keep :: keep | strip,
configured_releases :: releases(),
realized_releases :: releases(),
@@ -186,6 +189,15 @@ skip_apps(#state_t{skip_apps=Apps}) ->
skip_apps(State, SkipApps) ->
State#state_t{skip_apps=SkipApps}.
+-spec exclude_apps(t()) -> [AppName::atom()].
+exclude_apps(#state_t{exclude_apps=Apps}) ->
+ Apps.
+
+%% @doc the application overrides for the system
+-spec exclude_apps(t(), [AppName::atom()]) -> t().
+exclude_apps(State, SkipApps) ->
+ State#state_t{exclude_apps=SkipApps}.
+
-spec debug_info(t()) -> keep | strip.
debug_info(#state_t{debug_info=DebugInfo}) ->
DebugInfo.
diff --git a/test/rlx_release_SUITE.erl b/test/rlx_release_SUITE.erl
index f123e79..e7b6c22 100644
--- a/test/rlx_release_SUITE.erl
+++ b/test/rlx_release_SUITE.erl
@@ -29,6 +29,7 @@
make_scriptless_release/1,
make_overridden_release/1,
make_skip_app_release/1,
+ make_exclude_app_release/1,
make_auto_skip_empty_app_release/1,
make_app_type_none_release/1,
make_rerun_overridden_release/1,
@@ -68,7 +69,7 @@ init_per_testcase(_, Config) ->
all() ->
[make_release, make_extend_release, make_scriptless_release,
make_overridden_release, make_auto_skip_empty_app_release,
- make_skip_app_release, make_app_type_none_release,
+ make_skip_app_release, make_exclude_app_release, make_app_type_none_release,
make_implicit_config_release, make_rerun_overridden_release,
overlay_release, make_goalless_release, make_depfree_release,
make_invalid_config_release, make_relup_release, make_relup_release2,
@@ -309,6 +310,33 @@ make_skip_app_release(Config) ->
?assertNot(lists:member({goal_app_2, "0.0.1"}, AppSpecs)),
?assert(lists:member({lib_dep_1, "0.0.1", load}, AppSpecs)).
+%% Test to ensure that an excluded app and its deps are not included in a release
+make_exclude_app_release(Config) ->
+ LibDir1 = proplists:get_value(lib1, Config),
+
+ rlx_test_utils:create_app(LibDir1, "goal_app_1", "0.0.1", [stdlib,kernel, non_goal_1], []),
+ rlx_test_utils:create_app(LibDir1, "non_goal_1", "0.0.1", [stdlib,kernel, non_goal_2], []),
+ rlx_test_utils:create_app(LibDir1, "non_goal_2", "0.0.1", [stdlib,kernel], []),
+
+ ConfigFile = filename:join([LibDir1, "relx.config"]),
+ rlx_test_utils:write_config(ConfigFile,
+ [{release, {foo, "0.0.1"},
+ [goal_app_1]},
+ {exclude_apps, [non_goal_1]}]),
+ OutputDir = filename:join([proplists:get_value(data_dir, Config),
+ rlx_test_utils:create_random_name("relx-output")]),
+ {ok, Cwd} = file:get_cwd(),
+ {ok, State} = relx:do(Cwd, undefined, undefined, [], [LibDir1], 3,
+ OutputDir, [],
+ ConfigFile),
+ [{{foo, "0.0.1"}, Release}] = ec_dictionary:to_list(rlx_state:realized_releases(State)),
+ AppSpecs = rlx_release:applications(Release),
+ ?assert(lists:keymember(stdlib, 1, AppSpecs)),
+ ?assert(lists:keymember(kernel, 1, AppSpecs)),
+ ?assertNot(lists:member({non_goal_1, "0.0.1"}, AppSpecs)),
+ ?assertNot(lists:member({non_goal_2, "0.0.1"}, AppSpecs)),
+ ?assert(lists:member({goal_app_1, "0.0.1"}, AppSpecs)).
+
make_auto_skip_empty_app_release(Config) ->
DataDir = proplists:get_value(data_dir, Config),
EmptyAppDir1 = filename:join([DataDir, rlx_test_utils:create_random_name("skip_app_dir_")]),