From ff1771aff5512a2cd3e315fe9c28cbc8e8745680 Mon Sep 17 00:00:00 2001 From: Evan Vigil-McClanahan Date: Fri, 24 Sep 2021 10:15:07 -0700 Subject: [PATCH] add support for optional deps in otp24 --- src/rlx_app_info.erl | 20 +++++++++++++------- src/rlx_resolve.erl | 40 +++++++++++++++++++++++++++++----------- test/rlx_test_utils.erl | 6 +++--- 3 files changed, 45 insertions(+), 21 deletions(-) diff --git a/src/rlx_app_info.erl b/src/rlx_app_info.erl index 6f2774c6c..de8fc8303 100644 --- a/src/rlx_app_info.erl +++ b/src/rlx_app_info.erl @@ -36,13 +36,14 @@ %%% -module(rlx_app_info). --export([new/5, - new/6, +-export([new/6, + new/7, name/1, vsn/1, dir/1, applications/1, included_applications/1, + optional_applications/1, link/1, link/2, format_error/1, @@ -71,17 +72,18 @@ -export_type([t/0, app_type/0]). --spec new(atom(), string(), file:name(), [atom()], [atom()]) -> t(). -new(Name, Vsn, Dir, Applications, IncludedApplications) -> - new(Name, Vsn, Dir, Applications, IncludedApplications, dep). +-spec new(atom(), string(), file:name(), [atom()], [atom()], [atom()]) -> t(). +new(Name, Vsn, Dir, Applications, IncludedApplications, OptionalApplications) -> + new(Name, Vsn, Dir, Applications, IncludedApplications, OptionalApplications, dep). --spec new(atom(), string(), file:name(), [atom()], [atom()], app_type()) -> t(). -new(Name, Vsn, Dir, Applications, IncludedApplications, AppType) -> +-spec new(atom(), string(), file:name(), [atom()], [atom()], [atom()], app_type()) -> t(). +new(Name, Vsn, Dir, Applications, IncludedApplications, OptionalApplications, AppType) -> #{name => Name, vsn => Vsn, applications => Applications, included_applications => IncludedApplications, + optional_applications => OptionalApplications, dir => Dir, link => false, @@ -108,6 +110,10 @@ applications(#{applications := Deps}) -> included_applications(#{included_applications := Deps}) -> Deps. +-spec optional_applications(t()) -> [atom()]. +optional_applications(#{included_applications := Deps}) -> + Deps. + -spec link(t()) -> boolean(). link(#{link := Link}) -> Link. diff --git a/src/rlx_resolve.erl b/src/rlx_resolve.erl index 97b1b6013..49fff4c50 100644 --- a/src/rlx_resolve.erl +++ b/src/rlx_resolve.erl @@ -56,20 +56,32 @@ subset(Apps, World, LibDirs, CheckCodeLibDirs) -> subset([], _World, _Seen, _LibDirs, _CheckCodeLibDirs, Acc) -> Acc; subset([Goal | Rest], World, Seen, LibDirs, CheckCodeLibDirs, Acc) -> - {Name, Vsn} = name_version(Goal), + {Name, Vsn, Optional} = name_version(Goal), case sets:is_element(Name, Seen) of true -> subset(Rest, World, Seen, LibDirs, CheckCodeLibDirs, Acc); _ -> - AppInfo=#{applications := Applications, - included_applications := IncludedApplications} = - find_app(Name, Vsn, World, LibDirs, CheckCodeLibDirs), - subset(Rest ++ Applications ++ IncludedApplications, + {Rest1, Acc1} = + case find_app(Name, Vsn, World, LibDirs, CheckCodeLibDirs) of + not_found when Optional == true -> + {Rest, Acc}; + not_found -> + erlang:error(?RLX_ERROR({app_not_found, Name, Vsn})); + AppInfo = #{applications := Applications, + included_applications := IncludedApplications, + optional_applications := OptionalApplications0 + } -> + OptionalApplications = [{optional, OApp} || OApp <- OptionalApplications0], + {Rest ++ (Applications -- OptionalApplications0) + ++ IncludedApplications ++ OptionalApplications, + Acc ++ [AppInfo]} + end, + subset(Rest1, World, sets:add_element(Name, Seen), LibDirs, CheckCodeLibDirs, - Acc ++ [AppInfo]) + Acc1) end. @@ -96,9 +108,13 @@ set_resolved(Release0, Pkgs, State) -> end. name_version(Name) when is_atom(Name) -> - {Name, undefined}; + {Name, undefined, false}; name_version({Name, #{vsn := Vsn}}) -> - {Name, Vsn}. + {Name, Vsn, false}; +name_version({optional, Name}) when is_atom(Name) -> + {Name, undefined, true}; +name_version({optional, {Name, #{vsn := Vsn}}}) -> + {Name, Vsn, true}. remove_exclude_apps(AllApps, State) -> ExcludeApps = rlx_state:exclude_apps(State), @@ -144,7 +160,7 @@ search_for_app(Name, Vsn, LibDirs, CheckCodeLibDirs) -> %% app not found in any lib dir we are configured to search %% and user set a custom `system_libs' directory so we do %% not look in `code:lib_dir' - erlang:error(?RLX_ERROR({app_not_found, Name, Vsn})); + not_found; AppInfo -> case check_app(Name, Vsn, AppInfo) of true -> @@ -175,13 +191,13 @@ find_app_in_dir(Name, Vsn, [Dir | Rest]) -> find_app_in_code_path(Name, Vsn) -> case code:lib_dir(Name) of {error, bad_name} -> - erlang:error(?RLX_ERROR({app_not_found, Name, Vsn})); + not_found; Dir -> case to_app(Name, Vsn, filename:join([Dir, "ebin", [Name, ".app"]])) of {true, AppInfo} -> AppInfo; false -> - erlang:error(?RLX_ERROR({app_not_found, Name, Vsn})) + not_found end end. @@ -200,6 +216,7 @@ to_app(Name, Vsn, AppFilePath) -> end, Applications = proplists:get_value(applications, AppData, []), IncludedApplications = proplists:get_value(included_applications, AppData, []), + OptionalApplications = proplists:get_value(optional_applications, AppData, []), case lists:keyfind(vsn, 1, AppData) of {_, Vsn1} when Vsn =:= undefined ; @@ -209,6 +226,7 @@ to_app(Name, Vsn, AppFilePath) -> applications => Applications, included_applications => IncludedApplications, + optional_applications => OptionalApplications, dir => filename:dirname(filename:dirname(AppFilePath)), link => false}}; diff --git a/test/rlx_test_utils.erl b/test/rlx_test_utils.erl index a144948ff..6aec50065 100644 --- a/test/rlx_test_utils.erl +++ b/test/rlx_test_utils.erl @@ -10,20 +10,20 @@ create_app(Dir, Name, Vsn, Deps, LibDeps) -> write_src_file(AppDir, Name), write_priv_file(AppDir), compile_src_files(AppDir), - rlx_app_info:new(erlang:list_to_atom(Name), Vsn, AppDir, Deps, []). + rlx_app_info:new(erlang:list_to_atom(Name), Vsn, AppDir, Deps, [], []). create_full_app(Dir, Name, Vsn, Deps, LibDeps) -> AppDir = filename:join([Dir, Name ++ "-" ++ Vsn]), write_full_app_files(AppDir, Name, Vsn, Deps, LibDeps), compile_src_files(AppDir), rlx_app_info:new(erlang:list_to_atom(Name), Vsn, AppDir, - Deps, []). + Deps, [], []). create_empty_app(Dir, Name, Vsn, Deps, LibDeps) -> AppDir = filename:join([Dir, Name ++ "-" ++ Vsn]), write_app_file(AppDir, Name, Vsn, [], Deps, LibDeps), rlx_app_info:new(erlang:list_to_atom(Name), Vsn, AppDir, - Deps, []). + Deps, [], []). app_modules(Name) -> [list_to_atom(M ++ Name) ||