Packages
rebar3_hex
1.2.0
7.1.0
7.0.11
7.0.10
7.0.9
7.0.8
7.0.7
7.0.6
7.0.5
7.0.4
7.0.3
7.0.2
7.0.1
7.0.0
6.11.9
6.11.8
6.11.7
6.11.6
6.11.5
6.11.4
6.11.3
6.11.2
6.11.1
6.11.0
6.10.3
6.10.2
6.10.1
6.10.0
6.9.6
6.9.5
6.9.4
6.9.3
6.9.2
6.9.1
6.9.0
6.8.0
6.7.0
6.6.0
6.5.0
6.4.0
6.3.0
6.2.0
6.1.0
6.0.0
4.1.0
4.0.0
3.1.0
3.0.0
2.5.1
2.5.0
2.4.0
2.3.0
2.2.0
2.1.0
2.0.0
1.20.0
1.19.0
1.18.0
1.17.0
1.16.0
1.15.0
1.14.0
1.13.0
1.12.0
1.11.0
1.10.0
1.9.1
1.9.0
1.8.1
1.8.0
1.7.2
1.7.1
1.7.0
1.6.3
1.6.1
1.6.0
1.5.0
1.4.0
1.3.0
1.2.0
1.1.0
0.9.0
0.8.0
0.7.0
0.6.0
0.5.1
0.5.0
0.4.0
0.3.0
0.2.0
0.1.0
Hex.pm plugin for rebar3
Current section
Files
Jump to
Current section
Files
src/rebar3_hex_pkg.erl
-module(rebar3_hex_pkg).
-export([init/1,
do/1,
format_error/1]).
-export([publish/2
,publish/6]).
-include("rebar3_hex.hrl").
-define(PROVIDER, publish).
-define(DEPS, [{default, app_discovery}]).
-define(ENDPOINT, "packages").
%% ===================================================================
%% Public API
%% ===================================================================
-spec init(rebar_state:t()) -> {ok, rebar_state:t()}.
init(State) ->
Provider = providers:create([
{name, ?PROVIDER},
{module, ?MODULE},
{namespace, hex},
{bare, true},
{deps, ?DEPS},
{example, "rebar3 hex publish"},
{short_desc, "Publish a new version of your package and update the package"},
{desc, ""},
{opts, [{revert, undefined, "revert", string, "Revert given version."}]}
]),
State1 = rebar_state:add_provider(State, Provider),
{ok, State1}.
-spec do(rebar_state:t()) -> {ok, rebar_state:t()} | {error, string()}.
do(State) ->
Apps = rebar3_hex_utils:select_apps(rebar_state:project_apps(State)),
lists:foldl(fun(App, {ok, StateAcc}) ->
do_(App, StateAcc)
end, {ok, State}, Apps).
-spec format_error(any()) -> iolist().
format_error(undefined_server_error) ->
"Unknown server error";
format_error(Error) ->
Message = proplists:get_value(<<"message">>, Error, ""),
Errors = proplists:get_value(<<"errors">>, Error, ""),
ErrorString = errors_to_string(Errors),
io_lib:format("Hex Error: ~s~n\t~s", [Message, ErrorString]).
%% ===================================================================
%% Public API
%% ===================================================================
do_(App, State) ->
Name = rebar_app_info:name(App),
{Args, _} = rebar_state:command_parsed_args(State),
Revert = proplists:get_value(revert, Args, undefined),
case Revert of
undefined ->
publish(App, State);
Version ->
case delete(Name, Version) of
ok ->
{ok, State};
Error ->
Error
end
end.
publish(App, State) ->
AppDir = rebar_app_info:dir(App),
Name = rebar_app_info:name(App),
Version = rebar_app_info:original_vsn(App),
Deps = rebar_state:get(State, {locks, default}, []),
TopLevel = [{N, V} || {_,{pkg,N,V},0} <- Deps],
Excluded = [binary_to_list(N) || {N,{T,_,_},0} <- Deps, T =/= pkg],
AppDetails = rebar_app_info:app_details(App),
case publish(AppDir, Name, Version, TopLevel, Excluded, AppDetails) of
ok ->
{ok, State};
Error ->
Error
end.
publish(AppDir, Name, Version, Deps, Excluded, AppDetails) ->
Description = list_to_binary(proplists:get_value(description, AppDetails, "")),
FilePaths = proplists:get_value(files, AppDetails, ?DEFAULT_FILES),
Files = rebar3_hex_utils:expand_paths(FilePaths, AppDir),
Contributors = proplists:get_value(contributors, AppDetails, []),
Licenses = proplists:get_value(licenses, AppDetails, []),
Links = proplists:get_value(links, AppDetails, []),
Optional = [{app, Name}
,{requirements, Deps}
,{contributors, Contributors}
,{precompiled, false}
,{parameters, []}
,{description, Description}
,{files, Files}
,{licenses, Licenses}
,{links, Links}
,{build_tools, [<<"rebar">>]}],
OptionalFiltered = [{Key, Value} || {Key, Value} <- Optional, Value =/= []],
Meta = [{name, Name}, {version, Version} | OptionalFiltered],
MetaString = [{<<"meta">>, rebar3_hex_utils:binarify(Meta)}],
{ok, Auth} = rebar3_hex_config:auth(),
ec_talk:say("Publishing ~s ~s", [Name, Version]),
ec_talk:say(" Dependencies:~n ~s", [format_deps(Deps)]),
ec_talk:say(" Excluded dependencies (not part of the Hex package):~n ~s", [string:join(Excluded, "\n ")]),
ec_talk:say(" Included files:~n ~s", [string:join(Files, "\n ")]),
case ec_talk:ask_default("Proceed?", boolean, "Y") of
true ->
upload_package(Auth, Name, Version, Meta, Files);
_ ->
ec_talk:say("Goodbye..."),
ok
end.
%% Internal functions
delete(Name, Version) ->
{ok, Auth} = rebar3_hex_config:auth(),
case rebar3_hex_http:delete(filename:join([?ENDPOINT, Name, "releases", Version]), Auth) of
ok ->
rebar_api:info("Successfully deleted package ~s ~s", [Name, Version]),
ok;
{error, _} ->
rebar_api:error("Unable to delete package ~s ~s", [Name, Version])
end.
upload_package(Auth, Name, Version, Meta, Files) ->
{ok, Tar} = rebar3_hex_tar:create(Name, Version, Meta, Files),
case rebar3_hex_http:post(filename:join([?ENDPOINT, Name, "releases"])
,Auth
,Tar
,integer_to_list(byte_size(Tar))) of
ok ->
rebar_api:info("Published ~s ~s", [Name, Version]),
ok;
{error, _, Error} ->
?PRV_ERROR(Error)
end.
errors_to_string(Value) when is_binary(Value) ->
Value;
errors_to_string({Key, Value}) ->
io_lib:format("~s: ~s", [Key, errors_to_string(Value)]);
errors_to_string(Errors) when is_list(Errors) ->
lists:flatten([io_lib:format("~s", [errors_to_string(Values)]) || Values <- Errors]).
format_deps(Deps) ->
string:join([binary_to_list(<<N/binary, " ", V/binary>>) || {N, V} <- Deps], "\n ").