diff options
Diffstat (limited to 'lib/reltool')
-rw-r--r-- | lib/reltool/doc/src/notes.xml | 28 | ||||
-rw-r--r-- | lib/reltool/src/reltool_server.erl | 189 | ||||
-rw-r--r-- | lib/reltool/src/reltool_sys_win.erl | 159 | ||||
-rw-r--r-- | lib/reltool/test/Makefile | 4 | ||||
-rw-r--r-- | lib/reltool/test/reltool_server_SUITE.erl | 125 | ||||
-rw-r--r-- | lib/reltool/test/reltool_server_SUITE_data/Makefile.src | 19 | ||||
-rw-r--r-- | lib/reltool/test/reltool_server_SUITE_data/otp_9229/x-1.0/ebin/x.app | 7 | ||||
-rw-r--r-- | lib/reltool/test/reltool_server_SUITE_data/otp_9229/x-1.0/src/mylib.erl | 4 | ||||
-rw-r--r-- | lib/reltool/test/reltool_server_SUITE_data/otp_9229/x-1.0/src/x.erl | 4 | ||||
-rw-r--r-- | lib/reltool/test/reltool_server_SUITE_data/otp_9229/y-1.0/ebin/y.app | 7 | ||||
-rw-r--r-- | lib/reltool/test/reltool_server_SUITE_data/otp_9229/y-1.0/src/mylib.erl | 4 | ||||
-rw-r--r-- | lib/reltool/test/reltool_server_SUITE_data/otp_9229/y-1.0/src/y.erl | 4 | ||||
-rw-r--r-- | lib/reltool/vsn.mk | 2 |
13 files changed, 452 insertions, 104 deletions
diff --git a/lib/reltool/doc/src/notes.xml b/lib/reltool/doc/src/notes.xml index a791f2ce03..324d69675e 100644 --- a/lib/reltool/doc/src/notes.xml +++ b/lib/reltool/doc/src/notes.xml @@ -37,7 +37,33 @@ thus constitutes one section in this document. The title of each section is the version number of Reltool.</p> - <section><title>Reltool 0.5.5</title> + <section><title>Reltool 0.5.6</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + The system level option <c>app_files</c> is documented to + allow the values <c>keep | strip | all</c>, but it only + allowed <c>keep</c>. This is corrected.</p> + <p> + Own Id: OTP-9135</p> + </item> + <item> + <p> + Allow the same module name in multiple applications + visible to reltool, as long as all but one of the + applications/modules are explicitely excluded. (Thanks to + Andrew Gopienko and Jay Nelson)</p> + <p> + Own Id: OTP-9229</p> + </item> + </list> + </section> + +</section> + +<section><title>Reltool 0.5.5</title> <section><title>Fixed Bugs and Malfunctions</title> <list> diff --git a/lib/reltool/src/reltool_server.erl b/lib/reltool/src/reltool_server.erl index 9743289ca6..692baea0a4 100644 --- a/lib/reltool/src/reltool_server.erl +++ b/lib/reltool/src/reltool_server.erl @@ -465,16 +465,16 @@ analyse(#state{common = C, [MissingApp2 | Apps2] end, app_propagate_is_used_by(C, Apps3), - Apps4 = read_apps(C, Sys, Apps3, []), + {Apps4,Status4} = app_recap_dependencies(C, Sys, Apps3, [], Status3), %% io:format("Missing app: ~p\n", %% [lists:keysearch(?MISSING_APP_NAME, #app.name, Apps4)]), Sys2 = Sys#sys{apps = Apps4}, - case verify_config(RelApps2, Sys2, Status3) of - {ok, _Warnings} = Status4 -> - {S#state{sys = Sys2}, Status4}; - {error, _} = Status4 -> - {S, Status4} + case verify_config(RelApps2, Sys2, Status4) of + {ok, _Warnings} = Status5 -> + {S#state{sys = Sys2}, Status5}; + {error, _} = Status5 -> + {S, Status5} end. apps_in_rels(Rels, Apps, Status) -> @@ -548,21 +548,24 @@ app_init_is_included(C, {derived, [_ | _]} -> % App is included in at least one rel {true, undefined, true, Status} end, - A2 = A#app{is_pre_included = IsPreIncl, + {Mods2,Status3} = lists:mapfoldl(fun(Mod,Acc) -> + mod_init_is_included(C, + Mod, + ModCond, + AppCond, + Default, + Acc) + end, + Status2, + Mods), + A2 = A#app{mods = Mods2, + is_pre_included = IsPreIncl, is_included = IsIncl, rels = Rels}, ets:insert(C#common.app_tab, A2), - lists:foreach(fun(Mod) -> - mod_init_is_included(C, - Mod, - ModCond, - AppCond, - Default) - end, - Mods), - {A2, Status2}. - -mod_init_is_included(C, M, ModCond, AppCond, Default) -> + {A2, Status3}. + +mod_init_is_included(C, M, ModCond, AppCond, Default, Status) -> %% print(M#mod.name, hipe, "incl_cond -> ~p\n", [AppCond]), IsIncl = case AppCond of @@ -595,9 +598,52 @@ mod_init_is_included(C, M, ModCond, AppCond, Default) -> Default end end, + M2 = M#mod{is_pre_included = IsIncl, is_included = IsIncl}, + + Status2 = + case ets:lookup(C#common.mod_tab,M#mod.name) of + [Existing] -> + case {Existing#mod.is_included,IsIncl} of + {false,_} -> + Warning = + lists:concat( + ["Module ",M#mod.name, + " exists in applications ", Existing#mod.app_name, + " and ", M#mod.app_name, + ". Using module from application ", + M#mod.app_name, "."]), + ets:insert(C#common.mod_tab, M2), + reltool_utils:add_warning(Status,Warning); + {_,false} -> + Warning = + lists:concat( + ["Module ",M#mod.name, + " exists in applications ", Existing#mod.app_name, + " and ", M#mod.app_name, + ". Using module from application ", + Existing#mod.app_name, "."]), + + %% Don't insert in mod_tab - using Existing + reltool_utils:add_warning(Status,Warning); + {_,_} -> + Error = + lists:concat( + ["Module ",M#mod.name, + " potentially included by ", + "two different applications: ", + Existing#mod.app_name, " and ", + M#mod.app_name, "."]), + %% Don't insert in mod_tab - using Existing + reltool_utils:return_first_error(Status,Error) + end; + [] -> + ets:insert(C#common.mod_tab, M2), + Status + end, + %% print(M#mod.name, hipe, "~p -> ~p\n", [M2, IsIncl]), - ets:insert(C#common.mod_tab, M2). + {M2,Status2}. false_to_undefined(Bool) -> case Bool of @@ -612,21 +658,27 @@ app_propagate_is_included(_C, _Sys, [], Acc) -> Acc. mod_propagate_is_included(C, Sys, A, [#mod{name = ModName} | Mods], Acc) -> - [M2] = ets:lookup(C#common.mod_tab, ModName), - %% print(ModName, file, "Maybe Prop ~p -> ~p\n", - %% [M2, M2#mod.is_included]), - %% print(ModName, filename, "Maybe Prop ~p -> ~p\n", - %% [M2, M2#mod.is_included]), Acc2 = - case M2#mod.is_included of - true -> - %% Propagate include mark - mod_mark_is_included(C, Sys, ModName, M2#mod.uses_mods, Acc); - false -> - Acc; - undefined -> - Acc - end, + case ets:lookup(C#common.mod_tab, ModName) of + [M2] when M2#mod.app_name=:=A#app.name -> + %% print(ModName, file, "Maybe Prop ~p -> ~p\n", + %% [M2, M2#mod.is_included]), + %% print(ModName, filename, "Maybe Prop ~p -> ~p\n", + %% [M2, M2#mod.is_included]), + case M2#mod.is_included of + true -> + %% Propagate include mark + mod_mark_is_included(C,Sys,ModName,M2#mod.uses_mods,Acc); + false -> + Acc; + undefined -> + Acc + end; + [_] -> + %% This module is currently used from a different application + %% Ignore + Acc + end, mod_propagate_is_included(C, Sys, A, Mods, Acc2); mod_propagate_is_included(_C, _Sys, _A, [], Acc) -> Acc. @@ -740,9 +792,10 @@ mod_propagate_is_used_by(C, [#mod{name = ModName} | Mods]) -> mod_propagate_is_used_by(_C, []) -> ok. -read_apps(C, Sys, [#app{mods = Mods, is_included = IsIncl} = A | Apps], Acc) -> - {Mods2, IsIncl2} = read_apps(C, Sys, A, Mods, [], IsIncl), - Status = +app_recap_dependencies(C, Sys, [#app{mods = Mods, is_included = IsIncl} = A | Apps], Acc, Status) -> + {Mods2, IsIncl2, Status2} = + mod_recap_dependencies(C, Sys, A, Mods, [], IsIncl, Status), + AppStatus = case lists:keymember(missing, #mod.status, Mods2) of true -> missing; false -> ok @@ -759,34 +812,52 @@ read_apps(C, Sys, [#app{mods = Mods, is_included = IsIncl} = A | Apps], Acc) -> UsedByApps2 = lists:usort(UsedByApps), A2 = A#app{mods = Mods2, - status = Status, + status = AppStatus, uses_mods = UsesMods2, used_by_mods = UsedByMods2, uses_apps = UsesApps2, used_by_apps = UsedByApps2, is_included = IsIncl2}, - read_apps(C, Sys, Apps, [A2 | Acc]); -read_apps(_C, _Sys, [], Acc) -> - lists:reverse(Acc). - -read_apps(C, Sys, A, [#mod{name = ModName} | Mods], Acc, IsIncl) -> - [M2] = ets:lookup(C#common.mod_tab, ModName), - Status = do_get_status(M2), - %% print(M2#mod.name, hipe, "status -> ~p\n", [Status]), - {IsIncl2, M3} = - case M2#mod.is_included of - true -> - UsedByMods = - [N || {_, N} <- ets:lookup(C#common.mod_used_by_tab, - ModName)], - {true, M2#mod{status = Status, used_by_mods = UsedByMods}}; - _ -> - {IsIncl, M2#mod{status = Status, used_by_mods = []}} - end, - ets:insert(C#common.mod_tab, M3), - read_apps(C, Sys, A, Mods, [M3 | Acc], IsIncl2); -read_apps(_C, _Sys, _A, [], Acc, IsIncl) -> - {lists:reverse(Acc), IsIncl}. + ets:insert(C#common.app_tab,A2), + app_recap_dependencies(C, Sys, Apps, [A2 | Acc], Status2); +app_recap_dependencies(_C, _Sys, [], Acc, Status) -> + {lists:reverse(Acc), Status}. + +mod_recap_dependencies(C, Sys, A, [#mod{name = ModName}=M1 | Mods], Acc, IsIncl, Status) -> + case ets:lookup(C#common.mod_tab, ModName) of + [M2] when M2#mod.app_name=:=A#app.name -> + ModStatus = do_get_status(M2), + %% print(M2#mod.name, hipe, "status -> ~p\n", [ModStatus]), + {IsIncl2, M3} = + case M2#mod.is_included of + true -> + UsedByMods = + [N || {_, N} <- ets:lookup(C#common.mod_used_by_tab, + ModName)], + {true, M2#mod{status = ModStatus, used_by_mods = UsedByMods}}; + _ -> + {IsIncl, M2#mod{status = ModStatus, used_by_mods = []}} + end, + ets:insert(C#common.mod_tab, M3), + mod_recap_dependencies(C, Sys, A, Mods, [M3 | Acc], IsIncl2, Status); + [_] when A#app.is_included==false; M1#mod.incl_cond==exclude -> + %% App is explicitely excluded so it is ok that the module + %% record does not exist for this module in this + %% application. + mod_recap_dependencies(C, Sys, A, Mods, [M1 | Acc], IsIncl, Status); + [M2] -> + %% A module is potensially included by multiple + %% applications. This is not allowed! + Error = + lists:concat( + ["Module ",ModName, + " potentially included by two different applications: ", + A#app.name, " and ", M2#mod.app_name, "."]), + Status2 = reltool_utils:return_first_error(Status,Error), + mod_recap_dependencies(C, Sys, A, Mods, [M1 | Acc], IsIncl, Status2) + end; +mod_recap_dependencies(_C, _Sys, _A, [], Acc, IsIncl, Status) -> + {lists:reverse(Acc), IsIncl, Status}. do_get_status(M) -> if diff --git a/lib/reltool/src/reltool_sys_win.erl b/lib/reltool/src/reltool_sys_win.erl index dbb8e32aa2..8b0f64eb45 100644 --- a/lib/reltool/src/reltool_sys_win.erl +++ b/lib/reltool/src/reltool_sys_win.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2009-2010. All Rights Reserved. +%% Copyright Ericsson AB 2009-2011. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -54,7 +54,9 @@ whitelist, blacklist, derived, - fgraph_wins + fgraph_wins, + app_box, + mod_box }). -define(WIN_WIDTH, 800). @@ -86,6 +88,11 @@ -define(blacklist, "Excluded"). -define(derived, "Derived"). +-define(safe_config,{sys,[{incl_cond,exclude}, + {app,kernel,[{incl_cond,include}]}, + {app,stdlib,[{incl_cond,include}]}, + {app,sasl,[{incl_cond,include}]}]}). + -record(root_data, {dir}). -record(lib_data, {dir, tree, item}). -record(escript_data, {file, tree, item}). @@ -102,7 +109,7 @@ start_link(Opts) -> proc_lib:start_link(?MODULE, init, - [[{parent, self()} | Opts]], + [[{safe_config, false}, {parent, self()} | Opts]], infinity, []). @@ -126,53 +133,73 @@ init(Options) -> exit({Reason, erlang:get_stacktrace()}) end. -do_init([{parent, Parent} | Options]) -> +do_init([{safe_config, Safe}, {parent, Parent} | Options]) -> case reltool_server:start_link(Options) of {ok, ServerPid, C, Sys} -> process_flag(trap_exit, C#common.trap_exit), - S = #state{parent_pid = Parent, - server_pid = ServerPid, - common = C, - config_file = filename:absname("config.reltool"), - target_dir = filename:absname("reltool_target_dir"), - app_wins = [], - sys = Sys, - fgraph_wins = []}, wx:new(), wx:debug(C#common.wx_debug), - S2 = create_window(S), %% wx_misc:beginBusyCursor(), case reltool_server:get_status(ServerPid) of {ok, Warnings} -> exit_dialog(Warnings), - {ok, Sys2} = reltool_server:get_sys(ServerPid), - S3 = S2#state{sys = Sys2}, + {ok, Sys} = reltool_server:get_sys(ServerPid), + S = #state{parent_pid = Parent, + server_pid = ServerPid, + common = C, + config_file = filename:absname("config.reltool"), + target_dir = filename:absname("reltool_target_dir"), + app_wins = [], + sys = Sys, + fgraph_wins = []}, + S2 = create_window(S), S5 = wx:batch(fun() -> Title = atom_to_list(?APPLICATION), - wxFrame:setTitle(S3#state.frame, + wxFrame:setTitle(S2#state.frame, Title), %% wxFrame:setMinSize(Frame, %% {?WIN_WIDTH, ?WIN_HEIGHT}), wxStatusBar:setStatusText( - S3#state.status_bar, + S2#state.status_bar, "Done."), - S4 = redraw_apps(S3), - redraw_libs(S4) + S3 = redraw_apps(S2), + S4 = redraw_libs(S3), + redraw_config_page(S4) end), %% wx_misc:endBusyCursor(), %% wxFrame:destroy(Frame), proc_lib:init_ack(S#state.parent_pid, {ok, self()}), loop(S5); {error, Reason} -> - io:format("~p(~p): <ERROR> ~p\n", [?MODULE, ?LINE, Reason]), - exit(Reason) + restart_server_safe_config(Safe,Parent,Reason) end; {error, Reason} -> io:format("~p(~p): <ERROR> ~p\n", [?MODULE, ?LINE, Reason]), exit(Reason) end. +restart_server_safe_config(true,_Parent,Reason) -> + io:format("~p(~p): <ERROR> ~p\n", [?MODULE, ?LINE, Reason]), + exit(Reason); +restart_server_safe_config(false,Parent,Reason) -> + Strings = + [{?wxBLACK,"Could not start reltool server:\n\n"}, + {?wxRED,Reason++"\n\n"}, + {?wxBLACK, + io_lib:format( + "Resetting the configuration to:~n~n ~p~n~n" + "Do you want to continue with this configuration?", + [?safe_config])}], + + case question_dialog_2("Reltool server start error", Strings) of + ?wxID_OK -> + do_init([{safe_config,true},{parent,Parent},?safe_config]); + ?wxID_CANCEL -> + io:format("~p(~p): <ERROR> ~p\n", [?MODULE, ?LINE, Reason]), + exit(Reason) + end. + exit_dialog([]) -> ok; exit_dialog(Warnings) -> @@ -606,6 +633,13 @@ create_config_page(#state{sys = Sys, book = Book} = S) -> {proportion, 1}]), wxPanel:setSizer(Panel, Sizer), wxNotebook:addPage(Book, Panel, ?SYS_PAGE, []), + S#state{app_box = AppBox, mod_box = ModBox}. + +redraw_config_page(#state{sys = Sys, app_box = AppBox, mod_box = ModBox} = S) -> + AppChoice = reltool_utils:incl_cond_to_index(Sys#sys.incl_cond), + wxRadioBox:setSelection(AppBox, AppChoice), + ModChoice = reltool_utils:mod_cond_to_index(Sys#sys.mod_cond), + wxRadioBox:setSelection(ModBox, ModChoice), S. create_main_release_page(#state{book = Book} = S) -> @@ -640,15 +674,15 @@ create_main_release_page(#state{book = Book} = S) -> add_release_page(Book, #rel{name = RelName, rel_apps = RelApps}) -> Panel = wxPanel:new(Book, []), Sizer = wxBoxSizer:new(?wxHORIZONTAL), - RelBox = wxRadioBox:new(Panel, - ?wxID_ANY, - "Applications included in the release " ++ RelName, - ?wxDefaultPosition, - ?wxDefaultSize, - [atom_to_list(RA#rel_app.name) || RA <- RelApps], - []), - %% wxRadioBox:setSelection(RelBox, 2), % mandatory - wxEvtHandler:connect(RelBox, command_radiobox_selected, + AppNames = [kernel, stdlib | + [RA#rel_app.name || RA <- RelApps] -- [kernel, stdlib]], + RelBox = wxListBox:new( + Panel,?wxID_ANY, + [{pos,?wxDefaultPosition}, + {size,?wxDefaultSize}, + {choices,[[atom_to_list(AppName)] || AppName <- AppNames]}, + {style,?wxLB_EXTENDED}]), + wxEvtHandler:connect(RelBox, command_listbox_selected, [{userData, {config_rel_cond, RelName}}]), RelToolTip = "Choose which applications that shall " "be included in the release resource file.", @@ -1092,17 +1126,23 @@ move_app(S, {_ItemNo, AppBase}, Action) -> OldApp#app{incl_cond = AppCond}. do_set_app(#state{server_pid = ServerPid, app_wins = AppWins} = S, NewApp) -> - {ok, AnalysedApp, Warnings} = reltool_server:set_app(ServerPid, NewApp), + Result = reltool_server:set_app(ServerPid, NewApp), [ok = reltool_app_win:refresh(AW#app_win.pid) || AW <- AppWins], S2 = redraw_apps(S), - case Warnings of - [] -> - ignore; - _ -> - Msg = lists:flatten([[W, $\n] || W <- Warnings]), - display_message(Msg, ?wxICON_WARNING) - end, - {ok, AnalysedApp, S2}. + ReturnApp = + case Result of + {ok, AnalysedApp, []} -> + AnalysedApp; + {ok, AnalysedApp, Warnings} -> + Msg = lists:flatten([[W, $\n] || W <- Warnings]), + display_message(Msg, ?wxICON_WARNING), + AnalysedApp; + {error, Reason} -> + display_message(Reason, ?wxICON_ERROR), + {ok,OldApp} = reltool_server:get_app(ServerPid, NewApp#app.name), + OldApp + end, + {ok, ReturnApp, S2}. redraw_apps(#state{server_pid = ServerPid, source = SourceCtrl, @@ -1357,7 +1397,8 @@ refresh(S) -> [ok = reltool_app_win:refresh(AW#app_win.pid) || AW <- S#state.app_wins], S2 = S#state{sys = Sys}, S3 = redraw_libs(S2), - redraw_apps(S3). + S4 = redraw_apps(S3), + redraw_config_page(S4). question_dialog(Question, Details) -> %% Parent = S#state.frame, @@ -1414,6 +1455,44 @@ display_message(Message, Icon) -> wxMessageDialog:showModal(Dialog), wxMessageDialog:destroy(Dialog). +%% Strings = [{Color,String}] +question_dialog_2(DialogLabel, Strings) -> + %% Parent = S#state.frame, + Parent = wx:typeCast(wx:null(), wxWindow), + %% [{style, ?wxYES_NO bor ?wxICON_ERROR bor ?wx}]), + DialogStyle = ?wxRESIZE_BORDER bor ?wxCAPTION bor ?wxSYSTEM_MENU bor + ?wxMINIMIZE_BOX bor ?wxMAXIMIZE_BOX bor ?wxCLOSE_BOX, + Dialog = wxDialog:new(Parent, ?wxID_ANY, DialogLabel, + [{style, DialogStyle}]), + Color = wxWindow:getBackgroundColour(Dialog), + TextStyle = ?wxTE_READONLY bor ?wxTE_MULTILINE bor ?wxHSCROLL, + Text = wxTextCtrl:new(Dialog, ?wxID_ANY, + [{size, {600, 400}}, {style, TextStyle}]), + wxWindow:setBackgroundColour(Text, Color), + TextAttr = wxTextAttr:new(), + add_text(Text,TextAttr,Strings), + Sizer = wxBoxSizer:new(?wxVERTICAL), + wxSizer:add(Sizer, Text, [{border, 2}, {flag, ?wxEXPAND}, {proportion, 1}]), + ButtSizer = wxDialog:createStdDialogButtonSizer(Dialog, ?wxOK bor ?wxCANCEL), + wxSizer:add(Sizer, ButtSizer, [{border, 2}, {flag, ?wxEXPAND}]), + wxPanel:setSizer(Dialog, Sizer), + wxSizer:fit(Sizer, Dialog), + wxSizer:setSizeHints(Sizer, Dialog), + Answer = wxDialog:showModal(Dialog), + wxDialog:destroy(Dialog), + Answer. + +add_text(Text,Attr,[{Color,String}|Strings]) -> + wxTextAttr:setTextColour(Attr, Color), + wxTextCtrl:setDefaultStyle(Text, Attr), + wxTextCtrl:appendText(Text, String), + add_text(Text,Attr,Strings); +add_text(_,_,[]) -> + ok. + + + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% sys callbacks diff --git a/lib/reltool/test/Makefile b/lib/reltool/test/Makefile index 62fe05238b..767454b66a 100644 --- a/lib/reltool/test/Makefile +++ b/lib/reltool/test/Makefile @@ -76,8 +76,8 @@ release_tests_spec: opt $(INSTALL_DATA) reltool.spec reltool.cover $(ERL_FILES) $(HRL_FILES) $(RELSYSDIR) $(INSTALL_SCRIPT) rtt $(INSTALL_PROGS) $(RELSYSDIR) $(INSTALL_DATA) $(INSTALL_PROGS) $(RELSYSDIR) -# chmod -R u+w $(RELSYSDIR) -# @tar cf - *_SUITE_data | (cd $(RELSYSDIR); tar xf -) + chmod -R u+w $(RELSYSDIR) + @tar cf - *_SUITE_data | (cd $(RELSYSDIR); tar xf -) release_docs_spec: diff --git a/lib/reltool/test/reltool_server_SUITE.erl b/lib/reltool/test/reltool_server_SUITE.erl index b77560db94..9ed79e8c95 100644 --- a/lib/reltool/test/reltool_server_SUITE.erl +++ b/lib/reltool/test/reltool_server_SUITE.erl @@ -25,6 +25,7 @@ -compile(export_all). -include("reltool_test_lib.hrl"). +-include_lib("common_test/include/ct.hrl"). -define(NODE_NAME, '__RELTOOL__TEMPORARY_TEST__NODE__'). -define(WORK_DIR, "reltool_work_dir"). @@ -53,7 +54,7 @@ all() -> [start_server, set_config, create_release, create_script, create_target, create_embedded, create_standalone, create_old_target, - otp_9135]. + otp_9135, otp_9229_exclude_app, otp_9229_exclude_mod]. groups() -> []. @@ -361,6 +362,114 @@ create_old_target(_Config) -> ok. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% OTP-9229 - handle duplicated module names, i.e. same module name +%% exists in two applications. + +%% Include on app, exclude the other +otp_9229_exclude_app(Config) -> + DataDir = ?config(data_dir,Config), + LibDir = filename:join(DataDir,"otp_9229"), + + %% Configure the server + ExclApp = + {sys, + [ + {root_dir, code:root_dir()}, + {lib_dirs, [LibDir]}, + {incl_cond,exclude}, + {app,x,[{incl_cond,include}]}, + {app,y,[{incl_cond,exclude}]}, + {app,kernel,[{incl_cond,include}]}, + {app,stdlib,[{incl_cond,include}]}, + {app,sasl,[{incl_cond,include}]} + ]}, + + %% Generate target file + TargetDir = filename:join([?WORK_DIR, "target_dupl_mod_excl_app"]), + ?m(ok, reltool_utils:recursive_delete(TargetDir)), + ?m(ok, file:make_dir(TargetDir)), + ?log("SPEC: ~p\n", [reltool:get_target_spec([{config, ExclApp}])]), + {ok,["Module mylib exists in applications x and y. Using module from application x."]} = reltool:get_status([{config, ExclApp}]), + ?m(ok, reltool:create_target([{config, ExclApp}], TargetDir)), + + Erl = filename:join([TargetDir, "bin", "erl"]), + {ok, Node} = ?msym({ok, _}, start_node(?NODE_NAME, Erl)), + + AbsTargetDir = filename:absname(TargetDir), + XArchive = "x-1.0.ez", + AbsXArchive = filename:join([AbsTargetDir,lib,XArchive]), + XEbin = ["ebin","x-1.0",XArchive], + YArchive = "y-1.0.ez", + AbsYArchive = filename:join([AbsTargetDir,lib,YArchive]), + + ?m(true, filelib:is_file(AbsXArchive)), + ?m(XEbin, mod_path(Node,x)), + ?m(XEbin, mod_path(Node,mylib)), + ?m(false, filelib:is_file(AbsYArchive)), + ?m(non_existing, mod_path(Node,y)), + + ?msym(ok, stop_node(Node)), + + ok. + +%% Include both apps, but exclude common module from one app +otp_9229_exclude_mod(Config) -> + DataDir = ?config(data_dir,Config), + LibDir = filename:join(DataDir,"otp_9229"), + + %% Configure the server + ExclMod = + {sys, + [ + {root_dir, code:root_dir()}, + {lib_dirs, [LibDir]}, + {incl_cond,exclude}, + {app,x,[{incl_cond,include}]}, + {app,y,[{incl_cond,include},{mod, mylib,[{incl_cond,exclude}]}]}, + {app,kernel,[{incl_cond,include}]}, + {app,stdlib,[{incl_cond,include}]}, + {app,sasl,[{incl_cond,include}]} + ]}, + + %% Generate target file + TargetDir = filename:join([?WORK_DIR, "target_dupl_mod_excl_mod"]), + ?m(ok, reltool_utils:recursive_delete(TargetDir)), + ?m(ok, file:make_dir(TargetDir)), + ?log("SPEC: ~p\n", [reltool:get_target_spec([{config, ExclMod}])]), + {ok,["Module mylib exists in applications x and y. Using module from application x."]} = reltool:get_status([{config, ExclMod}]), + ?m(ok, reltool:create_target([{config, ExclMod}], TargetDir)), + + Erl = filename:join([TargetDir, "bin", "erl"]), + {ok, Node} = ?msym({ok, _}, start_node(?NODE_NAME, Erl)), + + AbsTargetDir = filename:absname(TargetDir), + XArchive = "x-1.0.ez", + AbsXArchive = filename:join([AbsTargetDir,lib,XArchive]), + XEbin = ["ebin","x-1.0",XArchive], + YArchive = "y-1.0.ez", + AbsYArchive = filename:join([AbsTargetDir,lib,YArchive]), + YEbin = ["ebin","y-1.0",YArchive], + + ?m(true, filelib:is_file(AbsXArchive)), + ?m(XEbin, mod_path(Node,x)), + ?m(XEbin, mod_path(Node,mylib)), + ?m(true, filelib:is_file(AbsYArchive)), + ?m(YEbin, mod_path(Node,y)), + + %% Remove path to XEbin and check that mylib is not located in YEbin + Mylib = rpc:call(Node,code,which,[mylib]), + rpc:call(Node,code,del_path,[filename:dirname(Mylib)]), + ?m(non_existing, mod_path(Node,mylib)), + + ?msym(ok, stop_node(Node)), + + ok. + + + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Library functions erl_libs() -> @@ -407,6 +516,20 @@ os_cmd(Cmd) when is_list(Cmd) -> end end. +%% Returns the location (directory) of the given module. Split, +%% reverted and relative to the lib dir. +mod_path(Node,Mod) -> + case rpc:call(Node,code,which,[Mod]) of + Path when is_list(Path) -> + lists:takewhile( + fun("lib") -> false; + (_) -> true + end, + lists:reverse(filename:split(filename:dirname(Path)))); + Other -> + Other + end. + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Node handling diff --git a/lib/reltool/test/reltool_server_SUITE_data/Makefile.src b/lib/reltool/test/reltool_server_SUITE_data/Makefile.src new file mode 100644 index 0000000000..049e8dd6cc --- /dev/null +++ b/lib/reltool/test/reltool_server_SUITE_data/Makefile.src @@ -0,0 +1,19 @@ +EFLAGS=+debug_info + +OTP9229= \ + otp_9229/x-1.0/ebin/x.@EMULATOR@ \ + otp_9229/x-1.0/ebin/mylib.@EMULATOR@ \ + otp_9229/y-1.0/ebin/y.@EMULATOR@ \ + otp_9229/y-1.0/ebin/mylib.@EMULATOR@ + + +all: $(OTP9229) + +otp_9229/x-1.0/ebin/x.@EMULATOR@: otp_9229/x-1.0/src/x.erl + erlc $(EFLAGS) -ootp_9229/x-1.0/ebin otp_9229/x-1.0/src/x.erl +otp_9229/x-1.0/ebin/mylib.@EMULATOR@: otp_9229/x-1.0/src/mylib.erl + erlc $(EFLAGS) -ootp_9229/x-1.0/ebin otp_9229/x-1.0/src/mylib.erl +otp_9229/y-1.0/ebin/y.@EMULATOR@: otp_9229/y-1.0/src/y.erl + erlc $(EFLAGS) -ootp_9229/y-1.0/ebin otp_9229/y-1.0/src/y.erl +otp_9229/y-1.0/ebin/mylib.@EMULATOR@: otp_9229/y-1.0/src/mylib.erl + erlc $(EFLAGS) -ootp_9229/y-1.0/ebin otp_9229/y-1.0/src/mylib.erl diff --git a/lib/reltool/test/reltool_server_SUITE_data/otp_9229/x-1.0/ebin/x.app b/lib/reltool/test/reltool_server_SUITE_data/otp_9229/x-1.0/ebin/x.app new file mode 100644 index 0000000000..e597704b19 --- /dev/null +++ b/lib/reltool/test/reltool_server_SUITE_data/otp_9229/x-1.0/ebin/x.app @@ -0,0 +1,7 @@ +%% -*- erlang -*- +{application, x, + [{description, "X CXC 138 11"}, + {vsn, "1.0"}, + {modules, [x, mylib]}, + {registered, []}, + {applications, [kernel, stdlib]}]}. diff --git a/lib/reltool/test/reltool_server_SUITE_data/otp_9229/x-1.0/src/mylib.erl b/lib/reltool/test/reltool_server_SUITE_data/otp_9229/x-1.0/src/mylib.erl new file mode 100644 index 0000000000..c8603d1a8e --- /dev/null +++ b/lib/reltool/test/reltool_server_SUITE_data/otp_9229/x-1.0/src/mylib.erl @@ -0,0 +1,4 @@ +-module(mylib). +-export([foo/0]). + +foo() -> erlang:time(). diff --git a/lib/reltool/test/reltool_server_SUITE_data/otp_9229/x-1.0/src/x.erl b/lib/reltool/test/reltool_server_SUITE_data/otp_9229/x-1.0/src/x.erl new file mode 100644 index 0000000000..17ff84f08f --- /dev/null +++ b/lib/reltool/test/reltool_server_SUITE_data/otp_9229/x-1.0/src/x.erl @@ -0,0 +1,4 @@ +-module(x). +-export([x/0]). + +x() ->mylib:foo(). diff --git a/lib/reltool/test/reltool_server_SUITE_data/otp_9229/y-1.0/ebin/y.app b/lib/reltool/test/reltool_server_SUITE_data/otp_9229/y-1.0/ebin/y.app new file mode 100644 index 0000000000..5b327862e3 --- /dev/null +++ b/lib/reltool/test/reltool_server_SUITE_data/otp_9229/y-1.0/ebin/y.app @@ -0,0 +1,7 @@ +%% -*- erlang -*- +{application, y, + [{description, "Y CXC 138 11"}, + {vsn, "1.0"}, + {modules, [y, mylib]}, + {registered, []}, + {applications, [kernel, stdlib]}]}. diff --git a/lib/reltool/test/reltool_server_SUITE_data/otp_9229/y-1.0/src/mylib.erl b/lib/reltool/test/reltool_server_SUITE_data/otp_9229/y-1.0/src/mylib.erl new file mode 100644 index 0000000000..c8603d1a8e --- /dev/null +++ b/lib/reltool/test/reltool_server_SUITE_data/otp_9229/y-1.0/src/mylib.erl @@ -0,0 +1,4 @@ +-module(mylib). +-export([foo/0]). + +foo() -> erlang:time(). diff --git a/lib/reltool/test/reltool_server_SUITE_data/otp_9229/y-1.0/src/y.erl b/lib/reltool/test/reltool_server_SUITE_data/otp_9229/y-1.0/src/y.erl new file mode 100644 index 0000000000..342e7da7d5 --- /dev/null +++ b/lib/reltool/test/reltool_server_SUITE_data/otp_9229/y-1.0/src/y.erl @@ -0,0 +1,4 @@ +-module(y). +-export([y/0]). + +y() ->mylib:foo(). diff --git a/lib/reltool/vsn.mk b/lib/reltool/vsn.mk index 484f84788d..227b1c80a2 100644 --- a/lib/reltool/vsn.mk +++ b/lib/reltool/vsn.mk @@ -1 +1 @@ -RELTOOL_VSN = 0.5.5 +RELTOOL_VSN = 0.5.6 |