chore(update_appup): take regexes into account when comparing vsns

This change makes the `update_appup.escript` check whether the new
version of an application (the _current_ one) is already contained in
entries in the _new_ .appup file for that application if such .appup
file contains regexes.

NOTE: this does not cover the case in which we calculate the
difference between _old_ and _new_ appup entries, and those consist of
regexes.  In such case, we would need to check if one regex is
"contained" in the other, which is not currently supported by this
patch.
This commit is contained in:
Thales Macedo Garitezi 2021-12-17 14:48:41 -03:00
parent 5066be2385
commit 3ff6661a58
No known key found for this signature in database
GPG Key ID: DD279F8152A9B6DD
1 changed files with 40 additions and 16 deletions

View File

@ -189,8 +189,11 @@ find_appup_actions(CurrApps, PrevApps) ->
maps:fold( maps:fold(
fun(App, CurrAppIdx, Acc) -> fun(App, CurrAppIdx, Acc) ->
case PrevApps of case PrevApps of
#{App := PrevAppIdx} -> find_appup_actions(App, CurrAppIdx, PrevAppIdx) ++ Acc; #{App := PrevAppIdx} ->
_ -> Acc %% New app, nothing to upgrade here. find_appup_actions(App, CurrAppIdx, PrevAppIdx) ++ Acc;
_ ->
%% New app, nothing to upgrade here.
Acc
end end
end, end,
[], [],
@ -214,10 +217,10 @@ find_appup_actions(App, CurrAppIdx, PrevAppIdx = #app{version = PrevVersion}) ->
%% in their current appup. %% in their current appup.
diff_appup_instructions(ComputedChanges, PresentChanges) -> diff_appup_instructions(ComputedChanges, PresentChanges) ->
lists:foldr( lists:foldr(
fun({Vsn, ComputedActions}, Acc) -> fun({VsnOrRegex, ComputedActions}, Acc) ->
case find_matching_version(Vsn, PresentChanges) of case find_matching_version(VsnOrRegex, PresentChanges) of
undefined -> undefined ->
[{Vsn, ComputedActions} | Acc]; [{VsnOrRegex, ComputedActions} | Acc];
PresentActions -> PresentActions ->
DiffActions = ComputedActions -- PresentActions, DiffActions = ComputedActions -- PresentActions,
case DiffActions of case DiffActions of
@ -225,7 +228,7 @@ diff_appup_instructions(ComputedChanges, PresentChanges) ->
%% no diff %% no diff
Acc; Acc;
_ -> _ ->
[{Vsn, DiffActions} | Acc] [{VsnOrRegex, DiffActions} | Acc]
end end
end end
end, end,
@ -250,8 +253,11 @@ parse_appup_diffs(Upgrade, OldUpgrade, Downgrade, OldDowngrade) ->
end. end.
%% TODO: handle regexes %% TODO: handle regexes
find_matching_version(Vsn, PresentChanges) -> %% Since the first argument may be a regex itself, we would need to
proplists:get_value(Vsn, PresentChanges). %% check if it is "contained" within other regexes inside list of
%% versions in the second argument.
find_matching_version(VsnOrRegex, PresentChanges) ->
proplists:get_value(VsnOrRegex, PresentChanges).
find_old_appup_actions(App, PrevVersion) -> find_old_appup_actions(App, PrevVersion) ->
{Upgrade0, Downgrade0} = {Upgrade0, Downgrade0} =
@ -279,11 +285,11 @@ merge_update_actions(App, Changes, Vsns) ->
lists:map(fun(Ret = {<<".*">>, _}) -> lists:map(fun(Ret = {<<".*">>, _}) ->
Ret; Ret;
({Vsn, Actions}) -> ({Vsn, Actions}) ->
{Vsn, do_merge_update_actions(App, Changes, Actions)} {Vsn, do_merge_update_actions(App, Vsn, Changes, Actions)}
end, end,
Vsns). Vsns).
do_merge_update_actions(App, {New0, Changed0, Deleted0}, OldActions) -> do_merge_update_actions(App, Vsn, {New0, Changed0, Deleted0}, OldActions) ->
AppSpecific = app_specific_actions(App) -- OldActions, AppSpecific = app_specific_actions(App) -- OldActions,
AlreadyHandled = lists:flatten(lists:map(fun process_old_action/1, OldActions)), AlreadyHandled = lists:flatten(lists:map(fun process_old_action/1, OldActions)),
New = New0 -- AlreadyHandled, New = New0 -- AlreadyHandled,
@ -308,14 +314,30 @@ process_old_action(_) ->
[]. [].
ensure_version(Version, OldInstructions) -> ensure_version(Version, OldInstructions) ->
OldVersions = [ensure_string(element(1, I)) || I <- OldInstructions], OldVersions = [element(1, I) || I <- OldInstructions],
case lists:member(Version, OldVersions) of case contains_version(Version, OldVersions) of
false -> false ->
[{Version, []}|OldInstructions]; [{Version, []} | OldInstructions];
_ -> _ ->
OldInstructions OldInstructions
end. end.
contains_version(Needle, Haystack) when is_list(Needle) ->
lists:any(
fun(Regex) when is_binary(Regex) ->
case re:run(Needle, Regex) of
{match, _} ->
true;
nomatch ->
false
end;
(Needle) ->
true;
(_) ->
false
end,
Haystack).
read_appup(File) -> read_appup(File) ->
%% NOTE: appup file is a script, it may contain variables or functions. %% NOTE: appup file is a script, it may contain variables or functions.
case file:script(File, [{'VSN', "VSN"}]) of case file:script(File, [{'VSN', "VSN"}]) of
@ -398,16 +420,18 @@ index_app(AppFile) ->
, modules = Modules , modules = Modules
}}. }}.
diff_app(App, #app{version = NewVersion, modules = NewModules}, #app{version = OldVersion, modules = OldModules}) -> diff_app(App,
#app{version = NewVersion, modules = NewModules},
#app{version = OldVersion, modules = OldModules}) ->
{New, Changed} = {New, Changed} =
maps:fold( fun(Mod, MD5, {New, Changed}) -> maps:fold( fun(Mod, MD5, {New, Changed}) ->
case OldModules of case OldModules of
#{Mod := OldMD5} when MD5 =:= OldMD5 -> #{Mod := OldMD5} when MD5 =:= OldMD5 ->
{New, Changed}; {New, Changed};
#{Mod := _} -> #{Mod := _} ->
{New, [Mod|Changed]}; {New, [Mod | Changed]};
_ -> _ ->
{[Mod|New], Changed} {[Mod | New], Changed}
end end
end end
, {[], []} , {[], []}