aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/reltool/src/reltool.hrl7
-rw-r--r--lib/reltool/src/reltool_server.erl420
-rw-r--r--lib/reltool/src/reltool_target.erl217
3 files changed, 350 insertions, 294 deletions
diff --git a/lib/reltool/src/reltool.hrl b/lib/reltool/src/reltool.hrl
index d0a4c77657..b3f06e8753 100644
--- a/lib/reltool/src/reltool.hrl
+++ b/lib/reltool/src/reltool.hrl
@@ -177,11 +177,11 @@
sorted_dirs :: [dir()],
vsn :: app_vsn(),
label :: app_label(),
- info :: #app_info{} | undefined,
+ info :: #app_info{} | undefined,
mods :: [#mod{}],
%% Static source cond
- mod_cond :: mod_cond() | undefined,
+ mod_cond :: mod_cond() | undefined,
incl_cond :: incl_cond() | undefined,
%% Static target cond
@@ -201,7 +201,8 @@
uses_apps :: [app_name()],
used_by_apps :: [app_name()],
is_pre_included :: boolean(),
- is_included :: boolean()
+ is_included :: boolean(),
+ rels :: [rel_name()]
}).
-record(rel_app,
diff --git a/lib/reltool/src/reltool_server.erl b/lib/reltool/src/reltool_server.erl
index a9985677ba..6a3122f879 100644
--- a/lib/reltool/src/reltool_server.erl
+++ b/lib/reltool/src/reltool_server.erl
@@ -138,11 +138,12 @@ do_init(Options) ->
proc_lib:init_ack(ParentPid,
{ok, self(), C, Sys#sys{apps = undefined}}),
{S2, Status2} = refresh(S, true, Status),
- {S3, Status3} = analyse(S2#state{old_sys = S2#state.sys}, Status2),
- case Status3 of
- {ok, _Warnings} ->
- loop(S3#state{status = Status3, old_status = {ok, []}});
- {error, Reason} ->
+ {S3, Status3} =
+ analyse(S2#state{old_sys = S2#state.sys}, Status2),
+ case Status3 of
+ {ok, _Warnings} -> % BUGBUG: handle warnings
+ loop(S3#state{status = Status3, old_status = {ok, []}});
+ {error, Reason} ->
exit(Reason)
end
end.
@@ -161,33 +162,27 @@ parse_options(Opts) ->
rels = reltool_utils:default_rels(),
emu_name = ?DEFAULT_EMU_NAME,
profile = ?DEFAULT_PROFILE,
- incl_sys_filters =
- reltool_utils:decode_regexps(incl_sys_filters,
- ?DEFAULT_INCL_SYS_FILTERS,
- []),
- excl_sys_filters =
- reltool_utils:decode_regexps(excl_sys_filters,
- ?DEFAULT_EXCL_SYS_FILTERS,
- []),
- incl_app_filters =
- reltool_utils:decode_regexps(incl_app_filters,
- ?DEFAULT_INCL_APP_FILTERS,
- []),
- excl_app_filters =
- reltool_utils:decode_regexps(excl_app_filters,
- ?DEFAULT_EXCL_APP_FILTERS,
- []),
+ incl_sys_filters = dec_re(incl_sys_filters,
+ ?DEFAULT_INCL_SYS_FILTERS,
+ []),
+ excl_sys_filters = dec_re(excl_sys_filters,
+ ?DEFAULT_EXCL_SYS_FILTERS,
+ []),
+ incl_app_filters = dec_re(incl_app_filters,
+ ?DEFAULT_INCL_APP_FILTERS,
+ []),
+ excl_app_filters = dec_re(excl_app_filters,
+ ?DEFAULT_EXCL_APP_FILTERS,
+ []),
relocatable = ?DEFAULT_RELOCATABLE,
app_type = ?DEFAULT_APP_TYPE,
app_file = ?DEFAULT_APP_FILE,
- incl_archive_filters =
- reltool_utils:decode_regexps(incl_archive_filters,
- ?DEFAULT_INCL_ARCHIVE_FILTERS,
- []),
- excl_archive_filters =
- reltool_utils:decode_regexps(excl_archive_filters,
- ?DEFAULT_EXCL_ARCHIVE_FILTERS,
- []),
+ incl_archive_filters = dec_re(incl_archive_filters,
+ ?DEFAULT_INCL_ARCHIVE_FILTERS,
+ []),
+ excl_archive_filters = dec_re(excl_archive_filters,
+ ?DEFAULT_EXCL_ARCHIVE_FILTERS,
+ []),
archive_opts = ?DEFAULT_ARCHIVE_OPTS,
debug_info = ?DEFAULT_DEBUG_INFO},
C2 = #common{sys_debug = [],
@@ -199,6 +194,9 @@ parse_options(Opts) ->
S = #state{options = Opts},
parse_options(Opts, S, C2, Sys, {ok, []}).
+dec_re(Key, Regexps, _Old) ->
+ reltool_utils:decode_regexps(Key, Regexps, _Old).
+
parse_options([{Key, Val} | KeyVals], S, C, Sys, Status) ->
case Key of
parent ->
@@ -261,6 +259,7 @@ loop(#state{common = C, sys = Sys} = S) ->
{ok, _Warnings} ->
S5#state{status = Status3, old_status = S#state.status};
{error, _} ->
+ %% Keep old state
S
end,
reltool_utils:reply(ReplyTo, Ref, Status3),
@@ -277,9 +276,9 @@ loop(#state{common = C, sys = Sys} = S) ->
Reply =
case lists:keysearch(RelName, #rel.name, Sys#sys.rels) of
{value, Rel} ->
- {ok, reltool_target:gen_rel(Rel, Sys)};
+ reltool_target:gen_rel(Rel, Sys);
false ->
- {error, "No such release"}
+ {error, "No such release: " ++ RelName}
end,
reltool_utils:reply(ReplyTo, Ref, Reply),
?MODULE:loop(S);
@@ -292,7 +291,7 @@ loop(#state{common = C, sys = Sys} = S) ->
Vars = [],
reltool_target:gen_script(Rel, Sys, PathFlag, Vars);
false ->
- {error, "No such release"}
+ {error, "No such release: " ++ RelName}
end,
reltool_utils:reply(ReplyTo, Ref, Reply),
?MODULE:loop(S);
@@ -312,7 +311,8 @@ loop(#state{common = C, sys = Sys} = S) ->
{value, App} ->
{ok, App};
false ->
- {error, enoent}
+ {error, "No such application: " ++
+ atom_to_list(AppName)}
end,
reltool_utils:reply(ReplyTo, Ref, Reply),
?MODULE:loop(S);
@@ -327,6 +327,7 @@ loop(#state{common = C, sys = Sys} = S) ->
reltool_utils:reply(ReplyTo, Ref, {ok, App2, Warnings}),
?MODULE:loop(S3);
{error, Reason} ->
+ %% Keep old state
reltool_utils:reply(ReplyTo, Ref, {error, Reason}),
?MODULE:loop(S)
end;
@@ -372,16 +373,20 @@ loop(#state{common = C, sys = Sys} = S) ->
(Sys2#sys.lib_dirs =/= Sys#sys.lib_dirs) orelse
(Sys2#sys.escripts =/= Sys#sys.escripts),
{S3, Status} = refresh(S2, Force, {ok, []}),
- {S4, Status2} = analyse(S3#state{old_sys = S#state.sys}, Status),
- S6 =
- case Status2 of
- {ok, _Warnings} ->
- S4#state{status = Status2, old_status = S#state.status};
- {error, _} ->
- S
- end,
- reltool_utils:reply(ReplyTo, Ref, Status2),
- ?MODULE:loop(S6);
+ {S4, Status2} =
+ analyse(S3#state{old_sys = S#state.sys}, Status),
+ {S5, Status3} =
+ case Status2 of
+ {ok, _Warnings} -> % BUGBUG: handle warnings
+ {S4#state{status = Status2,
+ old_status = S#state.status},
+ Status2};
+ {error, _} ->
+ %% Keep old state
+ {S, Status2}
+ end,
+ reltool_utils:reply(ReplyTo, Ref, Status3),
+ ?MODULE:loop(S5);
{call, ReplyTo, Ref, get_status} ->
reltool_utils:reply(ReplyTo, Ref, S#state.status),
?MODULE:loop(S);
@@ -427,7 +432,9 @@ do_set_app(#state{sys = Sys} = S, App, Status) ->
Sys2 = Sys#sys{apps = Apps2, escripts = Escripts},
{S#state{sys = Sys2}, Status2}.
-analyse(#state{common = C, sys = #sys{apps = Apps0} = Sys} = S, Status) ->
+analyse(#state{common = C,
+ sys = #sys{apps = Apps0, rels = Rels} = Sys} = S,
+ Status) ->
Apps = lists:keydelete(?MISSING_APP, #app.name, Apps0),
ets:delete_all_objects(C#common.app_tab),
ets:delete_all_objects(C#common.mod_tab),
@@ -435,7 +442,13 @@ analyse(#state{common = C, sys = #sys{apps = Apps0} = Sys} = S, Status) ->
MissingApp = default_app(?MISSING_APP, "missing"),
ets:insert(C#common.app_tab, MissingApp),
- Apps2 = lists:map(fun(App) -> app_init_is_included(C, Sys, App) end, Apps),
+ RelApps = apps_in_rels(Rels),
+ {Apps2, Status2} =
+ lists:mapfoldl(fun(App, Acc) ->
+ app_init_is_included(C, Sys, App, RelApps, Acc)
+ end,
+ Status,
+ Apps),
Apps3 =
case app_propagate_is_included(C, Sys, Apps2, []) of
[] ->
@@ -454,15 +467,23 @@ analyse(#state{common = C, sys = #sys{apps = Apps0} = Sys} = S, Status) ->
%% io:format("Missing app: ~p\n",
%% [lists:keysearch(?MISSING_APP, #app.name, Apps4)]),
Sys2 = Sys#sys{apps = Apps4},
- try
- Status2 = verify_config(Sys2, Status),
- {S#state{sys = Sys2}, Status2}
- catch
- throw:{error, Status3} ->
+ case verify_config(Sys2, Status2) of
+ {ok, _Warnings} = Status3 ->
+ {S#state{sys = Sys2}, Status3};
+ {error, _} = Status3 ->
{S, Status3}
end.
-app_init_is_included(C, Sys, #app{mods = Mods} = A) ->
+apps_in_rels(Rels) ->
+ [{RelName, AppName} || #rel{name = RelName, rel_apps = RelApps} <- Rels,
+ RA <- RelApps,
+ AppName <- [RA#rel_app.name | RA#rel_app.incl_apps]].
+
+app_init_is_included(C,
+ Sys,
+ #app{name = AppName, mods = Mods} = A,
+ RelApps,
+ Status) ->
AppCond =
case A#app.incl_cond of
undefined -> Sys#sys.incl_cond;
@@ -473,24 +494,37 @@ app_init_is_included(C, Sys, #app{mods = Mods} = A) ->
undefined -> Sys#sys.mod_cond;
_ -> A#app.mod_cond
end,
- IsIncl =
- case AppCond of
- include -> true;
- exclude -> false;
- derived -> undefined
+ Rels = [RelName || {RelName, AN} <- RelApps, AN =:= AppName],
+ {Default, IsPreIncl, IsIncl, Status2} =
+ case {AppCond, Rels} of
+ {include, _} ->
+ {undefined, true, true, Status};
+ {exclude, []} ->
+ {undefined, false, false, Status};
+ {exclude, [RelName | _]} -> % App is included in at least one rel
+ Text = lists:concat(["Application ", AppName, " is used "
+ "in release ", RelName, " and cannot "
+ "be excluded"]),
+ TmpStatus = reltool_utils:return_first_error(Status, Text),
+ {undefined, false, false, TmpStatus};
+ {derived, []} ->
+ {undefined, undefined, undefined, Status};
+ {derived, [_ | _]} -> % App is included in at least one rel
+ {true, undefined, true, Status}
end,
- A2 = A#app{is_pre_included = IsIncl, is_included = IsIncl},
+ A2 = A#app{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,
- undefined)
+ Default)
end,
Mods),
- %%app_mod_init_is_included(C, AppName, Info, ModCond, AppCond),
- A2.
+ {A2, Status2}.
mod_init_is_included(C, M, ModCond, AppCond, Default) ->
%% print(M#mod.name, hipe, "incl_cond -> ~p\n", [AppCond]),
@@ -862,11 +896,15 @@ read_app_info(AppFileOrBin, AppFile, AppName, DefaultVsn, Status) ->
parse_app_info(AppFile, Info, AI, Status);
{ok, _BadApp} ->
Text = lists:concat([AppName,
- ": Illegal contents in app file ", AppFile]),
+ ": Illegal contents in app file ", AppFile,
+ ", application tuple with arity 3 expected."]),
{missing_app_info(DefaultVsn),
reltool_utils:add_warning(Status, Text)};
- {error, Text} when Text =:= EnoentText->
- {missing_app_info(DefaultVsn), Status};
+ {error, Text} when Text =:= EnoentText ->
+ Text2 = lists:concat([AppName,
+ ": Missing app file ", AppFile, "."]),
+ {missing_app_info(DefaultVsn),
+ reltool_utils:add_warning(Status, Text2)};
{error, Text} ->
Text2 = lists:concat([AppName,
": Cannot parse app file ",
@@ -1045,7 +1083,7 @@ do_get_config(S, InclDef, InclDeriv) ->
false -> shrink_sys(S);
true -> S
end,
- {ok, reltool_target:gen_config(S2#state.sys, InclDef)}.
+ reltool_target:gen_config(S2#state.sys, InclDef).
do_save_config(S, Filename, InclDef, InclDeriv) ->
{ok, Config} = do_get_config(S, InclDef, InclDeriv),
@@ -1072,6 +1110,7 @@ do_load_config(S, SysConfig) ->
{ok, _Warnings2} ->
S3#state{status = Status3, old_status = S#state.status};
{error, _} ->
+ %% Keep old state
S
end,
{S4, Status3};
@@ -1099,24 +1138,30 @@ read_config(OldSys, Filename, Status) when is_list(Filename) ->
end;
read_config(OldSys, {sys, KeyVals}, Status) ->
{NewSys, Status2} =
- try
- decode(OldSys#sys{apps = [], rels = []}, KeyVals, Status)
- catch
- throw:{error, Text} ->
- {OldSys, reltool_utils:return_first_error(Status, Text)}
- end,
- Apps = [A#app{mods = lists:sort(A#app.mods)} || A <- NewSys#sys.apps],
- case NewSys#sys.rels of
- [] -> Rels = reltool_utils:default_rels();
- Rels -> ok
- end,
- NewSys2 = NewSys#sys{apps = lists:sort(Apps), rels = lists:sort(Rels)},
- case lists:keysearch(NewSys2#sys.boot_rel, #rel.name, NewSys2#sys.rels) of
- {value, _} ->
- {NewSys2, Status2};
- false ->
- Text2 = "Missing rel: " ++ NewSys2#sys.boot_rel,
- {OldSys, reltool_utils:return_first_error(Status2, Text2)}
+ decode(OldSys#sys{apps = [], rels = []}, KeyVals, Status),
+ case Status2 of
+ {ok, _Warnings} -> % BUGBUG: handle warnings
+ Apps = [A#app{mods = lists:sort(A#app.mods)} ||
+ A <- NewSys#sys.apps],
+ case NewSys#sys.rels of
+ [] -> Rels = reltool_utils:default_rels();
+ Rels -> ok
+ end,
+ NewSys2 = NewSys#sys{apps = lists:sort(Apps),
+ rels = lists:sort(Rels)},
+ case lists:keysearch(NewSys2#sys.boot_rel,
+ #rel.name,
+ NewSys2#sys.rels) of
+ {value, _} ->
+ {NewSys2, Status2};
+ false ->
+ Text2 = lists:concat(["Release " ++ NewSys2#sys.boot_rel,
+ " is mandatory (used as boot_rel)"]),
+ {OldSys, reltool_utils:return_first_error(Status2, Text2)}
+ end;
+ {error, _} ->
+ %% Keep old state
+ {OldSys, Status2}
end;
read_config(OldSys, BadConfig, Status) ->
Text = lists:flatten(io_lib:format("~p", [BadConfig])),
@@ -1175,96 +1220,78 @@ decode(#sys{} = Sys, [{Key, Val} | KeyVals], Status) ->
profile when Val =:= development ->
Val = ?DEFAULT_PROFILE, % assert,
{Sys#sys{profile = Val,
- incl_sys_filters =
- reltool_utils:decode_regexps(incl_sys_filters,
- ?DEFAULT_INCL_SYS_FILTERS,
- Sys#sys.incl_sys_filters),
- excl_sys_filters =
- reltool_utils:decode_regexps(excl_sys_filters,
- ?DEFAULT_EXCL_SYS_FILTERS,
- Sys#sys.excl_sys_filters),
- incl_app_filters =
- reltool_utils:decode_regexps(incl_app_filters,
- ?DEFAULT_INCL_APP_FILTERS,
- Sys#sys.incl_app_filters),
- excl_app_filters =
- reltool_utils:decode_regexps(excl_app_filters,
- ?DEFAULT_EXCL_APP_FILTERS,
- Sys#sys.excl_app_filters)},
+ incl_sys_filters = dec_re(incl_sys_filters,
+ ?DEFAULT_INCL_SYS_FILTERS,
+ Sys#sys.incl_sys_filters),
+ excl_sys_filters = dec_re(excl_sys_filters,
+ ?DEFAULT_EXCL_SYS_FILTERS,
+ Sys#sys.excl_sys_filters),
+ incl_app_filters = dec_re(incl_app_filters,
+ ?DEFAULT_INCL_APP_FILTERS,
+ Sys#sys.incl_app_filters),
+ excl_app_filters = dec_re(excl_app_filters,
+ ?DEFAULT_EXCL_APP_FILTERS,
+ Sys#sys.excl_app_filters)},
Status};
profile when Val =:= embedded ->
{Sys#sys{profile = Val,
- incl_sys_filters =
- reltool_utils:decode_regexps(incl_sys_filters,
- ?EMBEDDED_INCL_SYS_FILTERS,
- Sys#sys.incl_sys_filters),
- excl_sys_filters =
- reltool_utils:decode_regexps(excl_sys_filters,
- ?EMBEDDED_EXCL_SYS_FILTERS,
- Sys#sys.excl_sys_filters),
- incl_app_filters =
- reltool_utils:decode_regexps(incl_app_filters,
- ?EMBEDDED_INCL_APP_FILTERS,
- Sys#sys.incl_app_filters),
- excl_app_filters =
- reltool_utils:decode_regexps(excl_app_filters,
- ?EMBEDDED_EXCL_APP_FILTERS,
- Sys#sys.excl_app_filters)},
+ incl_sys_filters = dec_re(incl_sys_filters,
+ ?EMBEDDED_INCL_SYS_FILTERS,
+ Sys#sys.incl_sys_filters),
+ excl_sys_filters = dec_re(excl_sys_filters,
+ ?EMBEDDED_EXCL_SYS_FILTERS,
+ Sys#sys.excl_sys_filters),
+ incl_app_filters = dec_re(incl_app_filters,
+ ?EMBEDDED_INCL_APP_FILTERS,
+ Sys#sys.incl_app_filters),
+ excl_app_filters = dec_re(excl_app_filters,
+ ?EMBEDDED_EXCL_APP_FILTERS,
+ Sys#sys.excl_app_filters)},
Status};
profile when Val =:= standalone ->
{Sys#sys{profile = Val,
- incl_sys_filters =
- reltool_utils:decode_regexps(incl_sys_filters,
- ?STANDALONE_INCL_SYS_FILTERS,
- Sys#sys.incl_sys_filters),
- excl_sys_filters =
- reltool_utils:decode_regexps(excl_sys_filters,
- ?STANDALONE_EXCL_SYS_FILTERS,
- Sys#sys.excl_sys_filters),
- incl_app_filters =
- reltool_utils:decode_regexps(incl_app_filters,
- ?STANDALONE_INCL_APP_FILTERS,
- Sys#sys.incl_app_filters),
- excl_app_filters =
- reltool_utils:decode_regexps(excl_app_filters,
- ?STANDALONE_EXCL_APP_FILTERS,
- Sys#sys.excl_app_filters)},
+ incl_sys_filters = dec_re(incl_sys_filters,
+ ?STANDALONE_INCL_SYS_FILTERS,
+ Sys#sys.incl_sys_filters),
+ excl_sys_filters = dec_re(excl_sys_filters,
+ ?STANDALONE_EXCL_SYS_FILTERS,
+ Sys#sys.excl_sys_filters),
+ incl_app_filters = dec_re(incl_app_filters,
+ ?STANDALONE_INCL_APP_FILTERS,
+ Sys#sys.incl_app_filters),
+ excl_app_filters = dec_re(excl_app_filters,
+ ?STANDALONE_EXCL_APP_FILTERS,
+ Sys#sys.excl_app_filters)},
Status};
incl_sys_filters ->
- {Sys#sys{incl_sys_filters =
- reltool_utils:decode_regexps(Key,
- Val,
- Sys#sys.incl_sys_filters)},
+ {Sys#sys{incl_sys_filters = dec_re(Key,
+ Val,
+ Sys#sys.incl_sys_filters)},
Status};
excl_sys_filters ->
- {Sys#sys{excl_sys_filters =
- reltool_utils:decode_regexps(Key,
- Val,
- Sys#sys.excl_sys_filters)},
+ {Sys#sys{excl_sys_filters = dec_re(Key,
+ Val,
+ Sys#sys.excl_sys_filters)},
Status};
incl_app_filters ->
- {Sys#sys{incl_app_filters =
- reltool_utils:decode_regexps(Key,
- Val,
- Sys#sys.incl_app_filters)},
+ {Sys#sys{incl_app_filters = dec_re(Key,
+ Val,
+ Sys#sys.incl_app_filters)},
Status};
excl_app_filters ->
- {Sys#sys{excl_app_filters =
- reltool_utils:decode_regexps(Key,
- Val,
- Sys#sys.excl_app_filters)},
+ {Sys#sys{excl_app_filters = dec_re(Key,
+ Val,
+ Sys#sys.excl_app_filters)},
Status};
incl_archive_filters ->
- {Sys#sys{incl_archive_filters =
- reltool_utils:decode_regexps(Key,
- Val,
- Sys#sys.incl_archive_filters)},
+ {Sys#sys{incl_archive_filters = dec_re(Key,
+ Val,
+ Sys#sys.incl_archive_filters)},
Status};
excl_archive_filters ->
- {Sys#sys{excl_archive_filters =
- reltool_utils:decode_regexps(Key,
- Val,
- Sys#sys.excl_archive_filters)},
+ {Sys#sys{excl_archive_filters = dec_re(Key,
+ Val,
+ Sys#sys.excl_archive_filters)},
Status};
archive_opts when is_list(Val) ->
{Sys#sys{archive_opts = Val}, Status};
@@ -1304,7 +1331,7 @@ decode(#app{} = App, [{Key, Val} | KeyVals], Status) ->
Val =:= strip ->
{App#app{debug_info = Val}, Status};
app_file when Val =:= keep;
- Val =:= strip,
+ Val =:= strip;
Val =:= all ->
{App#app{app_file = Val}, Status};
app_type when Val =:= permanent;
@@ -1314,28 +1341,24 @@ decode(#app{} = App, [{Key, Val} | KeyVals], Status) ->
Val =:= none ->
{App#app{app_type = Val}, Status};
incl_app_filters ->
- {App#app{incl_app_filters =
- reltool_utils:decode_regexps(Key,
- Val,
- App#app.incl_app_filters)},
+ {App#app{incl_app_filters = dec_re(Key,
+ Val,
+ App#app.incl_app_filters)},
Status};
excl_app_filters ->
- {App#app{excl_app_filters =
- reltool_utils:decode_regexps(Key,
- Val,
- App#app.excl_app_filters)},
+ {App#app{excl_app_filters = dec_re(Key,
+ Val,
+ App#app.excl_app_filters)},
Status};
incl_archive_filters ->
- {App#app{incl_archive_filters =
- reltool_utils:decode_regexps(Key,
- Val,
- App#app.incl_archive_filters)},
+ {App#app{incl_archive_filters = dec_re(Key,
+ Val,
+ App#app.incl_archive_filters)},
Status};
excl_archive_filters ->
- {App#app{excl_archive_filters =
- reltool_utils:decode_regexps(Key,
- Val,
- App#app.excl_archive_filters)},
+ {App#app{excl_archive_filters = dec_re(Key,
+ Val,
+ App#app.excl_archive_filters)},
Status};
archive_opts when is_list(Val) ->
{App#app{archive_opts = Val}, Status};
@@ -1443,51 +1466,49 @@ merge_config(OldSys, NewSys, Force, Status) ->
verify_config(Sys, Status) ->
case lists:keymember(Sys#sys.boot_rel, #rel.name, Sys#sys.rels) of
true ->
- lists:foreach(fun(Rel)-> check_rel(Rel, Sys, Status) end,
- Sys#sys.rels),
- Status;
+ lists:foldl(fun(Rel, Acc)-> check_rel(Rel, Sys, Acc) end,
+ Status,
+ Sys#sys.rels);
false ->
- Text = lists:concat([Sys#sys.boot_rel, ": release is mandatory"]),
- Status2 = reltool_utils:return_first_error(Status, Text),
- throw({error, Status2})
+ Text = lists:concat(["Release ", Sys#sys.boot_rel,
+ " is mandatory (used as boot_rel)"]),
+ reltool_utils:return_first_error(Status, Text)
end.
check_rel(#rel{name = RelName, rel_apps = RelApps},
#sys{apps = Apps},
Status) ->
EnsureApp =
- fun(AppName) ->
+ fun(AppName, Acc) ->
case lists:keymember(AppName, #rel_app.name, RelApps) of
true ->
- ok;
+ Acc;
false ->
- Text = lists:concat([RelName, ": ", AppName,
- " is not included."]),
- Status2 =
- reltool_utils:return_first_error(Status, Text),
- throw({error, Status2})
+ Text = lists:concat(["Mandatory application ",
+ AppName,
+ " is not included in release ",
+ RelName]),
+ reltool_utils:return_first_error(Acc, Text)
end
end,
- EnsureApp(kernel),
- EnsureApp(stdlib),
+ Mandatory = [kernel, stdlib],
+ Status2 = lists:foldl(EnsureApp, Status, Mandatory),
CheckRelApp =
- fun(#rel_app{name = AppName}) ->
+ fun(#rel_app{name = AppName}, Acc) ->
case lists:keysearch(AppName, #app.name, Apps) of
{value, App} when App#app.is_pre_included ->
- ok;
+ Acc;
{value, App} when App#app.is_included ->
- ok;
+ Acc;
_ ->
- Text =
- lists:concat([RelName, ": uses application ",
- AppName, " that not is included."]),
- Status2 =
- reltool_utils:return_first_error(Status, Text),
- %% throw BUGBUG: add throw
- ({error, Status2})
+ Text = lists:concat(["Release ", RelName,
+ " uses non included application ",
+ AppName]),
+
+ reltool_utils:return_first_error(Acc, Text)
end
end,
- lists:foreach(CheckRelApp, RelApps).
+ lists:foldl(CheckRelApp, Status2, RelApps).
patch_erts_version(RootDir, Apps, Status) ->
AppName = erts,
@@ -1508,7 +1529,7 @@ patch_erts_version(RootDir, Apps, Status) ->
{Apps, Status}
end;
false ->
- Text = "erts cannnot be found in the root directory " ++ RootDir,
+ Text = "erts cannot be found in the root directory " ++ RootDir,
Status2 = reltool_utils:return_first_error(Status, Text),
{Apps, Status2}
end.
@@ -1814,7 +1835,8 @@ default_app(Name) ->
status = missing,
uses_mods = undefined,
is_pre_included = undefined,
- is_included = undefined}.
+ is_included = undefined,
+ rels = undefined}.
%% Assume that the application are sorted
refresh_apps([Old | OldApps], [New | NewApps], Acc, Force, Status)
diff --git a/lib/reltool/src/reltool_target.erl b/lib/reltool/src/reltool_target.erl
index e079a02f3c..a4440f8fb1 100644
--- a/lib/reltool/src/reltool_target.erl
+++ b/lib/reltool/src/reltool_target.erl
@@ -64,36 +64,39 @@ kernel_processes(KernelApp) ->
%% Generate the contents of a config file
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-gen_config(#sys{root_dir = RootDir,
- lib_dirs = LibDirs,
- mod_cond = ModCond,
- incl_cond = AppCond,
- apps = Apps,
- boot_rel = BootRel,
- rels = Rels,
- emu_name = EmuName,
- profile = Profile,
- incl_sys_filters = InclSysFiles,
- excl_sys_filters = ExclSysFiles,
- incl_app_filters = InclAppFiles,
- excl_app_filters = ExclAppFiles,
- incl_archive_filters = InclArchiveDirs,
- excl_archive_filters = ExclArchiveDirs,
- archive_opts = ArchiveOpts,
- relocatable = Relocatable,
- app_type = AppType,
- app_file = AppFile,
- debug_info = DebugInfo},
- InclDefs) ->
+gen_config(Sys, InclDefs) ->
+ {ok, do_gen_config(Sys, InclDefs)}.
+
+do_gen_config(#sys{root_dir = RootDir,
+ lib_dirs = LibDirs,
+ mod_cond = ModCond,
+ incl_cond = AppCond,
+ apps = Apps,
+ boot_rel = BootRel,
+ rels = Rels,
+ emu_name = EmuName,
+ profile = Profile,
+ incl_sys_filters = InclSysFiles,
+ excl_sys_filters = ExclSysFiles,
+ incl_app_filters = InclAppFiles,
+ excl_app_filters = ExclAppFiles,
+ incl_archive_filters = InclArchiveDirs,
+ excl_archive_filters = ExclArchiveDirs,
+ archive_opts = ArchiveOpts,
+ relocatable = Relocatable,
+ app_type = AppType,
+ app_file = AppFile,
+ debug_info = DebugInfo},
+ InclDefs) ->
ErtsItems =
case lists:keysearch(erts, #app.name, Apps) of
{value, Erts} ->
- [{erts, gen_config(Erts, InclDefs)}];
+ [{erts, do_gen_config(Erts, InclDefs)}];
false ->
[]
end,
AppsItems =
- [{app, A#app.name, gen_config(A, InclDefs)}
+ [{app, A#app.name, do_gen_config(A, InclDefs)}
|| A <- Apps,
A#app.name =/= ?MISSING_APP,
A#app.name =/= erts,
@@ -102,16 +105,19 @@ gen_config(#sys{root_dir = RootDir,
EscriptItems = [{escript,
A#app.active_dir,
emit(incl_cond, A#app.incl_cond, undefined, InclDefs)}
- || A <- Apps, A#app.is_escript],
+ || A <- Apps, A#app.is_escript],
DefaultRels = reltool_utils:default_rels(),
RelsItems =
- case {[{rel, R#rel.name, R#rel.vsn, gen_config(R, InclDefs)} ||
- R <- Rels],
- [{rel, R#rel.name, R#rel.vsn, gen_config(R, InclDefs)} ||
- R <- DefaultRels]} of
- {RI, RI} -> [];
- {RI, _} -> RI
- end,
+ [{rel, R#rel.name, R#rel.vsn, do_gen_config(R, InclDefs)} ||
+ R <- Rels],
+ DefaultRelsItems =
+ [{rel, R#rel.name, R#rel.vsn, do_gen_config(R, InclDefs)} ||
+ R <- DefaultRels],
+ RelsItems2 =
+ case InclDefs of
+ true -> RelsItems;
+ false -> RelsItems -- DefaultRelsItems
+ end,
X = fun(List) -> [Re || #regexp{source = Re} <- List] end,
{sys,
emit(root_dir, RootDir, code:root_dir(), InclDefs) ++
@@ -122,7 +128,7 @@ gen_config(#sys{root_dir = RootDir,
ErtsItems ++
AppsItems ++
emit(boot_rel, BootRel, ?DEFAULT_REL_NAME, InclDefs) ++
- RelsItems ++
+ RelsItems2 ++
emit(emu_name, EmuName, ?DEFAULT_EMU_NAME, InclDefs) ++
emit(relocatable, Relocatable, ?DEFAULT_RELOCATABLE, InclDefs) ++
emit(profile, Profile, ?DEFAULT_PROFILE, InclDefs) ++
@@ -136,60 +142,60 @@ gen_config(#sys{root_dir = RootDir,
emit(app_type, AppType, ?DEFAULT_APP_TYPE, InclDefs) ++
emit(app_file, AppFile, ?DEFAULT_APP_FILE, InclDefs) ++
emit(debug_info, DebugInfo, ?DEFAULT_DEBUG_INFO, InclDefs)};
-gen_config(#app{name = _Name,
- mod_cond = ModCond,
- incl_cond = AppCond,
- debug_info = DebugInfo,
- app_file = AppFile,
- incl_app_filters = InclAppFiles,
- excl_app_filters = ExclAppFiles,
- incl_archive_filters = InclArchiveDirs,
- excl_archive_filters = ExclArchiveDirs,
- archive_opts = ArchiveOpts,
- use_selected_vsn = UseSelected,
- vsn = Vsn,
- mods = Mods},
- InclDefs) ->
+do_gen_config(#app{name = _Name,
+ mod_cond = ModCond,
+ incl_cond = AppCond,
+ debug_info = DebugInfo,
+ app_file = AppFile,
+ incl_app_filters = InclAppFiles,
+ excl_app_filters = ExclAppFiles,
+ incl_archive_filters = InclArchiveDirs,
+ excl_archive_filters = ExclArchiveDirs,
+ archive_opts = ArchiveOpts,
+ use_selected_vsn = UseSelected,
+ vsn = Vsn,
+ mods = Mods},
+ InclDefs) ->
emit(mod_cond, ModCond, undefined, InclDefs) ++
- emit(incl_cond, AppCond, undefined, InclDefs) ++
- emit(debug_info, DebugInfo, undefined, InclDefs) ++
- emit(app_file, AppFile, undefined, InclDefs) ++
- emit(incl_app_filters, InclAppFiles, undefined, InclDefs) ++
- emit(excl_app_filters, ExclAppFiles, undefined, InclDefs) ++
- emit(incl_archive_filters, InclArchiveDirs, undefined, InclDefs) ++
- emit(excl_archive_filters, ExclArchiveDirs, undefined, InclDefs) ++
- emit(archive_opts, ArchiveOpts, undefined, InclDefs) ++
- emit(vsn, Vsn, undefined, InclDefs orelse UseSelected =/= true) ++
- [{mod, M#mod.name, gen_config(M, InclDefs)} ||
- M <- Mods,
- M#mod.is_included =:= true];
-gen_config(#mod{name = _Name,
- incl_cond = AppCond,
- debug_info = DebugInfo},
- InclDefs) ->
+ emit(incl_cond, AppCond, undefined, InclDefs) ++
+ emit(debug_info, DebugInfo, undefined, InclDefs) ++
+ emit(app_file, AppFile, undefined, InclDefs) ++
+ emit(incl_app_filters, InclAppFiles, undefined, InclDefs) ++
+ emit(excl_app_filters, ExclAppFiles, undefined, InclDefs) ++
+ emit(incl_archive_filters, InclArchiveDirs, undefined, InclDefs) ++
+ emit(excl_archive_filters, ExclArchiveDirs, undefined, InclDefs) ++
+ emit(archive_opts, ArchiveOpts, undefined, InclDefs) ++
+ emit(vsn, Vsn, undefined, InclDefs orelse UseSelected =/= true) ++
+ [{mod, M#mod.name, do_gen_config(M, InclDefs)} ||
+ M <- Mods,
+ M#mod.is_included =:= true];
+do_gen_config(#mod{name = _Name,
+ incl_cond = AppCond,
+ debug_info = DebugInfo},
+ InclDefs) ->
emit(incl_cond, AppCond, undefined, InclDefs) ++
- emit(debug_info, DebugInfo, undefined, InclDefs);
-gen_config(#rel{name = _Name,
- vsn = _Vsn,
- rel_apps = RelApps},
- InclDefs) ->
- [gen_config(RA, InclDefs) || RA <- RelApps];
-gen_config(#rel_app{name = Name,
- app_type = Type,
- incl_apps = InclApps},
- _InclDefs) ->
+ emit(debug_info, DebugInfo, undefined, InclDefs);
+do_gen_config(#rel{name = _Name,
+ vsn = _Vsn,
+ rel_apps = RelApps},
+ InclDefs) ->
+ [do_gen_config(RA, InclDefs) || RA <- RelApps];
+do_gen_config(#rel_app{name = Name,
+ app_type = Type,
+ incl_apps = InclApps},
+ _InclDefs) ->
case {Type, InclApps} of
{undefined, []} -> Name;
{undefined, _} -> {Name, InclApps};
{_, []} -> {Name, Type};
{_, _} -> {Name, Type, InclApps}
end;
-gen_config({Tag, Val}, InclDefs) ->
+do_gen_config({Tag, Val}, InclDefs) ->
emit(Tag, Val, undefined, InclDefs);
-gen_config([], _InclDefs) ->
+do_gen_config([], _InclDefs) ->
[];
-gen_config([H | T], InclDefs) ->
- lists:flatten([gen_config(H, InclDefs), gen_config(T, InclDefs)]).
+do_gen_config([H | T], InclDefs) ->
+ lists:flatten([do_gen_config(H, InclDefs), do_gen_config(T, InclDefs)]).
emit(Tag, Val, Default, InclDefs) ->
if
@@ -239,13 +245,28 @@ gen_app(#app{name = Name,
%% Generate the contents of a rel file
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-gen_rel(#rel{name = RelName, vsn = RelVsn, rel_apps = RelApps},
- #sys{apps = Apps}) ->
- {value, Erts} = lists:keysearch(erts, #app.name, Apps),
- {release,
- {RelName, RelVsn},
- {erts, Erts#app.vsn},
- [app_to_rel(RA, Apps ) || RA <- RelApps]}.
+gen_rel(Rel, Sys) ->
+ try
+ {ok, do_gen_rel(Rel, Sys)}
+ catch
+ throw:{error, Text} ->
+ {error, Text}
+ end.
+
+do_gen_rel(#rel{name = RelName, vsn = RelVsn, rel_apps = RelApps},
+ #sys{apps = Apps}) ->
+ ErtsName = erts,
+ case lists:keysearch(ErtsName, #app.name, Apps) of
+ {value, Erts} ->
+ {release,
+ {RelName, RelVsn},
+ {erts, Erts#app.vsn},
+ [app_to_rel(RA, Apps ) || RA <- RelApps]};
+ false ->
+ reltool_utils:throw_error("Mandatory application ~p is "
+ "not included",
+ [ErtsName])
+ end.
app_to_rel(#rel_app{name = Name, app_type = Type, incl_apps = InclApps},
Apps) ->
@@ -607,7 +628,7 @@ do_spec_rel_files(#rel{name = Name} = Rel, Sys) ->
RelFile = Name ++ ".rel",
ScriptFile = Name ++ ".script",
BootFile = Name ++ ".boot",
- GenRel = gen_rel(Rel, Sys),
+ GenRel = do_gen_rel(Rel, Sys),
PathFlag = true,
Variables = [],
{ok, Script} = do_gen_script(Rel, Sys, PathFlag, Variables),
@@ -678,7 +699,8 @@ strip_sys_files(Relocatable, SysFiles, Apps, ExclRegexps) ->
true ->
ExtraExcl = ["^erts.*/bin/.*src\$"],
reltool_utils:decode_regexps(excl_sys_filters,
- {add, ExtraExcl}, ExclRegexps);
+ {add, ExtraExcl},
+ ExclRegexps);
false ->
ExclRegexps
end,
@@ -759,18 +781,29 @@ spec_bin_files(Sys, AllSysFiles, StrippedSysFiles, RelFiles, InclRegexps) ->
GoodNames = [F || {copy_file, F} <- OldBinFiles,
not lists:suffix(".boot", F),
not lists:suffix(".script", F)],
- BinFiles2 = [Map(S) || S <- BinFiles, lists:member(element(2, S), GoodNames)],
+ BinFiles2 = [Map(S) || S <- BinFiles,
+ lists:member(element(2, S), GoodNames)],
BootFiles = [F || F <- RelFiles, lists:suffix(".boot", element(2, F))],
- [{write_file, _, BootRel}] = safe_lookup_spec(Sys#sys.boot_rel ++ ".boot", BootFiles),
- BootFiles2 = lists:keystore("start.boot", 2, BootFiles, {write_file, "start.boot", BootRel}),
- MakeRegexp = fun(File) -> "^bin/" ++ element(2, File) ++ "(|.escript)\$" end,
+ [{write_file, _, BootRel}] =
+ safe_lookup_spec(Sys#sys.boot_rel ++ ".boot", BootFiles),
+ BootFiles2 = lists:keystore("start.boot",
+ 2,
+ BootFiles,
+ {write_file, "start.boot", BootRel}),
+ MakeRegexp =
+ fun(File) -> "^bin/" ++ element(2, File) ++ "(|.escript)\$" end,
ExtraIncl = lists:map(MakeRegexp, Escripts),
- InclRegexps2 = reltool_utils:decode_regexps(incl_sys_filters, {add, ExtraIncl}, InclRegexps),
+ InclRegexps2 = reltool_utils:decode_regexps(incl_sys_filters,
+ {add, ExtraIncl},
+ InclRegexps),
{InclRegexps2, Escripts ++ BinFiles2 ++ BootFiles2}.
spec_escripts(#sys{apps = Apps}, ErtsBin, BinFiles) ->
- Filter = fun(#app{is_escript = IsEscript, is_included = IsIncl,
- is_pre_included = IsPre, name = Name, active_dir = File}) ->
+ Filter = fun(#app{is_escript = IsEscript,
+ is_included = IsIncl,
+ is_pre_included = IsPre,
+ name = Name,
+ active_dir = File}) ->
if
Name =:= ?MISSING_APP ->
false;