Packages

Upgrade tools for Erlang/OTP. Contains rebar3 plugin and escript.

Current section

Files

Jump to
erlup src erlup.erl
Raw

src/erlup.erl

%% @copyright 2016 Hinagiku Soranoba All Rights Reserved.
%%
%% @doc A escript to support the upgrade and downgrade of OTP application.
%%
%% ### Log level
%% It use `rebar_log'.
%% So, you can be set in the same manner as in the rebar3.
%%
%% ```
%% $ QUIET=1 erlup # silent mode
%% $ DEBUG=1 erlup # debug mode
%% '''
%%
-module(erlup).
-include("erlup.hrl").
%%----------------------------------------------------------------------------------------------------------------------
%% Exported API
%%----------------------------------------------------------------------------------------------------------------------
-export([
main/1, init/1
]).
%%----------------------------------------------------------------------------------------------------------------------
%% Exported Functions
%%----------------------------------------------------------------------------------------------------------------------
%% rebar3 plugins.
%%
%% @private
-spec init(rebar_state:t()) -> {ok, rebar_state:t()}.
init(State0) ->
Mods = [
erlup_appup
],
lists:foldl(fun(Mod, {ok, State}) -> Mod:init(State) end, {ok, State0}, Mods).
%% escript.
%%
%% @private
main(Args) ->
init_log(),
case getopt:parse(escript_opt_specs(), Args) of
{ok, {Options, _}} ->
DoHelp = proplists:get_value(help, Options, false),
Task = proplists:get_value(task, Options, ""),
case escript_opt_specs(Task) of
[] ->
?ERROR("Task ~s not found", [Task]), halt(1);
Specs when DoHelp; Task =:= "" ->
case Task =:= "" of
true ->
getopt:usage(Specs, "erlup"),
providers:help(rebar_state:providers(element(2, init(rebar_state:new()))));
false ->
getopt:usage(Specs, "erlup" ++ " " ++ Task)
end,
halt(0);
_ ->
try
do_task(Task, Options)
catch
throw:{error, {Module, Str}} when is_atom(Module) ->
?ERROR("~s", [Module:format_error(Str)]),
halt(1)
end
end;
{error, Reason} ->
?ERROR("~s", [getopt:format_error(escript_opt_specs(), Reason)]),
halt(1)
end,
halt(0).
%%----------------------------------------------------------------------------------------------------------------------
%% Internal Functions
%%----------------------------------------------------------------------------------------------------------------------
-spec init_log() -> ok.
init_log() ->
LogLevel = case os:getenv("QUIET") of
false ->
DefaultLevel = rebar_log:default_level(),
case os:getenv("DEBUG") of
false -> DefaultLevel;
_ -> DefaultLevel + 3
end;
_ ->
rebar_log:error_level()
end,
rebar_log:init(command_line, LogLevel).
-spec do_task(string(), [{atom(), term()}]) -> ok.
do_task(Task, Options) ->
ConfPath = proplists:get_value(conf, Options),
ErlupConf = case file:consult(ConfPath) of
{ok, Terms} ->
case proplists:lookup(erlup, Terms) of
none -> Terms;
{_, ErlupConf0} -> ErlupConf0
end;
{error, Reason} ->
?WARN("~s", [file:format_error(Reason) ++ " " ++ ConfPath]),
[]
end,
do_task(Task, Options, erlup_state:new(ErlupConf)).
-spec do_task(string(), [{atom(), term()}], erlup_state:t()) -> ok.
do_task("appup", Options, State) ->
Previous = proplists:get_value(previous, Options),
Current = proplists:get_value(current, Options),
Dirs = [binary_to_list(X) || X <- binary:split(proplists:get_value(dirs, Options), <<",">>, [trim, global])],
erlup_appup:do(Dirs, Previous, Current, State),
ok.
-spec escript_opt_specs() -> [getopt:option_spec()].
escript_opt_specs() ->
[
{ task, undefined, undefined, string, "Task to run"},
{ help, $h, undefined, undefined, "Display this help"},
{ conf, undefined, "conf", {string, "erlup.conf"}, "Path of configuration file [default: erlup.conf]"},
{ current, $c, undefined, string, "Vsn of the current release"},
{previous, $p, undefined, string, "Vsn of the previous release"},
{ dirs, undefined, "dir", {binary, <<".">>}, "List of release directory (e.g. rel/${APP})"}
].
-spec escript_opt_specs(string()) -> [getopt:option_spec()].
escript_opt_specs(Task) ->
lists:filter(fun(X) -> lists:member(element(1, X), task_opts(Task)) end,
escript_opt_specs()).
-spec task_opts(Task :: string()) -> [OptKey :: atom()].
task_opts("appup") -> [current, previous, conf, dirs, help];
task_opts("") -> [help, task, conf];
task_opts(_) -> []. % not supported