Current section

Files

Jump to
grisp_tools src grisp_tools_package.erl
Raw

src/grisp_tools_package.erl

-module(grisp_tools_package).
% API
-export([list/1]).
%--- API -----------------------------------------------------------------------
list(#{type := otp, platform := Platform}) ->
list_bucket(iolist_to_binary([[E, <<"/">>] || E <- [
<<"platforms">>,
atom_to_binary(Platform),
<<"otp">>
]])).
%--- Internal ------------------------------------------------------------------
list_bucket(Prefix) ->
Bucket = <<"grisp.s3.amazonaws.com">>,
{ok, Client} = hackney:connect(hackney_ssl, Bucket, 443, [with_body]),
list_bucket(Client, Prefix, undefined, []).
list_bucket(Client, Prefix, Token, Items) ->
TokenQS = [{<<"continuation-token">>, Token} || Token =/= undefined],
URL = hackney_url:make_url(<<>>, <<"">>, [
{<<"list-type">>, <<"2">>},
{<<"max-keys">>, <<"100">>},
{<<"prefix">>, Prefix}
] ++ TokenQS),
Request = {get, URL, [], <<>>},
{ok, 200, _Headers, Body} = hackney:send_request(Client, Request),
XML = decode(Body),
Contents = xpath(XML, "/ListBucketResult/Contents/Key/child::text()"),
Packages = simplify(Contents),
case continue(XML) of
eof ->
hackney:close(Client),
lists:sort(fun version_sort/2, [
clean(Prefix, P)
||
P <- Packages ++ Items, P =/= binary_to_list(Prefix)
]);
{continue, NewToken} ->
list_bucket(Client, Prefix, NewToken, Packages ++ Items)
end.
continue(Response) ->
Path = "/ListBucketResult/NextContinuationToken/child::text()",
case simplify(xpath(Response, Path)) of
[] -> eof;
[Token] -> {continue, Token}
end.
decode(Bin) ->
{XML, _Rest} = xmerl_scan:string(binary_to_list(Bin), [{space, normalize}]),
[Clean] = xmerl_lib:remove_whitespace([XML]),
Clean.
simplify(Elements) when is_list(Elements) -> [simplify(E) || E <- Elements];
simplify(XML) -> xmerl_lib:simplify_element(XML).
xpath(Element, Path) -> xmerl_xpath:string(Path, Element).
clean(Prefix, Path) ->
"grisp_otp_build_" ++ VsnHash = string:prefix(Path, Prefix),
[Vsn, HashExt] = string:split(VsnHash, <<"_">>),
Hash = filename:basename(HashExt, <<".tar.gz">>),
#{version => Vsn, hash => Hash}.
version_sort(#{version := Vsn, hash := H1}, #{version := Vsn, hash := H2}) ->
H1 =< H2;
version_sort(#{version := V1}, #{version := V2}) ->
V1 =< V2.