Packages
rebar3_hex
6.10.2
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_docs.erl
-module(rebar3_hex_docs).
-export([init/1,
do/1,
publish/3,
format_error/1]).
-include("rebar3_hex.hrl").
-define(PROVIDER, docs).
-define(DEPS, [{default, lock}]).
-define(ENDPOINT, "packages").
-define(DEFAULT_DOC_DIR, "doc").
%% ===================================================================
%% 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 docs"},
{short_desc, "Publish documentation for the current project and version"},
{desc, ""},
{opts, [{revert, undefined, "revert", string, "Revert given version."},
rebar3_hex:repo_opt()]},
{profiles, [docs]}]),
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_io:select_apps(rebar_state:project_apps(State)),
try publish_apps(Apps, State) of
{ok, State} ->
{ok, State}
catch
throw:{error,{rebar3_hex_docs, _}} = Err ->
Err;
error:{badmatch, {error, Reason}} ->
?PRV_ERROR(Reason)
end.
%% @doc Publish documentation directory to repository
%%
%% This following function is exported for publishing docs via the
%% main the publish command.
-spec publish(rebar_app_info:t(), rebar_state:t(), map()) ->
{ok, rebar_state:t()}.
publish(App, State, Repo) ->
handle_command(App, State, Repo).
-spec format_error(any()) -> iolist().
format_error(bad_command) ->
"Invalid command and/or options provided";
format_error({publish, {unauthorized, _Res}}) ->
"Error publishing : Not authorized";
format_error({publish, {not_found, _Res}}) ->
"Error publishing : Package or Package Version not found";
format_error({revert, {unauthorized, _Res}}) ->
"Error reverting docs : Not authorized";
format_error({revert, {not_found, _Res}}) ->
"Error reverting docs : Package or Package Version not found";
format_error(Reason) ->
rebar3_hex_error:format_error(Reason).
%% ===================================================================
%% Internal Functions
%% ===================================================================
publish_apps(Apps, State) ->
lists:foldl(fun(App, {ok, StateAcc}) ->
case handle_command(App, StateAcc) of
{ok, _StateAcc} ->
{ok, StateAcc};
Err ->
throw(Err)
end
end, {ok, State}, Apps).
handle_command(App, State) ->
{ok, Repo} = rebar3_hex_config:repo(State),
handle_command(App, State, Repo).
handle_command(App, State, Repo) ->
{Args, _} = rebar_state:command_parsed_args(State),
case proplists:get_value(revert, Args, undefined) of
undefined ->
do_publish(App, State, Repo);
Vsn ->
do_revert(App,State,Repo, Vsn)
end.
do_publish(App, State, Repo) ->
AppDir = rebar_app_info:dir(App),
DocDir = resolve_doc_dir(App),
assert_doc_dir(filename:join(AppDir, DocDir)),
Files = rebar3_hex_file:expand_paths([DocDir], AppDir),
AppDetails = rebar_app_info:app_details(App),
Name = binary_to_list(rebar_app_info:name(App)),
PkgName = rebar_utils:to_list(proplists:get_value(pkg_name, AppDetails, Name)),
OriginalVsn = rebar_app_info:original_vsn(App),
Vsn = rebar_utils:vcs_vsn(App, OriginalVsn, State),
Tarball = PkgName ++ "-" ++ vsn_string(Vsn) ++ "-docs.tar.gz",
ok = erl_tar:create(Tarball, file_list(Files, DocDir), [compressed]),
{ok, Tar} = file:read_file(Tarball),
file:delete(Tarball),
{ok, Config} = rebar3_hex_config:hex_config_write(Repo),
case rebar3_hex_client:publish_docs(Config, rebar_utils:to_binary(PkgName), rebar_utils:to_binary(Vsn), Tar) of
{ok, _} ->
rebar_api:info("Published docs for ~ts ~ts", [PkgName, Vsn]),
{ok, State};
Reason ->
?PRV_ERROR({publish, Reason})
end.
vsn_string(<<Vsn/binary>>) ->
binary_to_list(Vsn);
vsn_string(Vsn) ->
Vsn.
do_revert(App, State, Repo, Vsn) ->
{ok, Config} = rebar3_hex_config:hex_config_write(Repo),
AppDetails = rebar_app_info:app_details(App),
Name = binary_to_list(rebar_app_info:name(App)),
PkgName = ec_cnv:to_list(proplists:get_value(pkg_name, AppDetails, Name)),
case rebar3_hex_client:delete_docs(Config, rebar_utils:to_binary(PkgName), rebar_utils:to_binary(Vsn)) of
{modified, _Body} ->
rebar_api:info("Successfully deleted docs for ~ts ~ts", [Name, Vsn]),
{ok, State};
Reason ->
?PRV_ERROR({revert, Reason})
end.
%% @doc Returns the directory were docs are to be found
%%
%% The priority for resolution is the following:
%% 1. `doc' entry in the application's `*.app.src'.
%% 2. `dir' entry specified in `edoc_opts'.
%% 3. `"doc"' fallback default value.
-spec resolve_doc_dir(rebar_app_info:t()) -> string().
resolve_doc_dir(AppInfo) ->
AppOpts = rebar_app_info:opts(AppInfo),
EdocOpts = rebar_opts:get(AppOpts, edoc_opts, []),
AppDetails = rebar_app_info:app_details(AppInfo),
Dir = proplists:get_value(dir, EdocOpts, ?DEFAULT_DOC_DIR),
proplists:get_value(doc, AppDetails, Dir).
-spec assert_doc_dir(string()) -> true.
assert_doc_dir(DocDir) ->
filelib:is_dir(DocDir) orelse
rebar_api:abort( "Docs were not published since they "
"couldn't be found in '~s'. "
"Please build the docs and then run "
"`rebar3 hex docs` to publish them."
, [DocDir]
).
file_list(Files, DocDir) ->
[{drop_path(ShortName, [DocDir]), FullName} || {ShortName, FullName} <- Files].
drop_path(File, Path) ->
filename:join(filename:split(File) -- Path).