Current section

Files

Jump to
geas src geas_patches.hrl
Raw

src/geas_patches.hrl

%%-------------------------------------------------------------------------
%% @doc List currently installed patches
%% @end
%%-------------------------------------------------------------------------
list_installed_patches(undefined) -> [];
list_installed_patches(Current) ->
P = list_potential_patches(Current),
% For each potential patch, see if all updated application are found in lib_dir
A =lists:foldl(fun({L, R}, Acc) ->
case lists:all(fun(X)-> [Nameb, _] = binary:split(list_to_binary(X), <<"-">>, ?SPLIT_OPTS),
Name = list_to_atom(binary_to_list(Nameb)),
code:lib_dir(Name) == filename:join(code:lib_dir(), X)
end , R) of
false -> Acc ;
true -> lists:flatten(Acc ++ [list_to_atom(L)])
end
end, [], P),
lists:flatmap(fun(X) -> [atom_to_list(X)] end, A).
%%-------------------------------------------------------------------------
%% @doc List possible patches for current release
%% @end
%%-------------------------------------------------------------------------
list_potential_patches(Current)
->
S = filename:join([get(geas_cwd),code:priv_dir(geas), "otp_versions.table"]),
list_potential_patches(Current, S).
list_potential_patches(Current, S) ->
O = parse_otp_table(S),
{Poss, _} = lists:partition(fun({L, _R}) ->
% Keep L when not current release
case L of
Current -> false ;
_ -> % Keep L when a patche of current release
lists:prefix(Current, L)
end
end, O),
Poss.
%%-------------------------------------------------------------------------
%% @doc Parse otp_versions.table
%% @end
%%-------------------------------------------------------------------------
parse_otp_table(S)
when is_list(S)
->
{ok, B} = file:read_file(S),
Raw = binary:split(B, <<"\n">>, ?SPLIT_OPTS),
Net = lists:foldl(fun(X, Acc) ->
case X of
<<>> -> [];
_ ->
[N | _] = binary:split(X, <<"#">>,?SPLIT_OPTS),
[L, R] = binary:split(N, <<":">>, ?SPLIT_OPTS),
[_, V] = binary:split(L, <<"-">>, ?SPLIT_OPTS),
P_ = binary:split(R, <<" ">>, ?SPLIT_OPTS),
P = lists:flatmap(fun(Z) -> [erlang:binary_to_list(Z)] end, P_),
Acc ++ [{string:strip(erlang:binary_to_list(V)), P}]
end
end, [], Raw),
Net.
%%-------------------------------------------------------------------------
%% @doc Check if update OTP table is required
%% @note : simply remove file otp_versions.table in geas priv dir.
%% @end
%%-------------------------------------------------------------------------
check_update_otp_table(S) ->
% If required or if file does not exists, download it.
Conf = get_config(),
C1 = filelib:is_regular(S),
C2 = Conf#config.update ,
case ((C1 == false) or (C2 == true)) of
false -> ok ;
true ->
Str = Conf#config.http_opts ,
Opts = convert_str_to_term(Str),
application:start(inets),
application:start(crypto),
application:start(asn1),
application:start(public_key),
application:start(ssl),
update_otp_table(S, Opts)
end.
%%-------------------------------------------------------------------------
%% @doc Update OTP table
%% @end
%%-------------------------------------------------------------------------
update_otp_table(S, Opts)
when is_list(S) ->
try
do_log({notice, httpc, "Trying to update OTP table"}),
ok = httpc:set_options(Opts),
{ok, {{_, 200, _}, _, Body}} =
httpc:request(get, {"https://raw.githubusercontent.com/erlang/otp/master/otp_versions.table", []}, [], []),
ok = file:delete(S),
ok = file:write_file(S, Body),
do_log({notice, httpc, "OTP table was updated"})
catch
_:Err ->
do_log({error, httpc, Err}),
ok
end.
%%-------------------------------------------------------------------------
%% @doc Get recommended patches
%% @end
%%-------------------------------------------------------------------------
get_recommanded_patches(Current) ->
% List all applications used in current global code
C = get(geas_calls),
T = filename:join([get(geas_cwd),code:priv_dir(geas),"mod2app.term"]),
{ok, B} = file:read_file(T),
Term = erlang:binary_to_term(B),
Apps = lists:usort(lists:flatmap(fun({M, _, _}) ->
case lists:keyfind(M, 1, Term) of
false -> [];
{M, A} -> [A];
_ -> []
end
end, C)),
erlang:put(geas_apps, Apps),
log({notice, applications, Apps}),
% List patches higher than current version
S = filename:join([get(geas_cwd),code:priv_dir(geas), "otp_versions.table"]),
check_update_otp_table(S),
Ins = list_installed_patches(Current),
Pot = list_potential_patches(Current, S),
Candidats = lists:usort(lists:flatten(lists:flatmap(fun({P, L}) ->
case lists:member(P, Ins) of
true -> [];
false -> [{P, L}]
end
end , Pot))),
% For each patche, list application(s) that should be upgraded
R = lists:usort(lists:flatmap(fun({P, Al}) ->
%erlang:display({P, Al}),
[lists:usort(lists:flatmap(fun(A) ->
[A_ | _] = re:split(A,"-",[{return, list}]), % string:split available starting 20.0 !
case lists:member(erlang:list_to_atom(A_), Apps) of
false -> [];
true -> log({tip, {recommend, P}, A}),
[P]
end
end, Al))]
end, lists:reverse(Candidats))),
R.