From 20f3581ce75aecfd0597f1ea01f6eef790614fc3 Mon Sep 17 00:00:00 2001 From: Santiago Ferreira Date: Wed, 22 Oct 2025 18:27:14 -0300 Subject: [PATCH 1/3] Create maps recursively for "extra" metadata --- src/hex_tarball.erl | 24 ++++++++++++++++++------ test/hex_tarball_SUITE.erl | 6 ++++-- 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/src/hex_tarball.erl b/src/hex_tarball.erl index 7c2d622..5ff2f31 100644 --- a/src/hex_tarball.erl +++ b/src/hex_tarball.erl @@ -660,19 +660,31 @@ maybe_update_with(Key, Fun, Map) -> end. %% @private -try_into_map(List) -> - try_into_map(fun(X) -> X end, List). +try_into_map(Input) -> + case has_map_shape(Input) + of + true -> + maps:from_list(lists:map(fun({Key, Value}) -> + case has_map_shape(Value) of + true -> {Key, try_into_map(Value)}; + false -> {Key, Value} + end + end, Input)); + false -> Input + end. %% @private try_into_map(Fun, Input) -> - case - is_list(Input) andalso - lists:all(fun(E) -> is_tuple(E) andalso (tuple_size(E) == 2) end, Input) - of + case has_map_shape(Input) of true -> maps:from_list(lists:map(Fun, Input)); false -> Input end. +%% @private +has_map_shape(Input) -> + is_list(Input) andalso + lists:all(fun(E) -> is_tuple(E) andalso (tuple_size(E) == 2) end, Input). + %% @private encode_base16(Binary) -> <> = Binary, diff --git a/test/hex_tarball_SUITE.erl b/test/hex_tarball_SUITE.erl index 9b1aa8c..5f7f398 100644 --- a/test/hex_tarball_SUITE.erl +++ b/test/hex_tarball_SUITE.erl @@ -57,17 +57,19 @@ memory_test(_Config) -> <<"name">> => <<"foo">>, <<"version">> => <<"1.0.0">>, <<"maintainers">> => [<<"José">>], - <<"build_tool">> => <<"rebar3">> + <<"build_tool">> => <<"rebar3">>, + <<"extra">> => [{<<"foo">>, [{<<"bar">>, <<"baz">>}]}] }, Contents = [{"src/foo.erl", <<"-module(foo).">>}], {ok, #{tarball := Tarball, inner_checksum := InnerChecksum, outer_checksum := OuterChecksum}} = hex_tarball:create( Metadata, Contents ), + Metadata1 = maps:put(<<"extra">>, #{<<"foo">> => #{<<"bar">> => <<"baz">>}}, Metadata), {ok, #{ inner_checksum := InnerChecksum, outer_checksum := OuterChecksum, contents := Contents, - metadata := Metadata + metadata := Metadata1 }} = hex_tarball:unpack(Tarball, memory), ok. From 2f120e016a42f0abd1cebf9b323cc2e06916ae82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eric=20Meadows-J=C3=B6nsson?= Date: Sat, 25 Oct 2025 23:55:30 +0200 Subject: [PATCH 2/3] Only allow nested map for "extra" --- src/hex_tarball.erl | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/src/hex_tarball.erl b/src/hex_tarball.erl index 5ff2f31..1e523dc 100644 --- a/src/hex_tarball.erl +++ b/src/hex_tarball.erl @@ -457,7 +457,7 @@ characters_to_list(Binary) -> normalize_metadata(Metadata1) -> Metadata2 = maybe_update_with(<<"requirements">>, fun normalize_requirements/1, Metadata1), Metadata3 = maybe_update_with(<<"links">>, fun try_into_map/1, Metadata2), - Metadata4 = maybe_update_with(<<"extra">>, fun try_into_map/1, Metadata3), + Metadata4 = maybe_update_with(<<"extra">>, fun try_into_nested_map/1, Metadata3), guess_build_tools(Metadata4). %% @private @@ -660,23 +660,29 @@ maybe_update_with(Key, Fun, Map) -> end. %% @private -try_into_map(Input) -> - case has_map_shape(Input) +try_into_map(List) -> + try_into_map(fun(X) -> X end, List). + +%% @private +try_into_map(Fun, Input) -> + case + is_list(Input) andalso + lists:all(fun(E) -> is_tuple(E) andalso (tuple_size(E) == 2) end, Input) of - true -> - maps:from_list(lists:map(fun({Key, Value}) -> - case has_map_shape(Value) of - true -> {Key, try_into_map(Value)}; - false -> {Key, Value} - end - end, Input)); - false -> Input + true -> maps:from_list(lists:map(Fun, Input)); + false -> Input end. %% @private -try_into_map(Fun, Input) -> +try_into_nested_map(List) -> + try_into_nested_map(fun(X) -> X end, List). + +%% @private +try_into_nested_map(Fun, Input) -> case has_map_shape(Input) of - true -> maps:from_list(lists:map(Fun, Input)); + true -> maps:from_list(lists:map(fun({Key, Value}) -> + Fun({Key, try_into_nested_map(Fun, Value)}) + end, Input)); false -> Input end. From 9e3ae547e9dd42492b0c6e34b99d5af88bab60a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eric=20Meadows-J=C3=B6nsson?= Date: Sat, 25 Oct 2025 23:58:13 +0200 Subject: [PATCH 3/3] Use has_map_shape for try_into_map --- src/hex_tarball.erl | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/hex_tarball.erl b/src/hex_tarball.erl index 1e523dc..9131862 100644 --- a/src/hex_tarball.erl +++ b/src/hex_tarball.erl @@ -665,10 +665,7 @@ try_into_map(List) -> %% @private try_into_map(Fun, Input) -> - case - is_list(Input) andalso - lists:all(fun(E) -> is_tuple(E) andalso (tuple_size(E) == 2) end, Input) - of + case has_map_shape(Input) of true -> maps:from_list(lists:map(Fun, Input)); false -> Input end.