diff options
Diffstat (limited to 'lib/reltool')
12 files changed, 442 insertions, 166 deletions
diff --git a/lib/reltool/doc/src/reltool.xml b/lib/reltool/doc/src/reltool.xml index 2567a72999..8437b7a623 100644 --- a/lib/reltool/doc/src/reltool.xml +++ b/lib/reltool/doc/src/reltool.xml @@ -5,7 +5,7 @@ <header> <copyright> <year>2009</year> - <year>2012</year> + <year>2013</year> <holder>Ericsson AB, All Rights Reserved</holder> </copyright> <legalnotice> @@ -51,8 +51,18 @@ defines library directories where additional applications may reside and it defaults to the directories listed by the operating system environment variable - <c>ERL_LIBS</c>. See the module <c>code</c> for more info. - Finally single modules and entire applications may be read from + <c>ERL_LIBS</c>. See the module <c>code</c> for more info.</p> + + <p>An application directory <c>AppDir</c> under a library + directory is recognized by the existence of an <c>AppDir/ebin</c> + directory. If this does not exist, <c>reltool</c> will not + consider <c>AppDir</c> at all when looking for applications.</p> + + <p>It is recommended that application directories are named as the + application, possibly followed by a dash and the version + number. For example <c>myapp</c> or <c>myapp-1.1</c>.</p> + + <p>Finally single modules and entire applications may be read from Escripts.</p> <p>Some configuration parameters control the behavior of Reltool @@ -264,7 +274,8 @@ </taglist> <p>Example:</p> - <p><code>erl -sasl releases_dir \"mytarget/releases\" -boot mytarget/releases/1.0/myrel -boot_var RELTOOL_EXT_LIB mytarget/lib</code></p> + <p><code>erl -sasl releases_dir \"mytarget/releases\" -boot mytarget/releases/1.0/myrel\ + -boot_var RELTOOL_EXT_LIB mytarget/lib</code></p> </item> <tag><c>incl_sys_filters</c></tag> @@ -372,6 +383,11 @@ <p>This parameter is mutual exclusive with <c>lib_dir</c>. If <c>vsn</c> and <c>lib_dir</c> are both omitted, the latest version will be chosen.</p> + <p>Note that in order for reltool to sort application versions + and thereby be able to select the latest, it is required that + the version id for the application consits of integers and + dots only, for example <c>1</c>, <c>2.0</c> or + <c>3.17.1</c>.</p> </item> <tag><c>lib_dir</c></tag> <item> @@ -383,6 +399,11 @@ <p>This parameter is mutual exclusive with <c>vsn</c>. If <c>vsn</c> and <c>lib_dir</c> are both omitted, the latest version will be chosen.</p> + <p>Note that in order for reltool to sort application versions + and thereby be able to select the latest, it is required that + the version id for the application consits of integers and + dots only, for example <c>1</c>, <c>2.0</c> or + <c>3.17.1</c>.</p> </item> <tag><c>mod</c></tag> <item> @@ -446,7 +467,7 @@ <tag><c>incl_cond</c></tag> <item> <p>This parameter controls whether the module is included or not. By - default the <c>mod_incl</c> parameter on application and system level + default the <c>mod_cond</c> parameter on application and system level will be used to control whether the module is included or not. The value of <c>incl_cond</c> overrides the module inclusion policy. <c>include</c> implies that the module is included, while diff --git a/lib/reltool/doc/src/reltool_usage.xml b/lib/reltool/doc/src/reltool_usage.xml index d128e80a77..0041e60d8f 100644 --- a/lib/reltool/doc/src/reltool_usage.xml +++ b/lib/reltool/doc/src/reltool_usage.xml @@ -5,7 +5,7 @@ <header> <copyright> <year>2009</year> - <year>2011</year> + <year>2012</year> <holder>Ericsson AB, All Rights Reserved</holder> </copyright> <legalnotice> @@ -257,6 +257,11 @@ policy</c> part of the page. By default the latest version of the application is selected, but it is possible to override this by explicitly selecting another version.</p> + + <p>Note that in order for reltool to sort application versions and + thereby be able to select the latest, it is required that the + version id for the application consits of integers and dots only, + for example <c>1</c>, <c>2.0</c> or <c>3.17.1</c>.</p> <p>By default the <c>Application inclusion policy</c> on system level is used for all applications. Set the value to @@ -335,7 +340,7 @@ <p>There are two categories of modules on the <c>Module dependencies</c> page. If the module is used by other modules, - these are listed under <c>Modules used by others</c>. If the + these are listed under <c>Modules using this</c>. If the module uses other modules, these are listed under <c>Used modules</c>.</p> @@ -365,7 +370,7 @@ <p>There are two categories of modules on the <c>Dependencies</c> page. If the module is used by other modules, these are listed - under <c>Modules used by others</c>. If the module uses other + under <c>Modules using this</c>. If the module uses other modules, these are listed under <c>Used modules</c>.</p> <p>Double click on an module name to launch a module window.</p> diff --git a/lib/reltool/src/reltool_server.erl b/lib/reltool/src/reltool_server.erl index 3d1d7e54bf..c56e29152d 100644 --- a/lib/reltool/src/reltool_server.erl +++ b/lib/reltool/src/reltool_server.erl @@ -674,6 +674,8 @@ mod_init_is_included(ModTab, M, ModCond, AppCond, Default, Status) -> true; exclude -> false; + derived -> + undefined; undefined -> %% print(M#mod.name, hipe, "mod_cond -> ~p\n", %% [ModCond]), @@ -693,6 +695,8 @@ mod_init_is_included(ModTab, M, ModCond, AppCond, Default, Status) -> true; exclude -> false; + derived -> + undefined; undefined -> Default end @@ -783,9 +787,10 @@ mod_mark_is_included(#state{app_tab=AppTab, mod_tab=ModTab, sys=Sys} = S, M#mod{is_pre_included = true, is_included = true}; exclude -> - M#mod{is_pre_included = true, - is_included = true}; - undefined -> + M#mod{is_pre_included = false, + is_included = false}; + ModInclCond when ModInclCond==undefined; + ModInclCond==derived -> M#mod{is_included = true} end, ets:insert(ModTab, M2), @@ -979,7 +984,7 @@ refresh_app(#app{name = AppName, %% Add info from .app file Base = get_base(AppName, ActiveDir), - {_, DefaultVsn} = reltool_utils:split_app_name(Base), + DefaultVsn = get_vsn_from_dir(AppName,Base), Ebin = filename:join([ActiveDir, "ebin"]), AppFile = filename:join([Ebin, @@ -1680,8 +1685,7 @@ app_dirs2([Lib | Libs], Acc) -> EbinDir = filename:join([AppDir, "ebin"]), case filelib:is_dir(EbinDir, erl_prim_loader) of true -> - {Name, _Vsn} = - reltool_utils:split_app_name(Base), + Name = find_app_name(Base,EbinDir), case Name of erts -> false; _ -> {true, {Name, AppDir}} @@ -1699,17 +1703,74 @@ app_dirs2([Lib | Libs], Acc) -> app_dirs2([], Acc) -> lists:sort(lists:append(Acc)). +find_app_name(Base,EbinDir) -> + {ok,EbinFiles} = erl_prim_loader:list_dir(EbinDir), + AppFile = + case [F || F <- EbinFiles, filename:extension(F)=:=".app"] of + [AF] -> + AF; + _ -> + undefined + end, + find_app_name1(Base,AppFile). + +find_app_name1(Base,undefined) -> + {Name,_} = reltool_utils:split_app_name(Base), + Name; +find_app_name1(_Base,AppFile) -> + list_to_atom(filename:rootname(AppFile)). + +get_vsn_from_dir(AppName,Base) -> + Prefix = atom_to_list(AppName) ++ "-", + case lists:prefix(Prefix,Base) of + true -> + lists:nthtail(length(Prefix),Base); + false -> + "" + end. + + escripts_to_apps([Escript | Escripts], Apps, Status) -> {EscriptAppName, _Label} = split_escript_name(Escript), Ext = code:objfile_extension(), + + %% First find all .app files and associate the app name to the app + %% label - this is in order to now which application a module + %% belongs to in the next round. + AppFun = fun(FullName, _GetInfo, _GetBin, AppFiles) -> + Components = filename:split(FullName), + case Components of + [AppLabel, "ebin", File] -> + case filename:extension(File) of + ".app" -> + [{AppLabel,File}|AppFiles]; + _ -> + AppFiles + end; + _ -> + AppFiles + end + end, + AppFiles = + case reltool_utils:escript_foldl(AppFun, [], Escript) of + {ok, AF} -> + AF; + {error, Reason1} -> + reltool_utils:throw_error("Illegal escript ~p: ~p", + [Escript,Reason1]) + end, + + %% Next, traverse all files... Fun = fun(FullName, _GetInfo, GetBin, {FileAcc, StatusAcc}) -> Components = filename:split(FullName), case Components of [AppLabel, "ebin", File] -> case filename:extension(File) of ".app" -> - {AppName, DefaultVsn} = - reltool_utils:split_app_name(AppLabel), + AppName = + list_to_atom(filename:rootname(File)), + DefaultVsn = + get_vsn_from_dir(AppName,AppLabel), AppFileName = filename:join([Escript, FullName]), {Info, StatusAcc2} = @@ -1722,8 +1783,9 @@ escripts_to_apps([Escript | Escripts], Apps, Status) -> {[{AppName, app, Dir, Info} | FileAcc], StatusAcc2}; E when E =:= Ext -> - {AppName, _} = - reltool_utils:split_app_name(AppLabel), + AppFile = + proplists:get_value(AppLabel,AppFiles), + AppName = find_app_name1(AppLabel,AppFile), Mod = init_mod(AppName, File, {File, GetBin()}, @@ -1760,6 +1822,7 @@ escripts_to_apps([Escript | Escripts], Apps, Status) -> {FileAcc, StatusAcc} end end, + case reltool_utils:escript_foldl(Fun, {[], Status}, Escript) of {ok, {Files, Status2}} -> EscriptApp = @@ -1774,8 +1837,9 @@ escripts_to_apps([Escript | Escripts], Apps, Status) -> Apps, Status2), escripts_to_apps(Escripts, Apps2, Status3); - {error, Reason} -> - reltool_utils:throw_error("Illegal escript ~p: ~p", [Escript,Reason]) + {error, Reason2} -> + reltool_utils:throw_error("Illegal escript ~p: ~p", + [Escript,Reason2]) end; escripts_to_apps([], Apps, Status) -> {Apps, Status}. @@ -1934,7 +1998,7 @@ ensure_app_info(#app{name = Name, fun(Dir, StatusAcc) -> Base = get_base(Name, Dir), Ebin = filename:join([Dir, "ebin"]), - {_, DefaultVsn} = reltool_utils:split_app_name(Base), + DefaultVsn = get_vsn_from_dir(Name,Base), AppFile = filename:join([Ebin, atom_to_list(Name) ++ ".app"]), read_app_info(AppFile, AppFile, Name, DefaultVsn, StatusAcc) end, diff --git a/lib/reltool/src/reltool_sys_win.erl b/lib/reltool/src/reltool_sys_win.erl index 0c0b295db1..8e182d02ed 100644 --- a/lib/reltool/src/reltool_sys_win.erl +++ b/lib/reltool/src/reltool_sys_win.erl @@ -49,7 +49,6 @@ rel_book, lib_tree, status_bar, - popup_menu, source, whitelist, blacklist, @@ -136,6 +135,7 @@ init(Options) -> do_init(Options) catch error:Reason -> + io:format("~p: ~p~n",[Reason, erlang:get_stacktrace()]), exit({Reason, erlang:get_stacktrace()}) end. @@ -403,8 +403,6 @@ create_menubar(Frame) -> wxEvtHandler:connect(Frame, command_menu_selected, [{userData, main_window}]), - wxEvtHandler:connect(File, menu_close), - wxEvtHandler:connect(Help, menu_close), MenuBar. create_app_page(#state{book = Book} = S) -> @@ -780,15 +778,12 @@ root_popup(S, Root, Tree, Item) -> wxMenu:appendSeparator(PopupMenu), wxMenu:append(PopupMenu, 1, "Edit"), Choices = [edit], - wxEvtHandler:connect(PopupMenu, command_menu_selected), - wxEvtHandler:connect(PopupMenu, menu_close), + Popup = #root_popup{dir = Root, choices = Choices, + tree = Tree, item = Item}, + wxEvtHandler:connect(PopupMenu, command_menu_selected, [{userData, {popup, Popup}}]), wxWindow:popupMenu(S#state.frame, PopupMenu), - Popup = #root_popup{dir = Root, - choices = Choices, - tree = Tree, - item = Item}, - S#state{popup_menu = Popup}. + S. lib_popup(S, Lib, Tree, Item) -> PopupMenu = wxMenu:new(), @@ -804,12 +799,10 @@ lib_popup(S, Lib, Tree, Item) -> wxMenu:append(PopupMenu, 3, "Delete"), [add, edit, delete] end, - wxEvtHandler:connect(PopupMenu, command_menu_selected), - wxEvtHandler:connect(PopupMenu, menu_close), - wxWindow:popupMenu(S#state.frame, PopupMenu), - Popup = #lib_popup{dir = Lib, choices = Choices, tree = Tree, item = Item}, - S#state{popup_menu = Popup}. + wxEvtHandler:connect(PopupMenu, command_menu_selected, [{userData, {popup, Popup}}]), + wxWindow:popupMenu(S#state.frame, PopupMenu), + S. escript_popup(S, File, Tree, Item) -> PopupMenu = wxMenu:new(), @@ -825,15 +818,11 @@ escript_popup(S, File, Tree, Item) -> wxMenu:append(PopupMenu, 3, "Delete"), [add, edit, delete] end, - wxEvtHandler:connect(PopupMenu, command_menu_selected), - wxEvtHandler:connect(PopupMenu, menu_close), + Popup = #escript_popup{file = File, choices = Choices, + tree = Tree, item = Item}, + wxEvtHandler:connect(PopupMenu, command_menu_selected, [{userData, {popup, Popup}}]), wxWindow:popupMenu(S#state.frame, PopupMenu), - - Popup = #escript_popup{file = File, - choices = Choices, - tree = Tree, - item = Item}, - S#state{popup_menu = Popup}. + S. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -903,11 +892,13 @@ handle_event(S, #wx{id = Id, obj= ObjRef, userData = UserData, event = Event} = wxMessageDialog:showModal(MD), wxMessageDialog:destroy(MD), S; - #wxMenu{type = menu_close} -> - S#state{popup_menu = undefined}; - #wxCommand{type = command_menu_selected = Type, cmdString = Str} - when S#state.popup_menu =/= undefined -> - handle_popup_event(S, Type, Id, ObjRef, UserData, Str); + #wxCommand{type = command_menu_selected = Type, cmdString = Str} -> + case UserData of + {popup, Popup} -> + handle_popup_event(S, Type, Id, ObjRef, Popup, Str); + true -> + S + end; #wxMouse{type = enter_window} -> %% The following is commented out because it raises the %% main system window on top of popup windows. @@ -1028,11 +1019,9 @@ warning_popup_position(#state{frame=MF,warning_list=WL},{WFW,WFH}) -> {X,Y}. handle_popup_event(S, _Type, 0, _ObjRef, _UserData, _Str) -> - S#state{popup_menu = undefined}; -handle_popup_event(#state{popup_menu = #root_popup{dir = OldDir, - choices = Choices}, - sys = Sys} = S, - _Type, Pos, _ObjRef, _UserData, _Str) -> + S; +handle_popup_event(#state{sys = Sys} = S, _Type, Pos, _ObjRef, + #root_popup{dir = OldDir, choices = Choices}, _Str) -> case lists:nth(Pos, Choices) of edit -> Style = ?wxFD_OPEN bor ?wxFD_FILE_MUST_EXIST, @@ -1042,18 +1031,16 @@ handle_popup_event(#state{popup_menu = #root_popup{dir = OldDir, Style) of {ok, NewDir} when NewDir =:= OldDir -> %% Same dir.Ignore. - S#state{popup_menu = undefined}; + S; {ok, NewDir} -> Sys2 = Sys#sys{root_dir = NewDir}, - do_set_sys(S#state{popup_menu = undefined, sys = Sys2}); + do_set_sys(S#state{sys = Sys2}); cancel -> - S#state{popup_menu = undefined} + S end end; -handle_popup_event(#state{popup_menu = #lib_popup{dir = OldDir, - choices = Choices}, - sys = Sys} = S, - _Type, Pos, _ObjRef, _UserData, _Str) -> +handle_popup_event(#state{sys = Sys} = S, _Type, Pos, _ObjRef, + #lib_popup{dir = OldDir, choices = Choices}, _Str) -> case lists:nth(Pos, Choices) of add -> {ok, Cwd} = file:get_cwd(), @@ -1063,15 +1050,14 @@ handle_popup_event(#state{popup_menu = #lib_popup{dir = OldDir, case lists:member(NewDir, Sys#sys.lib_dirs) of true -> %% Ignore duplicate. Keep old. - S#state{popup_menu = undefined}; + S; false -> LibDirs = Sys#sys.lib_dirs ++ [NewDir], Sys2 = Sys#sys{lib_dirs = LibDirs}, - do_set_sys(S#state{popup_menu = undefined, - sys = Sys2}) + do_set_sys(S#state{sys = Sys2}) end; cancel -> - S#state{popup_menu = undefined} + S end; edit -> Style = ?wxFD_OPEN bor ?wxFD_FILE_MUST_EXIST, @@ -1083,28 +1069,25 @@ handle_popup_event(#state{popup_menu = #lib_popup{dir = OldDir, case lists:member(NewDir, Sys#sys.lib_dirs) of true -> %% Ignore duplicate. Keep old. - S#state{popup_menu = undefined}; + S; false -> Pred = fun(E) -> E =/= OldDir end, {Before, [_| After]} = lists:splitwith(Pred, Sys#sys.lib_dirs), LibDirs2 = Before ++ [NewDir | After], Sys2 = Sys#sys{lib_dirs = LibDirs2}, - do_set_sys(S#state{popup_menu = undefined, - sys = Sys2}) + do_set_sys(S#state{sys = Sys2}) end; cancel -> - S#state{popup_menu = undefined} + S end; delete -> LibDirs = Sys#sys.lib_dirs -- [OldDir], Sys2 = Sys#sys{lib_dirs = LibDirs}, - do_set_sys(S#state{popup_menu = undefined, sys = Sys2}) + do_set_sys(S#state{sys = Sys2}) end; -handle_popup_event(#state{popup_menu = #escript_popup{file = OldFile, - choices = Choices}, - sys = Sys} = S, - _Type, Pos, _ObjRef, _UserData, _Str) -> +handle_popup_event(#state{sys = Sys} = S, _Type, Pos, _ObjRef, + #escript_popup{file = OldFile, choices = Choices}, _Str) -> case lists:nth(Pos, Choices) of add -> OldFile2 = @@ -1124,14 +1107,14 @@ handle_popup_event(#state{popup_menu = #escript_popup{file = OldFile, case lists:member(NewFile, Sys#sys.escripts) of true -> %% Ignore duplicate. Keep old. - S#state{popup_menu = undefined}; + S; false -> Escripts = Sys#sys.escripts ++ [NewFile], Sys2 = Sys#sys{escripts = Escripts}, - do_set_sys(S#state{popup_menu = undefined, sys = Sys2}) + do_set_sys(S#state{sys = Sys2}) end; cancel -> - S#state{popup_menu = undefined} + S end; edit -> Style = ?wxFD_OPEN bor ?wxFD_FILE_MUST_EXIST, @@ -1143,23 +1126,22 @@ handle_popup_event(#state{popup_menu = #escript_popup{file = OldFile, case lists:member(NewFile, Sys#sys.escripts) of true -> %% Ignore duplicate. Keep old. - S#state{popup_menu = undefined}; + S; false -> Pred = fun(E) -> E =/= OldFile end, {Before, [_| After]} = lists:splitwith(Pred, Sys#sys.escripts), Escripts2 = Before ++ [NewFile | After], Sys2 = Sys#sys{escripts = Escripts2}, - do_set_sys(S#state{popup_menu = undefined, - sys = Sys2}) + do_set_sys(S#state{sys = Sys2}) end; cancel -> - S#state{popup_menu = undefined} + S end; delete -> Escripts = Sys#sys.escripts -- [OldFile], Sys2 = Sys#sys{escripts = Escripts}, - do_set_sys(S#state{popup_menu = undefined, sys = Sys2}) + do_set_sys(S#state{sys = Sys2}) end. handle_system_event(#state{sys = Sys} = S, diff --git a/lib/reltool/src/reltool_target.erl b/lib/reltool/src/reltool_target.erl index c39ed0ecd5..1f4ce7226a 100644 --- a/lib/reltool/src/reltool_target.erl +++ b/lib/reltool/src/reltool_target.erl @@ -333,7 +333,9 @@ merge_apps(#rel{name = RelName, A#app.name =/= ?MISSING_APP_NAME, not lists:keymember(A#app.name, #app.name, MergedApps2)], MergedApps3 = do_merge_apps(RelName, Embedded, Apps, EmbAppType, MergedApps2), - sort_apps(lists:reverse(MergedApps3)). + RevMerged = lists:reverse(MergedApps3), + MergedSortedUsedAndIncs = sort_used_and_incl_apps(RevMerged,RevMerged), + sort_apps(MergedSortedUsedAndIncs). do_merge_apps(RelName, [#rel_app{name = Name} = RA | RelApps], Apps, RelAppType, Acc) -> case is_already_merged(Name, RelApps, Acc) of @@ -342,9 +344,11 @@ do_merge_apps(RelName, [#rel_app{name = Name} = RA | RelApps], Apps, RelAppType, false -> {value, App} = lists:keysearch(Name, #app.name, Apps), MergedApp = merge_app(RelName, RA, RelAppType, App), - MoreNames = (MergedApp#app.info)#app_info.applications, + ReqNames = (MergedApp#app.info)#app_info.applications, + IncNames = (MergedApp#app.info)#app_info.incl_apps, Acc2 = [MergedApp | Acc], - do_merge_apps(RelName, MoreNames ++ RelApps, Apps, RelAppType, Acc2) + do_merge_apps(RelName, ReqNames ++ IncNames ++ RelApps, + Apps, RelAppType, Acc2) end; do_merge_apps(RelName, [Name | RelApps], Apps, RelAppType, Acc) -> case is_already_merged(Name, RelApps, Acc) of @@ -478,33 +482,62 @@ do_gen_script(#rel{name = RelName, vsn = RelVsn}, %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -load_app_mods(#app{mods = Mods} = App, Mand, PathFlag, Variables) -> +load_app_mods(#app{mods = Mods0} = App, Mand, PathFlag, Variables) -> Path = cr_path(App, PathFlag, Variables), - PartNames = - lists:sort([{packages:split(M),M} || - #mod{name = M, is_included=true} <- Mods, - not lists:member(M, Mand)]), - SplitMods = - lists:foldl( - fun({Parts,M}, [{Last, Acc}|Rest]) -> - [_|Tail] = lists:reverse(Parts), - case lists:reverse(Tail) of - Subs when Subs == Last -> - [{Last,[M|Acc]}|Rest]; - Subs -> - [{Subs, [M]}|[{Last,Acc}|Rest]] - end - end, - [{[], - []}], - PartNames), - lists:foldl( - fun({Subs,Ms}, Cmds) -> - [{path, [filename:join([Path | Subs])]}, - {primLoad, lists:sort(Ms)} | Cmds] - end, - [], - SplitMods). + Mods = [M || #mod{name = M, is_included=true} <- Mods0, + not lists:member(M, Mand)], + [{path, [filename:join([Path])]}, + {primLoad, lists:sort(Mods)}]. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% sort_used_and_incl_apps(Apps, OrderedApps) -> Apps +%% Apps = [#app{}] +%% OrderedApps = [#app{}] +%% +%% OTP-4121, OTP-9984 +%% (Tickets are written for systools, but needs to be implemented here +%% as well.) +%% Make sure that used and included applications are given in the same +%% order as in the release resource file (.rel). Otherwise load and +%% start instructions in the boot script, and consequently release +%% upgrade instructions in relup, may end up in the wrong order. + +sort_used_and_incl_apps([#app{info=Info} = App|Apps], OrderedApps) -> + Incls2 = + case Info#app_info.incl_apps of + Incls when length(Incls)>1 -> + sort_appl_list(Incls, OrderedApps); + Incls -> + Incls + end, + Uses2 = + case Info#app_info.applications of + Uses when length(Uses)>1 -> + sort_appl_list(Uses, OrderedApps); + Uses -> + Uses + end, + App2 = App#app{info=Info#app_info{incl_apps=Incls2, applications=Uses2}}, + [App2|sort_used_and_incl_apps(Apps, OrderedApps)]; +sort_used_and_incl_apps([], _OrderedApps) -> + []. + +sort_appl_list(List, Order) -> + IndexedList = find_pos(List, Order), + SortedIndexedList = lists:keysort(1, IndexedList), + lists:map(fun({_Index,Name}) -> Name end, SortedIndexedList). + +find_pos([Name|Incs], OrderedApps) -> + [find_pos(1, Name, OrderedApps)|find_pos(Incs, OrderedApps)]; +find_pos([], _OrderedApps) -> + []. + +find_pos(N, Name, [#app{name=Name}|_OrderedApps]) -> + {N, Name}; +find_pos(N, Name, [_OtherAppl|OrderedApps]) -> + find_pos(N+1, Name, OrderedApps). + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Function: sort_apps(Apps) -> {ok, Apps'} | throw({error, Error}) @@ -1420,12 +1453,10 @@ do_install(RelName, TargetDir) -> BinDir = filename:join([TargetDir2, "bin"]), case os:type() of {win32, _} -> - NativeRootDir = filename:nativename(TargetDir2), - %% NativeBinDir = - %% filename:nativename(filename:join([BinDir, "win32"])), - NativeBinDir = filename:nativename(BinDir), + NativeRootDir = nativename(TargetDir2), + NativeErtsBinDir = nativename(ErtsBinDir), IniData = ["[erlang]\r\n", - "Bindir=", NativeBinDir, "\r\n", + "Bindir=", NativeErtsBinDir, "\r\n", "Progname=erl\r\n", "Rootdir=", NativeRootDir, "\r\n"], IniFile = filename:join([BinDir, "erl.ini"]), @@ -1445,6 +1476,15 @@ do_install(RelName, TargetDir) -> reltool_utils:throw_error("~s: Illegal data file syntax", [DataFile]) end. +nativename(Dir) -> + escape_backslash(filename:nativename(Dir)). +escape_backslash([$\\|T]) -> + [$\\,$\\|escape_backslash(T)]; +escape_backslash([H|T]) -> + [H|escape_backslash(T)]; +escape_backslash([]) -> + []. + subst_src_scripts(Scripts, SrcDir, DestDir, Vars, Opts) -> Fun = fun(Script) -> subst_src_script(Script, SrcDir, DestDir, Vars, Opts) diff --git a/lib/reltool/test/reltool_server_SUITE.erl b/lib/reltool/test/reltool_server_SUITE.erl index f29f6049a5..8d71865508 100644 --- a/lib/reltool/test/reltool_server_SUITE.erl +++ b/lib/reltool/test/reltool_server_SUITE.erl @@ -90,8 +90,10 @@ all() -> gen_rel_files, save_config, dependencies, + mod_incl_cond_derived, use_selected_vsn, - use_selected_vsn_relative_path]. + use_selected_vsn_relative_path, + non_standard_vsn_id]. groups() -> []. @@ -106,6 +108,15 @@ end_per_group(_GroupName, Config) -> %% The test cases %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% A dummy break test case which is NOT in all(), but can be run +%% directly from the command line with ct_run. It just does a +%% test_server:break()... +break(_Config) -> + test_server:break(""), + ok. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Start a server process and check that it does not crash start_server(_Config) -> @@ -298,7 +309,6 @@ create_release(_Config) -> %% started before the including application. %% Circular dependencies shall also be detected and cause error. -create_release_sort(_Config) -> {skip, "Two bugs related to sorting"}; create_release_sort(Config) -> DataDir = ?config(data_dir,Config), %% Configure the server @@ -307,11 +317,12 @@ create_release_sort(Config) -> RelName3 = "Include-both", RelName4 = "Include-only-app", RelName5 = "Include-only-rel", - RelName6 = "Include-missing-app", + RelName6 = "Auto-add-missing-apps", RelName7 = "Circular", - RelName8 = "Include-both-missing-app", - RelName9 = "Include-overwrite", + RelName8 = "Include-rel-alter-order", + RelName9 = "Include-none-overwrite", RelName10= "Uses-order-as-rel", + RelName11= "Auto-add-dont-overwrite-load", RelVsn = "1.0", %% Application z (.app file): %% includes [tools, mnesia] @@ -326,11 +337,12 @@ create_release_sort(Config) -> {rel, RelName3, RelVsn, [stdlib, kernel, {z,[tools]}, tools, mnesia]}, {rel, RelName4, RelVsn, [stdlib, kernel, z, mnesia, tools]}, {rel, RelName5, RelVsn, [stdlib, kernel, {sasl,[tools]}]}, - {rel, RelName6, RelVsn, [stdlib, kernel, z]}, + {rel, RelName6, RelVsn, [z]}, {rel, RelName7, RelVsn, [stdlib, kernel, mnesia, y, sasl, x]}, - {rel, RelName8, RelVsn, [stdlib, kernel, {z,[tools]}]}, + {rel, RelName8, RelVsn, [stdlib, kernel, {z,[mnesia,tools]}]}, {rel, RelName9, RelVsn, [stdlib, kernel, {z,[]}]}, {rel, RelName10, RelVsn, [stdlib, kernel, {z,[]}, inets, sasl]}, + {rel, RelName11, RelVsn, [stdlib, kernel, z, {inets, load}]}, {incl_cond,exclude}, {mod_cond,app}, {app,kernel,[{incl_cond,include}]}, @@ -372,7 +384,6 @@ create_release_sort(Config) -> {mnesia, _}]}}, reltool:get_rel([{config, Sys}], RelName3)), - %%! BUG: same as OTP-4121, but for reltool???? Or revert tools and mnesia ?msym({ok, {release, {RelName4, RelVsn}, {erts, _}, [{kernel, _}, @@ -389,13 +400,29 @@ create_release_sort(Config) -> "in the app file: [tools]"}, reltool:get_rel([{config, Sys}], RelName5)), - ?m({error, "Undefined applications: [tools,mnesia]"}, + ?msym({ok, {release, {RelName6, RelVsn}, + {erts, _}, + [{kernel, _}, + {stdlib, _}, + {sasl, _}, + {inets, _}, + {tools, _}, + {mnesia, _}, + {z, _}]}}, reltool:get_rel([{config, Sys}], RelName6)), ?m({error,"Circular dependencies: [x,y]"}, reltool:get_rel([{config, Sys}], RelName7)), - ?m({error,"Undefined applications: [tools]"}, + ?msym({ok, {release, {RelName8, RelVsn}, + {erts, _}, + [{kernel, _}, + {stdlib, _}, + {sasl, _}, + {inets, _}, + {mnesia, _}, + {tools, _}, + {z, _, [mnesia,tools]}]}}, reltool:get_rel([{config, Sys}], RelName8)), ?msym({ok,{release,{RelName9,RelVsn}, @@ -407,7 +434,6 @@ create_release_sort(Config) -> {z,_,[]}]}}, reltool:get_rel([{config, Sys}], RelName9)), - %%! BUG: same as OTP-9984, but for reltool???? Or revert inets and sasl? ?msym({ok,{release,{RelName10,RelVsn}, {erts,_}, [{kernel,_}, @@ -417,6 +443,17 @@ create_release_sort(Config) -> {z,_,[]}]}}, reltool:get_rel([{config, Sys}], RelName10)), + ?msym({ok,{release,{RelName11,RelVsn}, + {erts,_}, + [{kernel,_}, + {stdlib,_}, + {sasl, _}, + {inets, _, load}, + {tools, _}, + {mnesia, _}, + {z,_}]}}, + reltool:get_rel([{config, Sys}], RelName11)), + ok. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -477,12 +514,16 @@ create_script_sort(Config) -> RelName3 = "Include-both", RelName4 = "Include-only-app", RelName5 = "Include-only-rel", - RelName6 = "Include-missing-app", + RelName6 = "Auto-add-missing-apps", RelName7 = "Circular", - RelName8 = "Include-both-missing-app", - RelName9 = "Include-overwrite", + RelName8 = "Include-rel-alter-order", + RelName9 = "Include-none-overwrite", + RelName10= "Uses-order-as-rel", RelVsn = "1.0", LibDir = filename:join(DataDir,"sort_apps"), + %% Application z (.app file): + %% includes [tools, mnesia] + %% uses [kernel, stdlib, sasl, inets] Sys = {sys, [ @@ -493,10 +534,11 @@ create_script_sort(Config) -> {rel, RelName3, RelVsn, [stdlib, kernel, {z,[tools]}, tools, mnesia]}, {rel, RelName4, RelVsn, [stdlib, kernel, z, mnesia, tools]}, {rel, RelName5, RelVsn, [stdlib, kernel, {sasl,[tools]}]}, - {rel, RelName6, RelVsn, [stdlib, kernel, z]}, + {rel, RelName6, RelVsn, [z]}, {rel, RelName7, RelVsn, [stdlib, kernel, mnesia, y, sasl, x]}, - {rel, RelName8, RelVsn, [stdlib, kernel, {z,[tools]}]}, + {rel, RelName8, RelVsn, [stdlib, kernel, {z,[mnesia,tools]}]}, {rel, RelName9, RelVsn, [stdlib, kernel, {z,[]}]}, + {rel, RelName10, RelVsn, [stdlib, kernel, {z,[]}, inets, sasl]}, {incl_cond,exclude}, {mod_cond,app}, {app,kernel,[{incl_cond,include}]}, @@ -553,8 +595,8 @@ create_script_sort(Config) -> [{kernel,KernelVsn}, {stdlib,StdlibVsn}, {z,"1.0"}, - {tools,ToolsVsn}, {mnesia,MnesiaVsn}, + {tools,ToolsVsn}, {sasl,SaslVsn}, {inets,InetsVsn}]}, FullName4 = filename:join(?WORK_DIR,RelName4), @@ -569,6 +611,10 @@ create_script_sort(Config) -> Rel6 = {release, {RelName6,RelVsn}, {erts,ErtsVsn}, [{kernel,KernelVsn}, {stdlib,StdlibVsn}, + {sasl,SaslVsn}, + {inets,InetsVsn}, + {tools,ToolsVsn}, + {mnesia,MnesiaVsn}, {z,"1.0"}]}, FullName6 = filename:join(?WORK_DIR,RelName6), ?m(ok, file:write_file(FullName6 ++ ".rel", io_lib:format("~p.\n", [Rel6]))), @@ -584,7 +630,11 @@ create_script_sort(Config) -> Rel8 = {release, {RelName8,RelVsn}, {erts,ErtsVsn}, [{kernel,KernelVsn}, {stdlib,StdlibVsn}, - {z,"1.0",[tools]}]}, + {z,"1.0",[mnesia,tools]}, + {sasl,SaslVsn}, + {inets,InetsVsn}, + {mnesia,MnesiaVsn}, + {tools,ToolsVsn}]}, FullName8 = filename:join(?WORK_DIR,RelName8), ?m(ok, file:write_file(FullName8 ++ ".rel", io_lib:format("~p.\n", [Rel8]))), Rel9 = {release, {RelName9,RelVsn}, {erts,ErtsVsn}, @@ -595,6 +645,14 @@ create_script_sort(Config) -> {inets,InetsVsn}]}, FullName9 = filename:join(?WORK_DIR,RelName9), ?m(ok, file:write_file(FullName9 ++ ".rel", io_lib:format("~p.\n", [Rel9]))), + Rel10 = {release, {RelName10,RelVsn}, {erts,ErtsVsn}, + [{kernel,KernelVsn}, + {stdlib,StdlibVsn}, + {z,"1.0",[]}, + {inets,InetsVsn}, + {sasl,SaslVsn}]}, + FullName10 = filename:join(?WORK_DIR,RelName10), + ?m(ok, file:write_file(FullName10 ++ ".rel", io_lib:format("~p.\n", [Rel10]))), %% Generate script files with systools and reltool and compare ZPath = filename:join([LibDir,"*",ebin]), @@ -626,26 +684,31 @@ create_script_sort(Config) -> "in the app file: [tools]"}, reltool:get_script(Pid, RelName5)), - ?msym({error,_,{undefined_applications,_}}, - systools_make_script(FullName6,ZPath)), - ?m({error, "Undefined applications: [tools,mnesia]"}, - reltool:get_script(Pid, RelName6)), + ?msym({ok,_,_}, systools_make_script(FullName6,ZPath)), + {ok, [SystoolsScript6]} = ?msym({ok,[_]}, file:consult(FullName6++".script")), + {ok, Script6} = ?msym({ok, _}, reltool:get_script(Pid, RelName6)), + ?m(equal, diff_script(SystoolsScript6, Script6)), ?msym({error,_,{circular_dependencies,_}}, systools_make_script(FullName7,ZPath)), ?m({error,"Circular dependencies: [x,y]"}, reltool:get_script(Pid, RelName7)), - ?msym({error,_,{undefined_applications,_}}, - systools_make_script(FullName8,ZPath)), - ?m({error, "Undefined applications: [tools]"}, - reltool:get_script(Pid, RelName8)), + ?msym({ok,_,_}, systools_make_script(FullName8,ZPath)), + {ok, [SystoolsScript8]} = ?msym({ok,[_]}, file:consult(FullName8++".script")), + {ok, Script8} = ?msym({ok, _}, reltool:get_script(Pid, RelName8)), + ?m(equal, diff_script(SystoolsScript8, Script8)), ?msym({ok,_,_}, systools_make_script(FullName9,ZPath)), {ok, [SystoolsScript9]} = ?msym({ok,[_]}, file:consult(FullName9++".script")), {ok, Script9} = ?msym({ok, _}, reltool:get_script(Pid, RelName9)), ?m(equal, diff_script(SystoolsScript9, Script9)), + ?msym({ok,_,_}, systools_make_script(FullName10,ZPath)), + {ok, [SystoolsScript10]} = ?msym({ok,[_]}, file:consult(FullName10++".script")), + {ok, Script10} = ?msym({ok, _}, reltool:get_script(Pid, RelName10)), + ?m(equal, diff_script(SystoolsScript10, Script10)), + %% Stop server ?m(ok, reltool:stop(Pid)), ok. @@ -951,8 +1014,6 @@ create_multiple_standalone(Config) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Generate old type of target system - -create_old_target(_Config) -> {skip, "Old style of target"}; create_old_target(_Config) -> %% Configure the server @@ -975,8 +1036,7 @@ create_old_target(_Config) -> ?m(ok, reltool_utils:recursive_delete(TargetDir)), ?m(ok, file:make_dir(TargetDir)), ok = ?m(ok, reltool:create_target([{config, Config}], TargetDir)), - - %% io:format("Will fail on Windows (should patch erl.ini)\n", []), + ok = ?m(ok, reltool:install(RelName2, TargetDir)), Erl = filename:join([TargetDir, "bin", "erl"]), @@ -1024,9 +1084,14 @@ create_slim(Config) -> RootDir = code:root_dir(), Erl = filename:join([RootDir, "bin", "erl"]), - Args = "-boot_var RELTOOL_EXT_LIB " ++ TargetLibDir ++ - " -boot " ++ filename:join(TargetRelVsnDir,RelName) ++ - " -sasl releases_dir \\\"" ++ TargetRelDir ++ "\\\"", + EscapedQuote = + case os:type() of + {win32,_} -> "\\\""; + _ -> "\"" + end, + Args = ["-boot_var", "RELTOOL_EXT_LIB", TargetLibDir, + "-boot", filename:join(TargetRelVsnDir,RelName), + "-sasl", "releases_dir", EscapedQuote++TargetRelDir++EscapedQuote], {ok, Node} = ?msym({ok, _}, start_node(?NODE_NAME, Erl, Args)), ?msym(RootDir, rpc:call(Node, code, root_dir, [])), ?msym([{RelName,RelVsn,_,permanent}], @@ -1942,7 +2007,7 @@ save_config(Config) -> %% %% x-1.0: x1.erl x2.erl x3.erl %% \ / (x2 calls y1, x3 calls y2) -%% y-1.0: y1.erl y2.erl +%% y-1.0: y0.erl y1.erl y2.erl %% \ (y1 calls z1) %% z-1.0 z1.erl %% @@ -2072,6 +2137,47 @@ dependencies(Config) -> ok. +%% Test that incl_cond on mod level overwrites mod_cond on app level +%% Uses same test applications as dependencies/1 above +mod_incl_cond_derived(Config) -> + %% In app y: mod_cond=none means no module shall be included + %% but mod_cond is overwritten by incl_cond on mod level + Sys = {sys,[{lib_dirs,[filename:join(datadir(Config),"dependencies")]}, + {incl_cond, exclude}, + {app,kernel,[{incl_cond,include}]}, + {app,sasl,[{incl_cond,include}]}, + {app,stdlib,[{incl_cond,include}]}, + {app,x,[{incl_cond,include}]}, + {app,y,[{incl_cond,include}, + {mod_cond,none}, + {mod,y0,[{incl_cond,derived}]}, + {mod,y2,[{incl_cond,derived}]}]}]}, + {ok, Pid} = ?msym({ok, _}, reltool:start_server([{config, Sys}])), + + ?msym({ok,[#app{name=kernel}, + #app{name=sasl}, + #app{name=stdlib}, + #app{name=x,uses_apps=[y]}, + #app{name=y,uses_apps=[]}]}, + reltool_server:get_apps(Pid,whitelist)), + {ok, Der} = ?msym({ok,_},reltool_server:get_apps(Pid,derived)), + ?msym([], rm_missing_app(Der)), + ?msym({ok,[]}, reltool_server:get_apps(Pid,source)), + + %% 1. check that y0 is not included since it has + %% incl_cond=derived, but is not used by any other module. + ?msym({ok,#mod{is_included=undefined}}, reltool_server:get_mod(Pid,y0)), + + %% 2. check that y1 is excluded since it has undefined incl_cond + %% on mod level, so mod_cond on app level shall be used. + ?msym({ok,#mod{is_included=false}}, reltool_server:get_mod(Pid,y1)), + + %% 3. check that y2 is included since it has incl_cond=derived and + %% is used by x3. + ?msym({ok,#mod{is_included=true}}, reltool_server:get_mod(Pid,y2)), + + ok. + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% use_selected_vsn(Config) -> LibDir1 = filename:join(datadir(Config),"use_selected_vsn"), @@ -2196,6 +2302,39 @@ use_selected_vsn_relative_path(Config) -> ok = file:set_cwd(Cwd), ok. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Test that reltool recognizes an application with its real name even +%% though it uses non standard format for its version number (in the +%% directory name) +non_standard_vsn_id(Config) -> + LibDir = filename:join(datadir(Config),"non_standard_vsn_id"), + B1Dir = filename:join(LibDir,"b-first"), + B2Dir = filename:join(LibDir,"b-second"), + + %%----------------------------------------------------------------- + %% Default vsn of app b + Sys1 = {sys,[{lib_dirs,[LibDir]}, + {incl_cond, exclude}, + {app,kernel,[{incl_cond,include}]}, + {app,sasl,[{incl_cond,include}]}, + {app,stdlib,[{incl_cond,include}]}, + {app,b,[{incl_cond,include}]}]}, + {ok, Pid1} = ?msym({ok, _}, reltool:start_server([{config, Sys1}])), + ?msym({ok,#app{vsn="first",active_dir=B1Dir,sorted_dirs=[B1Dir,B2Dir]}}, + reltool_server:get_app(Pid1,b)), + + %%----------------------------------------------------------------- + %% Pre-selected vsn of app b + Sys2 = {sys,[{lib_dirs,[LibDir]}, + {incl_cond, exclude}, + {app,kernel,[{incl_cond,include}]}, + {app,sasl,[{incl_cond,include}]}, + {app,stdlib,[{incl_cond,include}]}, + {app,b,[{incl_cond,include},{vsn,"second"}]}]}, + {ok, Pid2} = ?msym({ok, _}, reltool:start_server([{config, Sys2}])), + ?msym({ok,#app{vsn="second",active_dir=B2Dir,sorted_dirs=[B1Dir,B2Dir]}}, + reltool_server:get_app(Pid2,b)), + ok. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -2278,11 +2417,13 @@ mod_path(Node,Mod) -> start_node(Name, ErlPath) -> start_node(Name, ErlPath, []). -start_node(Name, ErlPath, Args) -> +start_node(Name, ErlPath, Args0) -> FullName = full_node_name(Name), - CmdLine = mk_node_cmdline(Name, ErlPath, Args), - io:format("Starting node ~p: ~s~n", [FullName, CmdLine]), - case open_port({spawn, CmdLine}, []) of + Args = mk_node_args(Name, Args0), + io:format("Starting node ~p: ~s~n", + [FullName, lists:flatten([[X," "] || X <- [ErlPath|Args]])]), + %io:format("open_port({spawn_executable, ~p}, [{args,~p}])~n",[ErlPath,Args]), + case open_port({spawn_executable, ErlPath}, [{args,Args}]) of Port when is_port(Port) -> unlink(Port), erlang:port_close(Port), @@ -2299,23 +2440,21 @@ stop_node(Node) -> spawn(Node, fun () -> halt() end), receive {nodedown, Node} -> ok end. -mk_node_cmdline(Name, Prog, Args) -> - Static = "-detached -noinput", +mk_node_args(Name, Args) -> Pa = filename:dirname(code:which(?MODULE)), NameSw = case net_kernel:longnames() of - false -> "-sname "; - true -> "-name "; + false -> "-sname"; + true -> "-name"; _ -> exit(not_distributed_node) end, {ok, Pwd} = file:get_cwd(), NameStr = atom_to_list(Name), - Prog ++ " " - ++ Static ++ " " - ++ NameSw ++ " " ++ NameStr ++ " " - ++ "-pa " ++ Pa ++ " " - ++ "-env ERL_CRASH_DUMP " ++ Pwd ++ "/erl_crash_dump." ++ NameStr ++ " " - ++ "-setcookie " ++ atom_to_list(erlang:get_cookie()) - ++ " " ++ Args. + ["-detached", "-noinput", + NameSw, NameStr, + "-pa", Pa, + "-env", "ERL_CRASH_DUMP", Pwd ++ "/erl_crash_dump." ++ NameStr, + "-setcookie", atom_to_list(erlang:get_cookie()) + | Args]. full_node_name(PreName) -> HostSuffix = lists:dropwhile(fun ($@) -> false; (_) -> true end, diff --git a/lib/reltool/test/reltool_server_SUITE_data/dependencies/y-1.0/ebin/y.app b/lib/reltool/test/reltool_server_SUITE_data/dependencies/y-1.0/ebin/y.app index d9dac371d7..39fdabeea4 100644 --- a/lib/reltool/test/reltool_server_SUITE_data/dependencies/y-1.0/ebin/y.app +++ b/lib/reltool/test/reltool_server_SUITE_data/dependencies/y-1.0/ebin/y.app @@ -2,6 +2,6 @@ {application, y, [{description, "Library application in reltool dependency test"}, {vsn, "1.0"}, - {modules, [y1,y2]}, + {modules, [y0,y1,y2]}, {registered, []}, {applications, [kernel, stdlib]}]}. diff --git a/lib/reltool/test/reltool_server_SUITE_data/dependencies/y-1.0/src/y0.erl b/lib/reltool/test/reltool_server_SUITE_data/dependencies/y-1.0/src/y0.erl new file mode 100644 index 0000000000..dc188ba7b6 --- /dev/null +++ b/lib/reltool/test/reltool_server_SUITE_data/dependencies/y-1.0/src/y0.erl @@ -0,0 +1,5 @@ +-module(y0). +-compile(export_all). + +f() -> + ok. diff --git a/lib/reltool/test/reltool_server_SUITE_data/non_standard_vsn_id/b-first/ebin/b.app b/lib/reltool/test/reltool_server_SUITE_data/non_standard_vsn_id/b-first/ebin/b.app new file mode 100644 index 0000000000..55550a8190 --- /dev/null +++ b/lib/reltool/test/reltool_server_SUITE_data/non_standard_vsn_id/b-first/ebin/b.app @@ -0,0 +1,6 @@ +%% -*- erlang -*- +{application, b, + [{description, "Reltool test app for using selected version of app"}, + {vsn, "first"}, + {modules, [b]}, + {applications, [kernel, stdlib]}]}. diff --git a/lib/reltool/test/reltool_server_SUITE_data/non_standard_vsn_id/b-first/src/b.erl b/lib/reltool/test/reltool_server_SUITE_data/non_standard_vsn_id/b-first/src/b.erl new file mode 100644 index 0000000000..a6b4ff1c05 --- /dev/null +++ b/lib/reltool/test/reltool_server_SUITE_data/non_standard_vsn_id/b-first/src/b.erl @@ -0,0 +1,4 @@ +-module(b). +-compile(export_all). + +foo() -> ok. diff --git a/lib/reltool/test/reltool_server_SUITE_data/non_standard_vsn_id/b-second/ebin/b.app b/lib/reltool/test/reltool_server_SUITE_data/non_standard_vsn_id/b-second/ebin/b.app new file mode 100644 index 0000000000..91e1365df7 --- /dev/null +++ b/lib/reltool/test/reltool_server_SUITE_data/non_standard_vsn_id/b-second/ebin/b.app @@ -0,0 +1,6 @@ +%% -*- erlang -*- +{application, b, + [{description, "Reltool test app for using selected version of app"}, + {vsn, "second"}, + {modules, [b]}, + {applications, [kernel, stdlib]}]}. diff --git a/lib/reltool/test/reltool_server_SUITE_data/non_standard_vsn_id/b-second/src/b.erl b/lib/reltool/test/reltool_server_SUITE_data/non_standard_vsn_id/b-second/src/b.erl new file mode 100644 index 0000000000..a6b4ff1c05 --- /dev/null +++ b/lib/reltool/test/reltool_server_SUITE_data/non_standard_vsn_id/b-second/src/b.erl @@ -0,0 +1,4 @@ +-module(b). +-compile(export_all). + +foo() -> ok. |