%% Copyright 2020 João Henrique Ferreira de Freitas %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. %% You may obtain a copy of the License at %% %% http://www.apache.org/licenses/LICENSE-2.0 %% %% Unless required by applicable law or agreed to in writing, software %% distributed under the License is distributed on an "AS IS" BASIS, %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %% See the License for the specific language governing permissions and %% limitations under the License. -module(rebar3_relsync_prv). -behaviour(provider). -export([init/1, do/1, format_error/1]). -define(PROVIDER, relsync). -define(DEPS, [release]). -define(DEFAULT_RELEASE_DIR, "rel"). -define(DEFAULT_RELEASE_LIB_DIR, "lib"). -spec init(rebar_state:t()) -> {ok, rebar_state:t()}. init(State) -> Provider = providers:create([ {name, ?PROVIDER}, {module, ?MODULE}, {bare, true}, {deps, ?DEPS}, {example, "rebar3 relsync --ssh --destination-node 192.168.7.2 " "--port 2222 --user relsync " "--local-path _build/devtest/rel/elock-ssh/lib/ " "--destination-path /usr/lib/elock/lib"}, {opts, opt_spec_list()}, {short_desc, "Synchronize a release on a remote node"}, {desc, "Synchronize a release on a remote node"} ]), {ok, rebar_state:add_provider(State, Provider)}. -spec do(rebar_state:t()) -> {ok, rebar_state:t()}. do(State) -> % Assembly a rebar release {ok, State0} = rebar_relx:do(release, State), ConfigOpts = rebar_state:get(State0, relsync, []), {CommandParsedArgs, _} = rebar_state:command_parsed_args(State0), DefaultOutputDir = filename:join(rebar_dir:base_dir(State), ?DEFAULT_RELEASE_DIR), OutputDir = output_dir(DefaultOutputDir, CommandParsedArgs), % Call resync {CommandParsedArgs, _} = rebar_state:command_parsed_args(State0), RelsyncArgOpts0 = filter_out_release_args(CommandParsedArgs), RelsyncArgOpts1 = maybe_add_local_path(OutputDir, RelsyncArgOpts0, CommandParsedArgs), relsync_cli:do("rebar3 relsync", RelsyncArgOpts1, ConfigOpts), {ok, State0}. format_error(Reason) -> io_lib:format("~p", [Reason]). opt_spec_list() -> RebarRelxOptSpecListSubset = [ {relname, $n, "relname", string, "Specify the name for the release that will be generated"} ], relsync_cli:opts() ++ RebarRelxOptSpecListSubset. % Filter rebar3 release arguments from relsync arguments filter_out_release_args(CommandParsedArgs) -> FilterRelsyncNamesFun = fun({Name, _Short, _Long, _ArgSpec, _Help}) -> Name end, RelsyncArgNames = lists:map(FilterRelsyncNamesFun, relsync_cli:opts()), IsRelsyncName = fun({Name, _}) -> lists:member(Name, RelsyncArgNames) end, lists:filter(IsRelsyncName, CommandParsedArgs). output_dir(DefaultOutputDir, Options) -> proplists:get_value(output_dir, Options, DefaultOutputDir). maybe_add_local_path(OutputDir, RelsyncArgOpts, CommandParsedArgs) -> Relname = proplists:get_value(relname, CommandParsedArgs, undefined), case Relname of undefined -> % error, it will not happen since as rebar_relx catches it first ignore; Relname -> case proplists:get_value(localpath, RelsyncArgOpts, undefined) of undefined -> LocalPath = filename:join([OutputDir, Relname, ?DEFAULT_RELEASE_LIB_DIR]), [{localpath, LocalPath} | RelsyncArgOpts]; _LocalPath -> RelsyncArgOpts end end.