Current section

Files

Jump to
grisp_updater src grisp_updater_tarball.erl
Raw

src/grisp_updater_tarball.erl

-module(grisp_updater_tarball).
-behaviour(grisp_updater_source).
%--- Includes ------------------------------------------------------------------
-include_lib("kernel/include/logger.hrl").
%--- Exports -------------------------------------------------------------------
% Behaviour grisp_updater_source callbacks
-export([source_init/1]).
-export([source_open/3]).
-export([source_stream/4]).
-export([source_cancel/3]).
-export([source_close/2]).
-export([source_terminate/2]).
%--- Records -------------------------------------------------------------------
-record(state, {
files = #{} :: #{reference() => binary()}
}).
%--- Behaviour grisp_updater_source Callbacks ----------------------------------
source_init(_Opts) ->
?LOG_INFO("Initializing GRiSP updater's tarball source", []),
{ok, #state{}}.
source_open(#state{files = Files} = State, Url, _Opts) ->
case uri_string:parse(Url) of
#{scheme := <<"tarball">>, host := <<>>, path := Path} ->
case filelib:is_regular(Path) of
false ->
{error, {tarball_not_found, Path}};
true ->
SourceRef = make_ref(),
{ok, SourceRef, State#state{
files = Files#{SourceRef => Path}
}}
end;
_Other ->
not_supported
end.
source_stream(#state{files = Files} = State, SourceRef, Path, _Opts) ->
case maps:find(SourceRef, Files) of
error -> {error, unknown_source};
{ok, Url} ->
Filename = tarball_path(Path),
case erl_tar:extract(Url, [memory, {files, [Filename]}]) of
{ok,[{Filename, Data}]} -> {data, Data, State};
{error, {_, enoent}} -> {error, {tarball_not_found, Url}};
{error, _Reason} = Error -> Error
end
end.
source_cancel(State, _SourceRef, _StreamRef) ->
State.
source_close(#state{files = Files} = State, SourceRef) ->
State#state{files = maps:remove(SourceRef, Files)}.
source_terminate(_State, _Reason) ->
?LOG_INFO("Terminating tarball update source", []),
ok.
%--- Internal Function ---------------------------------------------------------
tarball_path(Path) when is_list(Path) -> Path;
tarball_path(Path) when is_binary(Path) -> unicode:characters_to_list(Path).