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/systools.hrl | 5 | ||||
-rw-r--r-- | lib/sasl/src/systools_make.erl | 77 | ||||
-rw-r--r-- | lib/sasl/test/systools_SUITE.erl | 157 |
5 files changed, 223 insertions, 44 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/systools.hrl b/lib/sasl/src/systools.hrl index 9a3e98221c..da531dbee5 100644 --- a/lib/sasl/src/systools.hrl +++ b/lib/sasl/src/systools.hrl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2009. All Rights Reserved. +%% Copyright Ericsson AB 1996-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 @@ -60,7 +60,8 @@ %% integer() | infinity. mod = [], %% [] | {Mod, StartArgs}, Mod= atom(), %% StartArgs = list(). - start_phases = [], %% [] | {Phase, PhaseArgs}, Phase = atom(), + start_phases, %% [{Phase, PhaseArgs}] | undefined, + %% Phase = atom(), %% PhaseArgs = list(). dir = "" %% The directory where the .app file was %% found (internal use). diff --git a/lib/sasl/src/systools_make.erl b/lib/sasl/src/systools_make.erl index 12ba2a5476..61e660e918 100644 --- a/lib/sasl/src/systools_make.erl +++ b/lib/sasl/src/systools_make.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2011. All Rights Reserved. +%% Copyright Ericsson AB 1996-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 @@ -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, @@ -1456,15 +1468,18 @@ pack_app(#application{name=Name,vsn=V,id=Id,description=D,modules=M, {applications, App}, {included_applications, Incs}, {env, Env}, - {start_phases, SF}, {maxT, MaxT}, {maxP, MaxP} | - behave(Mod)]}. - + behave([{start_phases,SF},{mod,Mod}])]}. + +behave([{mod,[]}|T]) -> + behave(T); +behave([{start_phases,undefined}|T]) -> + behave(T); +behave([H|T]) -> + [H|behave(T)]; behave([]) -> - []; -behave(Mod) -> - [{mod, Mod}]. + []. %%______________________________________________________________________ %% mandatory modules; this modules must be loaded before processes 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). |