You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

176 lines
5.4 KiB

  1. %% Vendored from hex_core v0.6.8, do not edit manually
  2. -module(r3_hex_repo).
  3. -export([
  4. get_names/1,
  5. get_versions/1,
  6. get_package/2,
  7. get_tarball/3
  8. ]).
  9. %%====================================================================
  10. %% API functions
  11. %%====================================================================
  12. %% @doc
  13. %% Gets names resource from the repository.
  14. %%
  15. %% Examples:
  16. %%
  17. %% ```
  18. %% > r3_hex_repo:get_names(r3_hex_core:default_config()).
  19. %% {ok, {200, ...,
  20. %% [
  21. %% #{name => <<"package1">>},
  22. %% #{name => <<"package2">>},
  23. %% ]}}
  24. %% '''
  25. %% @end
  26. get_names(Config) when is_map(Config) ->
  27. Verify = maps:get(repo_verify_origin, Config, true),
  28. Decoder = fun(Data) ->
  29. case Verify of
  30. true -> r3_hex_registry:decode_names(Data, repo_name(Config));
  31. false -> r3_hex_registry:decode_names(Data, no_verify)
  32. end
  33. end,
  34. get_protobuf(Config, <<"names">>, Decoder).
  35. %% @doc
  36. %% Gets versions resource from the repository.
  37. %%
  38. %% Examples:
  39. %%
  40. %% ```
  41. %% > r3_hex_repo:get_versions(Config).
  42. %% {ok, {200, ...,
  43. %% [
  44. %% #{name => <<"package1">>, retired => [],
  45. %% versions => [<<"1.0.0">>]},
  46. %% #{name => <<"package2">>, retired => [<<"0.5.0>>"],
  47. %% versions => [<<"0.5.0">>, <<"1.0.0">>]},
  48. %% ]}}
  49. %% '''
  50. %% @end
  51. get_versions(Config) when is_map(Config) ->
  52. Verify = maps:get(repo_verify_origin, Config, true),
  53. Decoder = fun(Data) ->
  54. case Verify of
  55. true -> r3_hex_registry:decode_versions(Data, repo_name(Config));
  56. false -> r3_hex_registry:decode_versions(Data, no_verify)
  57. end
  58. end,
  59. get_protobuf(Config, <<"versions">>, Decoder).
  60. %% @doc
  61. %% Gets package resource from the repository.
  62. %%
  63. %% Examples:
  64. %%
  65. %% ```
  66. %% > r3_hex_repo:get_package(r3_hex_core:default_config(), <<"package1">>).
  67. %% {ok, {200, ...,
  68. %% {
  69. %% #{checksum => ..., version => <<"0.5.0">>, dependencies => []},
  70. %% #{checksum => ..., version => <<"1.0.0">>, dependencies => [
  71. %% #{package => <<"package2">>, optional => true, requirement => <<"~> 0.1">>}
  72. %% ]},
  73. %% ]}}
  74. %% '''
  75. %% @end
  76. get_package(Config, Name) when is_binary(Name) and is_map(Config) ->
  77. Verify = maps:get(repo_verify_origin, Config, true),
  78. Decoder = fun(Data) ->
  79. case Verify of
  80. true -> r3_hex_registry:decode_package(Data, repo_name(Config), Name);
  81. false -> r3_hex_registry:decode_package(Data, no_verify, no_verify)
  82. end
  83. end,
  84. get_protobuf(Config, <<"packages/", Name/binary>>, Decoder).
  85. %% @doc
  86. %% Gets tarball from the repository.
  87. %%
  88. %% Examples:
  89. %%
  90. %% ```
  91. %% > {ok, {200, _, Tarball}} = r3_hex_repo:get_tarball(<<"package1">>, <<"1.0.0">>, r3_hex_core:default_config()),
  92. %% > {ok, #{metadata := Metadata}} = r3_hex_tarball:unpack(Tarball, memory).
  93. %% '''
  94. %% @end
  95. get_tarball(Config, Name, Version) ->
  96. ReqHeaders = make_headers(Config),
  97. case get(Config, tarball_url(Config, Name, Version), ReqHeaders) of
  98. {ok, {200, RespHeaders, Tarball}} ->
  99. {ok, {200, RespHeaders, Tarball}};
  100. Other ->
  101. Other
  102. end.
  103. %%====================================================================
  104. %% Internal functions
  105. %%====================================================================
  106. get(Config, URI, Headers) ->
  107. r3_hex_http:request(Config, get, URI, Headers, undefined).
  108. get_protobuf(Config, Path, Decoder) ->
  109. PublicKey = maps:get(repo_public_key, Config),
  110. ReqHeaders = make_headers(Config),
  111. case get(Config, build_url(Config, Path), ReqHeaders) of
  112. {ok, {200, RespHeaders, Compressed}} ->
  113. Signed = zlib:gunzip(Compressed),
  114. case decode(Signed, PublicKey, Decoder, Config) of
  115. {ok, Decoded} ->
  116. {ok, {200, RespHeaders, Decoded}};
  117. {error, _} = Error ->
  118. Error
  119. end;
  120. Other ->
  121. Other
  122. end.
  123. decode(Signed, PublicKey, Decoder, Config) ->
  124. Verify = maps:get(repo_verify, Config, true),
  125. case Verify of
  126. true ->
  127. case r3_hex_registry:decode_and_verify_signed(Signed, PublicKey) of
  128. {ok, Payload} ->
  129. Decoder(Payload);
  130. Other ->
  131. Other
  132. end;
  133. false ->
  134. #{payload := Payload} = r3_hex_registry:decode_signed(Signed),
  135. Decoder(Payload)
  136. end.
  137. repo_name(#{repo_organization := Name}) when is_binary(Name) -> Name;
  138. repo_name(#{repo_name := Name}) when is_binary(Name) -> Name.
  139. tarball_url(Config, Name, Version) ->
  140. Filename = tarball_filename(Name, Version),
  141. build_url(Config, <<"tarballs/", Filename/binary>>).
  142. build_url(#{repo_url := URI, repo_organization := Org}, Path) when is_binary(Org) ->
  143. <<URI/binary, "/repos/", Org/binary, "/", Path/binary>>;
  144. build_url(#{repo_url := URI, repo_organization := undefined}, Path) ->
  145. <<URI/binary, "/", Path/binary>>;
  146. build_url(Config, Path) ->
  147. build_url(Config#{repo_organization => undefined}, Path).
  148. tarball_filename(Name, Version) ->
  149. <<Name/binary, "-", Version/binary, ".tar">>.
  150. make_headers(Config) ->
  151. maps:fold(fun set_header/3, #{}, Config).
  152. set_header(http_etag, ETag, Headers) when is_binary(ETag) -> maps:put(<<"if-none-match">>, ETag, Headers);
  153. set_header(repo_key, Token, Headers) when is_binary(Token) -> maps:put(<<"authorization">>, Token, Headers);
  154. set_header(_, _, Headers) -> Headers.