diff options
Diffstat (limited to 'lib/sasl')
-rw-r--r-- | lib/sasl/doc/src/appup.xml | 24 | ||||
-rw-r--r-- | lib/sasl/doc/src/rel.xml | 4 | ||||
-rw-r--r-- | lib/sasl/src/release_handler.erl | 2 | ||||
-rw-r--r-- | lib/sasl/src/systools_make.erl | 60 | ||||
-rw-r--r-- | lib/sasl/test/release_handler_SUITE.erl | 56 | ||||
-rw-r--r-- | lib/sasl/test/systools_SUITE.erl | 157 |
6 files changed, 266 insertions, 37 deletions
diff --git a/lib/sasl/doc/src/appup.xml b/lib/sasl/doc/src/appup.xml index 770b7c2492..bacfaa76ef 100644 --- a/lib/sasl/doc/src/appup.xml +++ b/lib/sasl/doc/src/appup.xml @@ -4,7 +4,7 @@ <fileref> <header> <copyright> - <year>1997</year><year>2011</year> + <year>1997</year><year>2012</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -56,12 +56,20 @@ the application.</p> </item> <item> - <p><c>UpFromVsn = string()</c> is an earlier version of - the application to upgrade from.</p> + <p><c>UpFromVsn = string() | binary()</c> is an earlier + version of the application to upgrade from. If it is a + string, it will be interpreted as a specific version + number. If it is a binary, it will be interpreted as a + regular expression which can match multiple version + numbers.</p> </item> <item> - <p><c>DownToVsn = string()</c> is an earlier version of - the application to downgrade to.</p> + <p><c>DownToVsn = string() | binary()</c> is an earlier + version of the application to downgrade to. If it is a + string, it will be interpreted as a specific version + number. If it is a binary, it will be interpreted as a + regular expression which can match multiple version + numbers.</p> </item> <item> <p><c>Instructions</c> is a list of <em>release upgrade instructions</em>, see below. It is recommended to use @@ -70,6 +78,12 @@ creating the <c>relup</c> file.</p> </item> </list> + <p>In order to avoid duplication of upgrade instructions it is + allowed to use regular expressions to specify the <c>UpFromVsn</c> + and <c>DownToVsn</c>. To be considered a regular expression, the + version identifier must be specified as a binary, e.g.</p> + <code type="none"><<"2\\.1\\.[0-9]+">></code> + <p>will match all versions <c>2.1.x</c>, where x is any number.</p> </section> <section> diff --git a/lib/sasl/doc/src/rel.xml b/lib/sasl/doc/src/rel.xml index 470adf3c03..68ef90330f 100644 --- a/lib/sasl/doc/src/rel.xml +++ b/lib/sasl/doc/src/rel.xml @@ -5,7 +5,7 @@ <header> <copyright> <year>1997</year> - <year>2011</year> + <year>2012</year> <holder>Ericsson AB, All Rights Reserved</holder> </copyright> <legalnotice> @@ -88,7 +88,7 @@ <p>The list must be a subset of the included applications specified in the application resource file (<c>Application.app</c>) and overrides this value. Defaults - to the empty list.</p> + to the same value as in the application resource file.</p> </item> </list> <note> diff --git a/lib/sasl/src/release_handler.erl b/lib/sasl/src/release_handler.erl index 522c7b496b..8d2b9c35d3 100644 --- a/lib/sasl/src/release_handler.erl +++ b/lib/sasl/src/release_handler.erl @@ -1572,7 +1572,7 @@ memlib(_Lib, []) -> false. %% recursively remove file or directory remove_file(File) -> - case file:read_file_info(File) of + case file:read_link_info(File) of {ok, Info} when Info#file_info.type==directory -> case file:list_dir(File) of {ok, Files} -> diff --git a/lib/sasl/src/systools_make.erl b/lib/sasl/src/systools_make.erl index a2ea9a8d7e..61e660e918 100644 --- a/lib/sasl/src/systools_make.erl +++ b/lib/sasl/src/systools_make.erl @@ -375,7 +375,7 @@ get_release1(File, Path, ModTestP, Machine) -> {ok, Release, Warnings1} = read_release(File, Path), {ok, Appls0} = collect_applications(Release, Path), {ok, Appls1} = check_applications(Appls0), - {ok, Appls2} = sort_included_applications(Appls1, Release), % OTP-4121 + {ok, Appls2} = sort_used_and_incl_appls(Appls1, Release), % OTP-4121, OTP-9984 {ok, Warnings2} = check_modules(Appls2, Path, ModTestP, Machine), {ok, Appls} = sort_appls(Appls2), {ok, Release, Appls, Warnings1 ++ Warnings2}. @@ -482,7 +482,7 @@ mandatory_applications([_|Apps],Kernel,Stdlib,Sasl) -> mandatory_applications([],Type,_,_) when Type=/=permanent -> error_mandatory_application(kernel,Type); mandatory_applications([],_,Type,_) when Type=/=permanent -> - error_mandatory_application(sasl,Type); + error_mandatory_application(stdlib,Type); mandatory_applications([],_,_,undefined) -> {ok, [{warning,missing_sasl}]}; mandatory_applications([],_,_,_) -> @@ -842,34 +842,45 @@ undefined_applications(Appls) -> filter(fun(X) -> not member(X, Defined) end, Uses). %%______________________________________________________________________ -%% sort_included_applications(Applications, Release) -> Applications +%% sort_used_and_incl_appls(Applications, Release) -> Applications %% Applications = [{{Name,Vsn},#application}] %% Release = #release{} %% -%% Check that included applications are given in the same order as in -%% the release resource file (.rel). Otherwise load instructions in -%% the boot script, and consequently release upgrade instructions in -%% relup, may end up in the wrong order. +%% OTP-4121, OTP-9984 +%% Check 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_included_applications(Applications, Release) when is_tuple(Release) -> +sort_used_and_incl_appls(Applications, Release) when is_tuple(Release) -> {ok, - sort_included_applications(Applications, Release#release.applications)}; - -sort_included_applications([{Tuple,Appl}|Appls], OrderedAppls) -> - case Appl#application.includes of - Incls when length(Incls)>1 -> - IndexedIncls = find_pos(Incls, OrderedAppls), - SortedIndexedIncls = lists:keysort(1, IndexedIncls), - Incls2 = lists:map(fun({_Index,Name}) -> Name end, - SortedIndexedIncls), - Appl2 = Appl#application{includes=Incls2}, - [{Tuple,Appl2}|sort_included_applications(Appls, OrderedAppls)]; - _Incls -> - [{Tuple,Appl}|sort_included_applications(Appls, OrderedAppls)] - end; -sort_included_applications([], _OrderedAppls) -> + sort_used_and_incl_appls(Applications, Release#release.applications)}; + +sort_used_and_incl_appls([{Tuple,Appl}|Appls], OrderedAppls) -> + Incls2 = + case Appl#application.includes of + Incls when length(Incls)>1 -> + sort_appl_list(Incls, OrderedAppls); + Incls -> + Incls + end, + Uses2 = + case Appl#application.uses of + Uses when length(Uses)>1 -> + sort_appl_list(Uses, OrderedAppls); + Uses -> + Uses + end, + Appl2 = Appl#application{includes=Incls2, uses=Uses2}, + [{Tuple,Appl2}|sort_used_and_incl_appls(Appls, OrderedAppls)]; +sort_used_and_incl_appls([], _OrderedAppls) -> []. +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], OrderedAppls) -> [find_pos(1, Name, OrderedAppls)|find_pos(Incs, OrderedAppls)]; find_pos([], _OrderedAppls) -> @@ -1253,7 +1264,8 @@ sort_appls(Appls) -> {ok, sort_appls(Appls, [], [], [])}. sort_appls([{N, A}|T], Missing, Circular, Visited) -> {Name,_Vsn} = N, - {Uses, T1, NotFnd1} = find_all(Name, A#application.uses, T, Visited, [], []), + {Uses, T1, NotFnd1} = find_all(Name, lists:reverse(A#application.uses), + T, Visited, [], []), {Incs, T2, NotFnd2} = find_all(Name, lists:reverse(A#application.includes), T1, Visited, [], []), Missing1 = NotFnd1 ++ NotFnd2 ++ Missing, diff --git a/lib/sasl/test/release_handler_SUITE.erl b/lib/sasl/test/release_handler_SUITE.erl index ac616dab72..467d1226b3 100644 --- a/lib/sasl/test/release_handler_SUITE.erl +++ b/lib/sasl/test/release_handler_SUITE.erl @@ -59,7 +59,7 @@ win32_cases() -> cases() -> [otp_2740, otp_2760, otp_5761, otp_9402, otp_9417, otp_9395_check_old_code, otp_9395_check_and_purge, - otp_9395_update_many_mods, otp_9395_rm_many_mods, + otp_9395_update_many_mods, otp_9395_rm_many_mods, otp_9864, instructions, eval_appup, eval_appup_with_restart, supervisor_which_children_timeout, release_handler_which_releases, install_release_syntax_check, @@ -1205,6 +1205,60 @@ otp_9395_rm_many_mods(Conf) when is_list(Conf) -> otp_9395_rm_many_mods(cleanup,_Conf) -> stop_node(node_name(otp_9395_rm_many_mods)). +otp_9864(Conf) -> + %% Set some paths + PrivDir = priv_dir(Conf), + Dir = filename:join(PrivDir,"otp_9864"), + RelDir = filename:join(?config(data_dir, Conf), "app1_app2"), + LibDir1 = filename:join(RelDir, "lib1"), + LibDir2 = filename:join(RelDir, "lib2"), + + %% Create the releases + Rel1 = create_and_install_fake_first_release(Dir, + [{app1,"1.0",LibDir1}, + {app2,"1.0",LibDir1}]), + Rel2 = create_fake_upgrade_release(Dir, + "2", + [{app1,"2.0",LibDir2}, + {app2,"1.0",LibDir2}], + {[Rel1],[Rel1],[LibDir1]}), + Rel1Dir = filename:dirname(Rel1), + Rel2Dir = filename:dirname(Rel2), + + %% Start a slave node + {ok, Node} = t_start_node(otp_9864, Rel1, filename:join(Rel1Dir,"sys.config")), + + %% Unpack rel2 (make sure it does not work if an AppDir is bad) + LibDir3 = filename:join(RelDir, "lib3"), + {error, {no_such_directory, _}} = + rpc:call(Node, release_handler, set_unpacked, + [Rel2++".rel", [{app1,"2.0",LibDir2}, {app2,"1.0",LibDir3}]]), + {ok, RelVsn2} = + rpc:call(Node, release_handler, set_unpacked, + [Rel2++".rel", [{app1,"2.0",LibDir2}, {app2,"1.0",LibDir2}]]), + ok = rpc:call(Node, release_handler, install_file, + [RelVsn2, filename:join(Rel2Dir, "relup")]), + ok = rpc:call(Node, release_handler, install_file, + [RelVsn2, filename:join(Rel2Dir, "start.boot")]), + ok = rpc:call(Node, release_handler, install_file, + [RelVsn2, filename:join(Rel2Dir, "sys.config")]), + + %% Install RelVsn2 without {update_paths, true} option + {ok, RelVsn1, []} = + rpc:call(Node, release_handler, install_release, [RelVsn2]), + + %% Install RelVsn1 again + {ok, RelVsn1, []} = + rpc:call(Node, release_handler, install_release, [RelVsn1]), + + TempRel2Dir = filename:join(Dir,"releases/2"), + file:make_symlink(TempRel2Dir, filename:join(TempRel2Dir, "foo_symlink_dir")), + + %% This will fail if symlinks are not handled + ok = rpc:call(Node, release_handler, remove_release, [RelVsn2]), + + ok. + upgrade_supervisor(Conf) when is_list(Conf) -> %% Set some paths diff --git a/lib/sasl/test/systools_SUITE.erl b/lib/sasl/test/systools_SUITE.erl index 4cf7364d74..878d582e6b 100644 --- a/lib/sasl/test/systools_SUITE.erl +++ b/lib/sasl/test/systools_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2011. All Rights Reserved. +%% Copyright Ericsson AB 2012. 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 @@ -45,7 +45,7 @@ abnormal_script/1, src_tests_script/1, crazy_script/1, included_script/1, included_override_script/1, included_fail_script/1, included_bug_script/1, exref_script/1, - otp_3065_circular_dependenies/1]). + otp_3065_circular_dependenies/1, included_and_used_sort_script/1]). -export([tar_options/1, normal_tar/1, no_mod_vsn_tar/1, system_files_tar/1, system_files_tar/2, invalid_system_files_tar/1, invalid_system_files_tar/2, variable_tar/1, @@ -80,7 +80,7 @@ groups() -> no_sasl_script, src_tests_script, crazy_script, included_script, included_override_script, included_fail_script, included_bug_script, exref_script, - otp_3065_circular_dependenies]}, + otp_3065_circular_dependenies, included_and_used_sort_script]}, {tar, [], [tar_options, normal_tar, no_mod_vsn_tar, system_files_tar, invalid_system_files_tar, variable_tar, @@ -500,6 +500,22 @@ crazy_script(Config) when is_list(Config) -> {error, _, {mandatory_app,kernel,load}} = systools:make_script(LatestName3, [silent,{path,P}]), + %% Run with .rel file with non-permanent stdlib + {LatestDir4, LatestName4} = create_script(latest_stdlib_start_type, Config), + ok = file:set_cwd(LatestDir4), + + error = systools:make_script(LatestName4), + {error, _, {mandatory_app,stdlib,load}} = + systools:make_script(LatestName4, [silent,{path,P}]), + + %% Run with .rel file lacking stdlib + {LatestDir5, LatestName5} = create_script(latest_no_stdlib, Config), + ok = file:set_cwd(LatestDir5), + + error = systools:make_script(LatestName5), + {error, _, {missing_mandatory_app,stdlib}} = + systools:make_script(LatestName5, [silent,{path,P}]), + ok = file:set_cwd(OldDir), ok. @@ -600,6 +616,24 @@ otp_3065_circular_dependenies(Config) when is_list(Config) -> ok = file:set_cwd(OldDir), ok. +%% Test sorting of included applications and used applications +included_and_used_sort_script(Config) when is_list(Config) -> + {ok, OldDir} = file:get_cwd(), + {LatestDir1, LatestName1} = create_include_files(sort_apps, Config), + ok = file:set_cwd(LatestDir1), + ok = systools:make_script(LatestName1), + ok = check_include_script(LatestName1, + [t20,t19,t18,t17,t16,t15,t14],[t20,t19,t18,t14]), + + {LatestDir2, LatestName2} = create_include_files(sort_apps_rev, Config), + ok = file:set_cwd(LatestDir2), + ok = systools:make_script(LatestName2), + ok = check_include_script(LatestName2, + [t18,t19,t20,t15,t16,t17,t14],[t18,t19,t20,t14]), + + ok = file:set_cwd(OldDir), + ok. + %% make_script: Check that make_script exref option works. exref_script(Config) when is_list(Config) -> @@ -2026,8 +2060,14 @@ create_script(latest_nokernel,Config) -> Apps = [{db,"2.1"},{fe,"3.1"}], do_create_script(latest_nokernel,Config,"4.4",Apps); create_script(latest_kernel_start_type,Config) -> - Apps = [{kernel,"1.0",load},{db,"2.1"},{fe,"3.1"}], + Apps = [{kernel,"1.0",load},{stdlib,"1.0"},{db,"2.1"},{fe,"3.1"}], do_create_script(latest_kernel_start_type,Config,"4.4",Apps); +create_script(latest_stdlib_start_type,Config) -> + Apps = [{kernel,"1.0"},{stdlib,"1.0",load},{db,"2.1"},{fe,"3.1"}], + do_create_script(latest_stdlib_start_type,Config,"4.4",Apps); +create_script(latest_no_stdlib,Config) -> + Apps = [{kernel,"1.0"},{db,"2.1"},{fe,"3.1"}], + do_create_script(latest_no_stdlib,Config,"4.4",Apps); create_script(latest_app_start_type1,Config) -> Apps = core_apps(current), do_create_script(latest_app_start_type1,Config,current,Apps); @@ -2301,8 +2341,53 @@ create_include_files(otp_3065_circular_dependenies, Config) -> " {chAts, \"1.0\"}, {aa12, \"1.0\"}, \n" " {chTraffic, \"1.0\"}]}.\n", file:write_file(Name ++ ".rel", list_to_binary(Rel)), + {filename:dirname(Name), filename:basename(Name)}; + +create_include_files(sort_apps, Config) -> + PrivDir = ?privdir, + Name = fname(PrivDir, sort_apps), + create_sort_apps(PrivDir), + + Apps = application_controller:which_applications(), + {value,{_,_,KernelVer}} = lists:keysearch(kernel,1,Apps), + {value,{_,_,StdlibVer}} = lists:keysearch(stdlib,1,Apps), + + Rel = "{release, {\"test\",\"R1A\"}, {erts, \"45\"},\n" + " [{kernel, \"" ++ KernelVer ++ "\"}, {stdlib, \"" + ++ StdlibVer ++ "\"},\n" + " {t14, \"1.0\"}, \n" + " {t20, \"1.0\"}, \n" + " {t19, \"1.0\"}, \n" + " {t18, \"1.0\"}, \n" + " {t17, \"1.0\"}, \n" + " {t16, \"1.0\"}, \n" + " {t15, \"1.0\"}]}.\n", + file:write_file(Name ++ ".rel", list_to_binary(Rel)), + {filename:dirname(Name), filename:basename(Name)}; + +create_include_files(sort_apps_rev, Config) -> + PrivDir = ?privdir, + Name = fname(PrivDir, sort_apps_rev), + create_sort_apps(PrivDir), + + Apps = application_controller:which_applications(), + {value,{_,_,KernelVer}} = lists:keysearch(kernel,1,Apps), + {value,{_,_,StdlibVer}} = lists:keysearch(stdlib,1,Apps), + + Rel = "{release, {\"test\",\"R1A\"}, {erts, \"45\"},\n" + " [{kernel, \"" ++ KernelVer ++ "\"}, {stdlib, \"" + ++ StdlibVer ++ "\"},\n" + " {t14, \"1.0\"}, \n" + " {t18, \"1.0\"}, \n" + " {t19, \"1.0\"}, \n" + " {t20, \"1.0\"}, \n" + " {t15, \"1.0\"}, \n" + " {t16, \"1.0\"}, \n" + " {t17, \"1.0\"}]}.\n", + file:write_file(Name ++ ".rel", list_to_binary(Rel)), {filename:dirname(Name), filename:basename(Name)}. + create_apps(Dir) -> T1 = "{application, t1,\n" " [{vsn, \"1.0\"},\n" @@ -2451,6 +2536,70 @@ create_apps_3065(Dir) -> " {registered, []}]}.\n", file:write_file(fname(Dir, 'aa12.app'), list_to_binary(T13)). +create_sort_apps(Dir) -> + T14 = "{application, t14,\n" + " [{vsn, \"1.0\"},\n" + " {description, \"test\"},\n" + " {modules, []},\n" + " {applications, [t18,t20,t19]},\n" + " {included_applications, [t15,t17,t16]},\n" + " {registered, []}]}.\n", + file:write_file(fname(Dir, 't14.app'), list_to_binary(T14)), + + T15 = "{application, t15,\n" + " [{vsn, \"1.0\"},\n" + " {description, \"test\"},\n" + " {modules, []},\n" + " {applications, []},\n" + " {included_applications, []},\n" + " {registered, []}]}.\n", + file:write_file(fname(Dir, 't15.app'), list_to_binary(T15)), + + T16 = "{application, t16,\n" + " [{vsn, \"1.0\"},\n" + " {description, \"test\"},\n" + " {modules, []},\n" + " {applications, []},\n" + " {included_applications, []},\n" + " {registered, []}]}.\n", + file:write_file(fname(Dir, 't16.app'), list_to_binary(T16)), + + T17 = "{application, t17,\n" + " [{vsn, \"1.0\"},\n" + " {description, \"test\"},\n" + " {modules, []},\n" + " {applications, []},\n" + " {included_applications, []},\n" + " {registered, []}]}.\n", + file:write_file(fname(Dir, 't17.app'), list_to_binary(T17)), + + T18 = "{application, t18,\n" + " [{vsn, \"1.0\"},\n" + " {description, \"test\"},\n" + " {modules, []},\n" + " {applications, []},\n" + " {included_applications, []},\n" + " {registered, []}]}.\n", + file:write_file(fname(Dir, 't18.app'), list_to_binary(T18)), + + T19 = "{application, t19,\n" + " [{vsn, \"1.0\"},\n" + " {description, \"test\"},\n" + " {modules, []},\n" + " {applications, []},\n" + " {included_applications, []},\n" + " {registered, []}]}.\n", + file:write_file(fname(Dir, 't19.app'), list_to_binary(T19)), + + T20 = "{application, t20,\n" + " [{vsn, \"1.0\"},\n" + " {description, \"test\"},\n" + " {modules, []},\n" + " {applications, []},\n" + " {included_applications, []},\n" + " {registered, []}]}.\n", + file:write_file(fname(Dir, 't20.app'), list_to_binary(T20)). + fname(N) -> filename:join(N). |