From 81369d99a9b6ee5caae6b5e6a5faffb8a65fb588 Mon Sep 17 00:00:00 2001 From: Luis Rascao Date: Sun, 20 Nov 2016 22:19:08 +0000 Subject: Provide a new config directive that allows per-app module exclusion By introducing a new entry in the config file allow excluding specific modules from a given app, they will not be copied onto the final release and their reference removed from the .app file. The new entry takes on the following form: {exclude_modules, [ {App :: atom(), [Module :: atom()]} ]} --- src/rlx_config.erl | 2 + src/rlx_prv_assembler.erl | 102 +++++++++++++++++++++++++++++++--------------- src/rlx_state.erl | 14 ++++++- 3 files changed, 85 insertions(+), 33 deletions(-) (limited to 'src') diff --git a/src/rlx_config.erl b/src/rlx_config.erl index 1dbfa13..dfcb511 100644 --- a/src/rlx_config.erl +++ b/src/rlx_config.erl @@ -173,6 +173,8 @@ 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({exclude_modules, ExcludeModules0}, {ok, State0}) -> + {ok, rlx_state:exclude_modules(State0, ExcludeModules0)}; 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 7ff1d61..3829c82 100644 --- a/src/rlx_prv_assembler.erl +++ b/src/rlx_prv_assembler.erl @@ -162,7 +162,7 @@ copy_app_directories_to_output(State, Release, OutputDir) -> false end, lists:flatten(ec_plists:map(fun(App) -> - copy_app(LibDir, App, IncludeSrc, IncludeErts) + copy_app(State, LibDir, App, IncludeSrc, IncludeErts) end, Apps))), case Result of [E | _] -> @@ -179,7 +179,7 @@ prepare_applications(State, Apps) -> Apps end. -copy_app(LibDir, App, IncludeSrc, IncludeErts) -> +copy_app(State, LibDir, App, IncludeSrc, IncludeErts) -> AppName = erlang:atom_to_list(rlx_app_info:name(App)), AppVsn = rlx_app_info:original_vsn(App), AppDir = rlx_app_info:dir(App), @@ -196,52 +196,67 @@ copy_app(LibDir, App, IncludeSrc, IncludeErts) -> true -> []; false -> - copy_app_(App, AppDir, TargetDir, IncludeSrc) + copy_app_(State, App, AppDir, TargetDir, IncludeSrc) end; _ -> - copy_app_(App, AppDir, TargetDir, IncludeSrc) + copy_app_(State, App, AppDir, TargetDir, IncludeSrc) end end. is_erts_lib(Dir) -> lists:prefix(filename:split(list_to_binary(code:lib_dir())), filename:split(Dir)). -copy_app_(App, AppDir, TargetDir, IncludeSrc) -> +copy_app_(State, App, AppDir, TargetDir, IncludeSrc) -> remove_symlink_or_directory(TargetDir), case rlx_app_info:link(App) of true -> link_directory(AppDir, TargetDir), - rewrite_app_file(App, AppDir); + rewrite_app_file(State, App, AppDir); false -> - copy_directory(AppDir, TargetDir, IncludeSrc), - rewrite_app_file(App, TargetDir) + copy_directory(State, App, AppDir, TargetDir, IncludeSrc), + rewrite_app_file(State, App, TargetDir) end. %% If excluded apps exist in this App's applications list we must write a new .app -rewrite_app_file(App, TargetDir) -> +rewrite_app_file(State, 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. + {ok, [{application, AppName, AppData0}]} = file:consult(AppFile), + OldActiveDeps = proplists:get_value(applications, AppData0, []), + OldIncludedDeps = proplists:get_value(included_applications, AppData0, []), + OldModules = proplists:get_value(modules, AppData0, []), + ExcludedModules = proplists:get_value(Name, + rlx_state:exclude_modules(State), []), + + %% maybe replace excluded apps + AppData2 = + case {OldActiveDeps, OldIncludedDeps} of + {ActiveDeps, IncludedDeps} -> + AppData0; + _ -> + AppData1 = lists:keyreplace(applications + ,1 + ,AppData0 + ,{applications, ActiveDeps}), + lists:keyreplace(included_applications + ,1 + ,AppData1 + ,{included_applications, IncludedDeps}) + end, + %% maybe replace excluded modules + AppData3 = + case ExcludedModules of + [] -> AppData2; + _ -> + lists:keyreplace(modules + ,1 + ,AppData2 + ,{modules, OldModules -- ExcludedModules}) + end, + Spec = io_lib:format("~p.\n", [{application, AppName, AppData3}]), + write_file_if_contents_differ(AppFile, Spec). write_file_if_contents_differ(Filename, Bytes) -> ToWrite = iolist_to_binary(Bytes), @@ -275,8 +290,8 @@ link_directory(AppDir, TargetDir) -> ok end. -copy_directory(AppDir, TargetDir, IncludeSrc) -> - [copy_dir(AppDir, TargetDir, SubDir) +copy_directory(State, App, AppDir, TargetDir, IncludeSrc) -> + [copy_dir(State, App, AppDir, TargetDir, SubDir) || SubDir <- ["ebin", "include", "priv", @@ -289,13 +304,20 @@ copy_directory(AppDir, TargetDir, IncludeSrc) -> [] end]]. -copy_dir(AppDir, TargetDir, SubDir) -> +copy_dir(State, App, AppDir, TargetDir, SubDir) -> SubSource = filename:join(AppDir, SubDir), SubTarget = filename:join(TargetDir, SubDir), case ec_file:is_dir(SubSource) of true -> ok = rlx_util:mkdir_p(SubTarget), - case ec_file:copy(SubSource, SubTarget, [recursive]) of + %% get a list of the modules to be excluded from this app + AppName = rlx_app_info:name(App), + ExcludedModules = proplists:get_value(AppName, rlx_state:exclude_modules(State), + []), + ExcludedFiles = [filename:join([binary_to_list(SubSource), + atom_to_list(M) ++ ".beam"]) || + M <- ExcludedModules], + case copy_dir(SubSource, SubTarget, ExcludedFiles) of {error, E} -> ?RLX_ERROR({ec_file_error, AppDir, SubTarget, E}); ok -> @@ -305,6 +327,22 @@ copy_dir(AppDir, TargetDir, SubDir) -> ok end. +%% no files are excluded, just copy the whole dir +copy_dir(SourceDir, TargetDir, []) -> + case ec_file:copy(SourceDir, TargetDir, [recursive]) of + {error, E} -> {error, E}; + ok -> + ok + end; +copy_dir(SourceDir, TargetDir, ExcludeFiles) -> + SourceFiles = filelib:wildcard( + filename:join([binary_to_list(SourceDir), "*"])), + lists:foreach(fun(F) -> + ok = ec_file:copy(F, + filename:join([TargetDir, + filename:basename(F)])) + end, SourceFiles -- ExcludeFiles). + create_release_info(State0, Release0, OutputDir) -> RelName = atom_to_list(rlx_release:name(Release0)), ReleaseDir = rlx_util:release_output_dir(State0, Release0), diff --git a/src/rlx_state.erl b/src/rlx_state.erl index 6974d52..75a5cba 100644 --- a/src/rlx_state.erl +++ b/src/rlx_state.erl @@ -82,7 +82,9 @@ upfrom/1, upfrom/2, format/1, - format/2]). + format/2, + exclude_modules/1, + exclude_modules/2]). -export_type([t/0, @@ -107,6 +109,7 @@ overrides=[] :: [{AppName::atom(), Directory::file:filename()}], skip_apps=[] :: [AppName::atom()], exclude_apps=[] :: [AppName::atom()], + exclude_modules=[] :: [{App::atom(), [Module::atom()]}], debug_info=keep :: keep | strip, configured_releases :: releases(), realized_releases :: releases(), @@ -200,6 +203,15 @@ exclude_apps(#state_t{exclude_apps=Apps}) -> exclude_apps(State, SkipApps) -> State#state_t{exclude_apps=SkipApps}. +-spec exclude_modules(t()) -> [{App::atom(), [Module::atom()]}]. +exclude_modules(#state_t{exclude_modules=Modules}) -> + Modules. + +%% @doc modules to be excluded from the release +-spec exclude_modules(t(), [{App::atom(), [Module::atom()]}]) -> t(). +exclude_modules(State, SkipModules) -> + State#state_t{exclude_modules=SkipModules}. + -spec debug_info(t()) -> keep | strip. debug_info(#state_t{debug_info=DebugInfo}) -> DebugInfo. -- cgit v1.2.3