|
|
@ -1,13 +1,12 @@ |
|
|
|
%% Vendored from hex_core v0.6.8, do not edit manually |
|
|
|
%% Vendored from hex_core v0.7.0, do not edit manually |
|
|
|
|
|
|
|
-module(r3_hex_tarball). |
|
|
|
-export([create/2, create_docs/1, unpack/2, unpack_docs/2, format_checksum/1, format_error/1]). |
|
|
|
-export([create/2, create/3, create_docs/1, create_docs/2, unpack/2, unpack/3, |
|
|
|
unpack_docs/2, unpack_docs/3, format_checksum/1, format_error/1]). |
|
|
|
-ifdef(TEST). |
|
|
|
-export([do_decode_metadata/1, gzip/1, normalize_requirements/1]). |
|
|
|
-endif. |
|
|
|
-define(VERSION, <<"3">>). |
|
|
|
-define(TARBALL_MAX_SIZE, 8 * 1024 * 1024). |
|
|
|
-define(TARBALL_MAX_UNCOMPRESSED_SIZE, 64 * 1024 * 1024). |
|
|
|
-define(BUILD_TOOL_FILES, [ |
|
|
|
{<<"mix.exs">>, <<"mix">>}, |
|
|
|
{<<"rebar.config">>, <<"rebar3">>}, |
|
|
@ -45,13 +44,16 @@ |
|
|
|
%% inner_checksum => <<178,12,...>>}} |
|
|
|
%% ''' |
|
|
|
%% @end |
|
|
|
-spec create(metadata(), files()) -> {ok, {tarball(), checksum()}} | {error, term()}. |
|
|
|
create(Metadata, Files) -> |
|
|
|
-spec create(metadata(), files(), r3_hex_core:config()) -> {ok, #{tarball => tarball(), outer_checksum => checksum(), |
|
|
|
inner_checksum => tarball()}} | {error, term()}. |
|
|
|
create(Metadata, Files, Config) -> |
|
|
|
MetadataBinary = encode_metadata(Metadata), |
|
|
|
ContentsTarball = create_memory_tarball(Files), |
|
|
|
ContentsTarballCompressed = gzip(ContentsTarball), |
|
|
|
InnerChecksum = inner_checksum(?VERSION, MetadataBinary, ContentsTarballCompressed), |
|
|
|
InnerChecksumBase16 = encode_base16(InnerChecksum), |
|
|
|
TarballMaxSize = maps:get(tarball_max_size, Config), |
|
|
|
TarballMaxUncompressedSize = maps:get(tarball_max_uncompressed_size, Config), |
|
|
|
|
|
|
|
OuterFiles = [ |
|
|
|
{"VERSION", ?VERSION}, |
|
|
@ -65,14 +67,22 @@ create(Metadata, Files) -> |
|
|
|
|
|
|
|
UncompressedSize = byte_size(ContentsTarball), |
|
|
|
|
|
|
|
case(byte_size(Tarball) > ?TARBALL_MAX_SIZE) or (UncompressedSize > ?TARBALL_MAX_UNCOMPRESSED_SIZE) of |
|
|
|
true -> |
|
|
|
{error, {tarball, too_big}}; |
|
|
|
case {(byte_size(Tarball) > TarballMaxSize), (UncompressedSize > TarballMaxUncompressedSize)} of |
|
|
|
{_, true} -> |
|
|
|
{error, {tarball, {too_big_uncompressed, TarballMaxUncompressedSize}}}; |
|
|
|
|
|
|
|
false -> |
|
|
|
{true, _} -> |
|
|
|
{error, {tarball, {too_big_compressed, TarballMaxSize}}}; |
|
|
|
|
|
|
|
{false, false} -> |
|
|
|
{ok, #{tarball => Tarball, outer_checksum => OuterChecksum, inner_checksum => InnerChecksum}} |
|
|
|
end. |
|
|
|
|
|
|
|
-spec create(metadata(), files()) -> {ok, #{tarball => tarball(), outer_checksum => checksum(), |
|
|
|
inner_checksum => tarball()}} | {error, term()}. |
|
|
|
create(Metadata, Files) -> |
|
|
|
create(Metadata, Files, r3_hex_core:default_config()). |
|
|
|
|
|
|
|
%% @doc |
|
|
|
%% Creates a docs tarball. |
|
|
|
%% |
|
|
@ -84,14 +94,14 @@ create(Metadata, Files) -> |
|
|
|
%% {ok, <<86,69,...>>} |
|
|
|
%% ''' |
|
|
|
%% @end |
|
|
|
-spec create_docs(files()) -> {ok, tarball()}. |
|
|
|
create_docs(Files) -> |
|
|
|
-spec create_docs(files(), r3_hex_core:config()) -> {ok, tarball()} | {error, term()}. |
|
|
|
create_docs(Files, #{tarball_max_size := TarballMaxSize, tarball_max_uncompressed_size := TarballMaxUncompressedSize}) -> |
|
|
|
UncompressedTarball = create_memory_tarball(Files), |
|
|
|
UncompressedSize = byte_size(UncompressedTarball), |
|
|
|
Tarball = gzip(UncompressedTarball), |
|
|
|
Size = byte_size(Tarball), |
|
|
|
|
|
|
|
case(Size > ?TARBALL_MAX_SIZE) or (UncompressedSize > ?TARBALL_MAX_UNCOMPRESSED_SIZE) of |
|
|
|
case(Size > TarballMaxSize) or (UncompressedSize > TarballMaxUncompressedSize) of |
|
|
|
true -> |
|
|
|
{error, {tarball, too_big}}; |
|
|
|
|
|
|
@ -99,6 +109,10 @@ create_docs(Files) -> |
|
|
|
{ok, Tarball} |
|
|
|
end. |
|
|
|
|
|
|
|
-spec create_docs(files()) -> {ok, tarball()}. |
|
|
|
create_docs(Files) -> |
|
|
|
create_docs(Files, r3_hex_core:default_config()). |
|
|
|
|
|
|
|
%% @doc |
|
|
|
%% Unpacks a package tarball. |
|
|
|
%% |
|
|
@ -117,16 +131,18 @@ create_docs(Files) -> |
|
|
|
%% {ok,#{outer_checksum => <<...>>, |
|
|
|
%% metadata => #{<<"name">> => <<"foo">>, ...}}} |
|
|
|
%% ''' |
|
|
|
-spec unpack(tarball(), memory) -> |
|
|
|
{ok, #{checksum => checksum(), metadata => metadata(), contents => contents()}} | |
|
|
|
-spec unpack(tarball(), memory, r3_hex_core:config()) -> |
|
|
|
{ok, #{outer_checksum => checksum(), inner_checksum => checksum(), |
|
|
|
metadata => metadata(), contents => contents()}} | |
|
|
|
{error, term()}; |
|
|
|
(tarball(), filename()) -> |
|
|
|
{ok, #{checksum => checksum(), metadata => metadata()}} | |
|
|
|
(tarball(), filename(), r3_hex_core:config()) -> |
|
|
|
{ok, #{outer_checksum => checksum(), inner_checksum => checksum(), |
|
|
|
metadata => metadata()}} | |
|
|
|
{error, term()}. |
|
|
|
unpack(Tarball, _) when byte_size(Tarball) > ?TARBALL_MAX_SIZE -> |
|
|
|
unpack(Tarball, _, #{tarball_max_size := TarballMaxSize}) when byte_size(Tarball) > TarballMaxSize -> |
|
|
|
{error, {tarball, too_big}}; |
|
|
|
|
|
|
|
unpack(Tarball, Output) -> |
|
|
|
unpack(Tarball, Output, _Config) -> |
|
|
|
case r3_hex_erl_tar:extract({binary, Tarball}, [memory]) of |
|
|
|
{ok, []} -> |
|
|
|
{error, {tarball, empty}}; |
|
|
@ -139,6 +155,18 @@ unpack(Tarball, Output) -> |
|
|
|
{error, {tarball, Reason}} |
|
|
|
end. |
|
|
|
|
|
|
|
|
|
|
|
-spec unpack(tarball(), memory) -> |
|
|
|
{ok, #{outer_checksum => checksum(), inner_checksum => checksum(), |
|
|
|
metadata => metadata(), contents => contents()}} | |
|
|
|
{error, term()}; |
|
|
|
(tarball(), filename()) -> |
|
|
|
{ok, #{outer_checksum => checksum(), inner_checksum => checksum(), |
|
|
|
metadata => metadata()}} | |
|
|
|
{error, term()}. |
|
|
|
unpack(Tarball, Output) -> |
|
|
|
unpack(Tarball, Output, r3_hex_core:default_config()). |
|
|
|
|
|
|
|
%% @doc |
|
|
|
%% Unpacks a documentation tarball. |
|
|
|
%% |
|
|
@ -151,14 +179,19 @@ unpack(Tarball, Output) -> |
|
|
|
%% > r3_hex_tarball:unpack_docs(Tarball, "path/to/unpack"). |
|
|
|
%% ok |
|
|
|
%% ''' |
|
|
|
-spec unpack_docs(tarball(), memory) -> {ok, contents()} | {error, term()}; |
|
|
|
(tarball(), filename()) -> ok | {error, term()}. |
|
|
|
unpack_docs(Tarball, _) when byte_size(Tarball) > ?TARBALL_MAX_SIZE -> |
|
|
|
-spec unpack_docs(tarball(), memory, r3_hex_core:config()) -> {ok, contents()} | {error, term()}; |
|
|
|
(tarball(), filename(), r3_hex_core:config()) -> ok | {error, term()}. |
|
|
|
unpack_docs(Tarball, _, #{tarball_max_size := TarballMaxSize}) when byte_size(Tarball) > TarballMaxSize -> |
|
|
|
{error, {tarball, too_big}}; |
|
|
|
|
|
|
|
unpack_docs(Tarball, Output) -> |
|
|
|
unpack_docs(Tarball, Output, _Config) -> |
|
|
|
unpack_tarball(Tarball, Output). |
|
|
|
|
|
|
|
-spec unpack_docs(tarball(), memory) -> {ok, contents()} | {error, term()}; |
|
|
|
(tarball(), filename()) -> ok | {error, term()}. |
|
|
|
unpack_docs(Tarball, Output) -> |
|
|
|
unpack_docs(Tarball, Output, r3_hex_core:default_config()). |
|
|
|
|
|
|
|
%% @doc |
|
|
|
%% Returns base16-encoded representation of checksum. |
|
|
|
-spec format_checksum(checksum()) -> binary(). |
|
|
@ -169,7 +202,11 @@ format_checksum(Checksum) -> |
|
|
|
%% Converts an error reason term to a human-readable error message string. |
|
|
|
-spec format_error(term()) -> string(). |
|
|
|
format_error({tarball, empty}) -> "empty tarball"; |
|
|
|
format_error({tarball, too_big}) -> "tarball is too big"; |
|
|
|
format_error({tarball, {too_big_uncompressed, Size}}) -> |
|
|
|
io_lib:format("package exceeds max uncompressed size ~w ~s", [format_byte_size(Size), "MB"]); |
|
|
|
format_error({tarball, {too_big_compressed, Size}}) -> |
|
|
|
io_lib:format("package exceeds max compressed size ~w ~s", [format_byte_size(Size), "MB"]); |
|
|
|
|
|
|
|
format_error({tarball, {missing_files, Files}}) -> io_lib:format("missing files: ~p", [Files]); |
|
|
|
format_error({tarball, {bad_version, Vsn}}) -> io_lib:format("unsupported version: ~p", [Vsn]); |
|
|
|
format_error({tarball, invalid_checksum}) -> "invalid tarball checksum"; |
|
|
@ -186,6 +223,9 @@ format_error({checksum_mismatch, ExpectedChecksum, ActualChecksum}) -> |
|
|
|
"Actual (base16-encoded): ~s", |
|
|
|
[encode_base16(ExpectedChecksum), encode_base16(ActualChecksum)]). |
|
|
|
|
|
|
|
format_byte_size(Size) -> |
|
|
|
Size / 1000000. |
|
|
|
|
|
|
|
%%==================================================================== |
|
|
|
%% Internal functions |
|
|
|
%%==================================================================== |
|
|
@ -225,7 +265,12 @@ finish_unpack({error, _} = Error) -> |
|
|
|
finish_unpack(#{metadata := Metadata, files := Files, inner_checksum := InnerChecksum, outer_checksum := OuterChecksum, output := Output}) -> |
|
|
|
_ = maps:get("VERSION", Files), |
|
|
|
ContentsBinary = maps:get("contents.tar.gz", Files), |
|
|
|
filelib:ensure_dir(filename:join(Output, "*")), |
|
|
|
|
|
|
|
case Output of |
|
|
|
memory -> ok; |
|
|
|
_ -> filelib:ensure_dir(filename:join(Output, "*")) |
|
|
|
end, |
|
|
|
|
|
|
|
case unpack_tarball(ContentsBinary, Output) of |
|
|
|
ok -> |
|
|
|
copy_metadata_config(Output, maps:get("metadata.config", Files)), |
|
|
|