112
112
-export([mk_relup/3, mk_relup/4, format_error/1, format_warning/1]).
113
113
-include("systools.hrl").
115
-define(R15_SASL_VSN,"2.2").
117
%% For test purposes only - used by kernel, stdlib and sasl tests
118
-export([appup_search_for_version/2]).
115
120
%%-----------------------------------------------------------------
116
121
%% mk_relup(TopRelFile, BaseUpRelDcs, BaseDnRelDcs)
117
122
%% mk_relup(TopRelFile, BaseUpRelDcs, BaseDnRelDcs, Opts) -> Ret
140
145
%% The option `path' sets search path, `silent' suppresses printing of
141
146
%% error messages to the console, `noexec' inhibits the creation of
142
%% the output "relup" file, and restart_emulator ensures that the new
143
%% emulator is restarted (as the final step).
147
%% the output "relup" file, restart_emulator ensures that the new
148
%% emulator is restarted (as the final step), and `warnings_as_errors'
149
%% treats warnings as errors.
144
150
%% ----------------------------------------------------------------
145
151
mk_relup(TopRelFile, BaseUpRelDcs, BaseDnRelDcs) ->
146
152
mk_relup(TopRelFile, BaseUpRelDcs, BaseDnRelDcs, []).
181
202
do_mk_relup(TopRelFile, BaseUpRelDcs, BaseDnRelDcs, Path, Opts) ->
183
case systools_make:get_release(to_list(TopRelFile), Path, ModTest) of
203
case systools_make:get_release(to_list(TopRelFile), Path) of
185
205
%% TopRel = #release
186
206
%% NameVsnApps = [{{Name, Vsn}, #application}]
187
207
{ok, TopRel, NameVsnApps, Ws0} ->
208
case lists:member({warning,missing_sasl},Ws0) of
210
throw({error,?MODULE,{missing_sasl,TopRel}});
189
215
%% TopApps = [#application]
190
216
TopApps = lists:map(fun({_, App}) -> App end, NameVsnApps),
196
222
{Dn, Ws2} = foreach_baserel_dn(TopRel, TopApps, BaseDnRelDcs,
197
223
Path, Opts, Ws1),
198
224
Relup = {TopRel#release.vsn, Up, Dn},
199
write_relup_file(Relup, Opts),
225
case systools_lib:werror(Opts, Ws2) of
229
write_relup_file(Relup, Opts)
200
231
{ok, Relup, ?MODULE, Ws2};
228
259
BaseRelFile = extract_filename(BaseRelDc),
230
{ok, BaseRel} = systools_make:read_release(BaseRelFile, Path),
261
{BaseRel, {BaseNameVsns, BaseApps}, Ws0} =
262
case systools_make:get_release(BaseRelFile, Path) of
263
{ok, BR, NameVsnApps, Warns} ->
264
case lists:member({warning,missing_sasl},Warns) of
266
throw({error,?MODULE,{missing_sasl,BR}});
268
%% NameVsnApps = [{{Name,Vsn},#application}]
269
%% Gives two lists - [{Name,Vsn}] and [#application]
270
{BR,lists:unzip(NameVsnApps),Warns}
233
278
%% BaseRel = #release
237
282
%% application, one for each added applications, and one for
238
283
%% each removed applications.
240
{RUs1, Ws1} = collect_appup_scripts(up, TopApps, BaseRel, Ws, []),
285
{RUs1, Ws1} = collect_appup_scripts(up, TopApps, BaseRel, Ws0++Ws, []),
242
287
{RUs2, Ws2} = create_add_app_scripts(BaseRel, TopRel, RUs1, Ws1),
244
289
{RUs3, Ws3} = create_remove_app_scripts(BaseRel, TopRel, RUs2, Ws2),
247
check_for_emulator_restart(TopRel, BaseRel, RUs3, Ws3, Opts),
251
case systools_make:get_release(BaseRelFile, Path, ModTest) of
252
{ok, _, NameVsnApps, _Warns} ->
253
lists:map(fun({_,App}) -> App end, NameVsnApps);
291
{RUs4, Ws4} = check_for_emulator_restart(TopRel, BaseRel, RUs3, Ws3, Opts),
258
293
case systools_rc:translate_scripts(up, RUs4, TopApps, BaseApps) of
296
{RUs, Ws5} = fix_r15_sasl_upgrade(RUs5,Ws4,BaseNameVsns),
260
298
VDR = {BaseRel#release.vsn,
261
299
extract_description(BaseRelDc), RUs},
262
300
foreach_baserel_up(TopRel, TopApps, BaseRelDcs, Path,
263
Opts, Ws4, [VDR| Acc]);
301
Opts, Ws5, [VDR| Acc]);
276
314
BaseRelFile = extract_filename(BaseRelDc),
278
{ok, BaseRel} = systools_make:read_release(BaseRelFile, Path),
280
%% BaseRel = #release
282
%% RUs = (release upgrade scripts)
284
{RUs1, Ws1} = collect_appup_scripts(dn, TopApps, BaseRel, Ws, []),
288
case systools_make:get_release(BaseRelFile, Path, ModTest) of
316
{BaseRel, BaseApps, Ws0} =
317
case systools_make:get_release(BaseRelFile, Path) of
290
319
%% NameVsnApps = [{{Name, Vsn}, #application}]
291
{ok, _, NameVsnApps, Warns} ->
293
%% NApps = [#application]
294
NApps = lists:map(fun({_,App}) -> App end, NameVsnApps),
295
{NApps, Warns ++ Ws1};
320
{ok, BR, NameVsnApps, Warns} ->
321
case lists:member({warning,missing_sasl},Warns) of
323
throw({error,?MODULE,{missing_sasl,BR}});
325
%% NApps = [#application]
326
NApps = lists:map(fun({_,App}) -> App end, NameVsnApps),
302
{RUs3, Ws3} = create_add_app_scripts(TopRel, BaseRel, RUs2, Ws2),
304
{RUs4, Ws4} = create_remove_app_scripts(TopRel, BaseRel, RUs3, Ws3),
306
{RUs5, Ws5} = check_for_emulator_restart(TopRel, BaseRel,
309
case systools_rc:translate_scripts(dn, RUs5, BaseApps, TopApps) of
333
%% BaseRel = #release
335
%% RUs = (release upgrade scripts)
337
{RUs1, Ws1} = collect_appup_scripts(dn, TopApps, BaseRel, Ws0++Ws, []),
339
{RUs2, Ws2} = create_add_app_scripts(TopRel, BaseRel, RUs1, Ws1),
341
{RUs3, Ws3} = create_remove_app_scripts(TopRel, BaseRel, RUs2, Ws2),
343
{RUs4, Ws4} = check_for_emulator_restart(TopRel, BaseRel, RUs3, Ws3, Opts),
345
case systools_rc:translate_scripts(dn, RUs4, BaseApps, TopApps) of
311
347
VDR = {BaseRel#release.vsn,
312
348
extract_description(BaseRelDc), RUs},
313
349
foreach_baserel_dn(TopRel, TopApps, BaseRelDcs, Path,
314
Opts, Ws5, [VDR| Acc]);
350
Opts, Ws4, [VDR| Acc]);
326
362
check_for_emulator_restart(#release{erts_vsn = Vsn1, name = N1},
327
363
#release{erts_vsn = Vsn2, name = N2}, RUs, Ws,
328
_Opts) when Vsn1 /= Vsn2 ->
329
{RUs++[[restart_new_emulator]], [{erts_vsn_changed, {N1, N2}} | Ws]};
364
Opts) when Vsn1 /= Vsn2 ->
365
%% Automatically insert a restart_new_emulator instruction when
366
%% erts version is changed. Also allow extra restart at the end of
367
%% the upgrade if restart_emulator option is given.
368
NewRUs = [[restart_new_emulator]|RUs],
369
NewWs = [{erts_vsn_changed, {{N1,Vsn1}, {N2,Vsn2}}} | Ws],
370
check_for_restart_emulator_opt(NewRUs, NewWs, Opts);
330
371
check_for_emulator_restart(_, _, RUs, Ws, Opts) ->
372
check_for_restart_emulator_opt(RUs, Ws, Opts).
374
check_for_restart_emulator_opt(RUs, Ws, Opts) ->
331
375
case get_opt(restart_emulator, Opts) of
332
true -> {RUs++[[restart_new_emulator]], Ws};
376
true -> {RUs++[[restart_emulator]], Ws};
381
%% Special handling of the upgrade from pre R15 to post R15. In R15,
382
%% upgrade of the emulator was improved by moving the restart of the
383
%% emulator before the rest of the upgrade instructions. However, it
384
%% can only work if the release_handler is already upgraded to a post
385
%% R15 version. If not, the upgrade instructions must be backwards
386
%% compatible - i.e. restart_new_emulator will be the last
387
%% instruction, executed after all code loading, code_change etc.
388
fix_r15_sasl_upgrade([restart_new_emulator | RestRUs]=RUs, Ws, BaseApps) ->
389
case lists:keyfind(sasl,1,BaseApps) of
390
{sasl,Vsn} when Vsn < ?R15_SASL_VSN ->
391
{lists:delete(restart_emulator,RestRUs) ++ [restart_new_emulator],
392
[pre_R15_emulator_upgrade|Ws]};
396
fix_r15_sasl_upgrade(RUs, Ws, _BaseApps) ->
336
400
%% collect_appup_scripts(Mode, TopApps, BaseRel, Ws, RUs) -> {NRUs, NWs}
337
401
%% Mode = up | dn
338
402
%% TopApps = [#application]
370
434
%% ToApps = [#application]
372
436
create_add_app_scripts(FromRel, ToRel, RU0s, W0s) ->
373
AddedNs = [N || {N, _V, _T} <- ToRel#release.applications,
437
AddedNs = [{N, T} || {N, _V, T} <- ToRel#release.applications,
374
438
not lists:keymember(N, 1, FromRel#release.applications)],
375
439
%% io:format("Added apps: ~p~n", [AddedNs]),
376
RUs = [[{add_application, N}] || N <- AddedNs],
440
RUs = [[{add_application, N, T}] || {N, T} <- AddedNs],
377
441
{RUs ++ RU0s, W0s}.
422
486
%% XXX Why is this a warning only?
423
487
[{bad_vsn, {TopVsn, TopApp#application.vsn}}| Ws]
425
case lists:keysearch(BaseVsn, 1, VsnRUs) of
489
case appup_search_for_version(BaseVsn, VsnRUs) of
427
491
{RUs ++ [RU], Ws1};
429
493
throw({error, ?MODULE, {no_relup, FName, TopApp, BaseVsn}})
496
appup_search_for_version(BaseVsn, VsnRUs) ->
497
appup_search_for_version(BaseVsn, length(BaseVsn), VsnRUs).
499
appup_search_for_version(BaseVsn,_,[{BaseVsn,RU}|_]) ->
501
appup_search_for_version(BaseVsn,Size,[{Vsn,RU}|VsnRUs]) when is_binary(Vsn) ->
502
case re:run(BaseVsn,Vsn,[unicode,{capture,first,index}]) of
503
{match,[{0,Size}]} ->
506
appup_search_for_version(BaseVsn,Size,VsnRUs)
508
appup_search_for_version(BaseVsn,Size,[_|VsnRUs]) ->
509
appup_search_for_version(BaseVsn,Size,VsnRUs);
510
appup_search_for_version(_,_,[]) ->
433
516
%% Primitives for the "lists of release names" that we upgrade from
526
609
[App#application.name, App#application.vsn,
527
610
App#application.name, Vsn, File]);
611
format_error({missing_sasl,Release}) ->
612
io_lib:format("No sasl application in release ~p, ~p. Can not be upgraded.",
613
[Release#release.name, Release#release.vsn]);
529
614
format_error(Error) ->
530
615
io:format("~p~n", [Error]).
533
print_warnings(Ws) when is_list(Ws) ->
534
lists:foreach(fun(W) -> print_warning(W) end, Ws);
618
print_warnings(Ws, Opts) when is_list(Ws) ->
619
lists:foreach(fun(W) -> print_warning(W, Opts) end, Ws);
620
print_warnings(W, Opts) ->
621
print_warning(W, Opts).
539
S = format_warning(W),
623
print_warning(W, Opts) ->
624
Prefix = case lists:member(warnings_as_errors, Opts) of
630
S = format_warning(Prefix, W),
540
631
io:format("~s", [S]).
542
format_warning({erts_vsn_changed, {Rel1, Rel2}}) ->
543
io_lib:format("*WARNING* The ERTS version changed between ~p and ~p~n",
545
format_warning(What) ->
546
io_lib:format("*WARNING* ~p~n",[What]).
634
format_warning("*WARNING* ", W).
636
format_warning(Prefix, {erts_vsn_changed, {Rel1, Rel2}}) ->
637
io_lib:format("~sThe ERTS version changed between ~p and ~p~n",
638
[Prefix, Rel1, Rel2]);
639
format_warning(Prefix, What) ->
640
io_lib:format("~s~p~n",[Prefix, What]).
549
643
get_reason({error, {open, _, _}}) -> open;