Compare commits

...

37 Commits

Author SHA1 Message Date
Paweł Chmielowski a58de70f06 Fix invalid argument in get_messages_susbset
This should fix #1818
2017-06-30 14:24:35 +02:00
Christophe Romain 800965a957 Avoid useless calls on simples subscriptions (#1313) 2017-06-29 15:24:18 +02:00
Alexey Shchepin fcf672c50e Add allow_local_users to mod_block_strangers (#1804, #1809) 2017-06-29 14:55:24 +03:00
Badlop b66e369a1d Fix Salt import from prosody SCRAMmed password (#1803) 2017-06-29 10:28:44 +02:00
Paweł Chmielowski 9dd03c873c Fix clone code in update-deps-release 2017-06-28 16:47:31 +02:00
Paweł Chmielowski e42bb47ce3 Update deps 2017-06-28 16:46:48 +02:00
Paweł Chmielowski dc7fa076d7 Fix problem with updating deps in rebar.config for non-tags 2017-06-28 16:36:59 +02:00
Paweł Chmielowski 960cf495c6 Don't use asn1rt:decode, it's not available on R20 2017-06-28 14:51:45 +02:00
Christophe Romain 0f12804a49 Quote paths to allow spaces (#1789) 2017-06-28 11:39:05 +02:00
Badlop 3c7c71cfa6 In offline export to SQL, first write all DELETE, later all INSERT (#1509) 2017-06-28 11:14:59 +02:00
Paweł Chmielowski aac190255b Update fast_tls 2017-06-27 15:02:23 +02:00
Paweł Chmielowski 85a08a087b Improve update-deps-releases deps parsing 2017-06-27 14:56:00 +02:00
Badlop 1bfb0ab39c Fix username in mam export (#1510)(thanks to themaverik) 2017-06-26 14:38:12 +02:00
Badlop 4ef1cdec12 Write validator for mod_multicast's limits option 2017-06-26 13:39:50 +02:00
Badlop 0534678028 Use YAML syntax for limits option in mod_multicast 2017-06-26 11:26:53 +02:00
Paweł Chmielowski 70606d7f1a Catch exception that may happen when sending data over websocket
This fixes #1667
2017-06-23 17:19:37 +02:00
Mickaël Rémond bb39ecbc08 More explicit bosh configuration handler
I also updated default url from to match URL suggested by XEP-0156
2017-06-23 16:47:14 +02:00
Evgeny Khramtsov 54e6e1a5fb Merge pull request #1793 from marcphilipp/bugfix/set_room_affiliation_master
Fix mod_muc_admin:set_room_affiliation
2017-06-22 18:28:12 +04:00
Evgeniy Khramtsov 5bb7a0b0db Don't let a receiver to crash if a controller is unavailable
Fixes #1796
2017-06-22 16:58:46 +03:00
Marc Philipp 976a8c9cc9 Fix mod_muc_admin:set_room_affiliation 2017-06-21 17:20:58 +02:00
Christophe Romain a095477b4c Fix outgoing_s2s_timeout description (#1684) 2017-06-21 16:30:51 +02:00
Holger Weiss 950aca380c mod_client_state: Reset state on session resume
Don't restore the previous CSI state when a stream management session is
resumed.
2017-06-21 01:05:46 +02:00
Holger Weiss 985b0a1933 mod_stream_mgmt: Add missing function specs 2017-06-21 01:00:29 +02:00
Christophe Romain a7841ed486 Improve API documentation generator 2017-06-20 14:45:57 +02:00
Christophe Romain a11e833a98 Make ext_mod api return rescode 2017-06-20 14:45:31 +02:00
Paweł Chmielowski 62ee051c6e Fix invalid {args,result}_examples in mod_muc_admin 2017-06-19 16:31:07 +02:00
Paweł Chmielowski 5424ead01d Generate better errors when not being able to generate documentation 2017-06-19 16:30:45 +02:00
Paweł Chmielowski 96d385bf82 Another tweak to md generator 2017-06-19 15:10:34 +02:00
Paweł Chmielowski 8e2258b16a Update markdown api document generator 2017-06-19 15:02:02 +02:00
Badlop f87b46f454 Fix srg_user_add/del for non-Mnesia database backends (#1780) 2017-06-15 11:05:41 +02:00
Christophe Romain 5418b37314 Add pubsub import from prosody/metronome 2017-06-15 09:56:05 +02:00
Paweł Chmielowski 6353a06a5d Catch exception from Elixir.ExUnit.Server.cases_loaded 2017-06-14 14:56:59 +02:00
Christophe Romain 58b9077b51 Fix OTP-17.5 support 2017-06-14 14:18:35 +02:00
Paweł Chmielowski 10fcfa860a Show operations to perform before asking to apply them 2017-06-14 14:05:41 +02:00
Holger Weiss 5f2dcc51ce Bump xmpp version 2017-06-14 01:05:15 +02:00
Evgeniy Khramtsov 0aa64381ff Fix IP address parsing for mod_metrics 2017-06-13 16:54:29 +03:00
Christophe Romain 6c8b037422 Fix refactor bug on wait_status 2017-06-13 12:37:27 +02:00
26 changed files with 406 additions and 188 deletions
+4 -4
View File
@@ -158,11 +158,11 @@ listen:
ip: "::"
module: ejabberd_http
request_handlers:
"/websocket": ejabberd_http_ws
"/ws": ejabberd_http_ws
"/bosh": mod_bosh
"/api": mod_http_api
## "/pub/archive": mod_http_fileserver
web_admin: true
http_bind: true
## register: true
captcha: true
##
@@ -265,12 +265,12 @@ listen:
## Outgoing S2S options
##
## Preferred address families (which to try first) and connect timeout
## in milliseconds.
## in seconds.
##
## outgoing_s2s_families:
## - ipv4
## - ipv6
## outgoing_s2s_timeout: 10000
## outgoing_s2s_timeout: 190
###. ==============
###' AUTHENTICATION
+8 -7
View File
@@ -10,9 +10,9 @@ FIREWALL_WINDOW=""
ERLANG_NODE=ejabberd@localhost
# define default environment variables
ERL={{erl}}
IEX={{bindir}}/iex
EPMD={{epmd}}
ERL="{{erl}}"
IEX="{{bindir}}/iex"
EPMD="{{epmd}}"
INSTALLUSER={{installuser}}
# check the proper system user is used if defined
@@ -110,12 +110,12 @@ exec_cmd()
exec_erl()
{
NODE=$1; shift
exec_cmd $ERL ${S:--}name $NODE $ERLANG_OPTS "$@"
exec_cmd "$ERL" ${S:--}name $NODE $ERLANG_OPTS "$@"
}
exec_iex()
{
NODE=$1; shift
exec_cmd $IEX ${S:---}name $NODE --erl "$ERLANG_OPTS" "$@"
exec_cmd "$IEX" ${S:---}name $NODE --erl "$ERLANG_OPTS" "$@"
}
# usage
@@ -245,7 +245,8 @@ wait_status()
if [ $timeout -eq 0 ] ; then
status=$1
else
ctl status > /dev/null
exec_erl $(uid ctl) -hidden -noinput -s ejabberd_ctl \
-extra $ERLANG_NODE $NO_TIMEOUT status > /dev/null
status=$?
fi
done
@@ -286,7 +287,7 @@ case $1 in
ping)
PEER=${2:-$ERLANG_NODE}
[ "$PEER" = "${PEER%.*}" ] && PS="-s"
exec_cmd $ERL ${PS:--}name $(uid ping $(hostname $PS)) $ERLANG_OPTS \
exec_cmd "$ERL" ${PS:--}name $(uid ping $(hostname $PS)) $ERLANG_OPTS \
-noinput -hidden -eval 'io:format("~p~n",[net_adm:ping('"$PEER"')])' \
-s erlang halt -output text
;;
+8 -7
View File
@@ -18,19 +18,20 @@
%%%
%%%----------------------------------------------------------------------
{deps, [{lager, ".*", {git, "https://github.com/erlang-lager/lager", {tag, "3.4.2"}}},
{deps, [{lager, ".*", {git, "https://github.com/erlang-lager/lager",
{tag, {if_version_above, "17", "3.4.2", "3.2.1"}}}},
{p1_utils, ".*", {git, "https://github.com/processone/p1_utils", {tag, "1.0.9"}}},
{cache_tab, ".*", {git, "https://github.com/processone/cache_tab", {tag, "1.0.8"}}},
{fast_tls, ".*", {git, "https://github.com/processone/fast_tls", {tag, "1.0.12"}}},
{cache_tab, ".*", {git, "https://github.com/processone/cache_tab", {tag, "1.0.9"}}},
{fast_tls, ".*", {git, "https://github.com/processone/fast_tls", {tag, "1.0.13"}}},
{stringprep, ".*", {git, "https://github.com/processone/stringprep", {tag, "1.0.9"}}},
{fast_xml, ".*", {git, "https://github.com/processone/fast_xml", {tag, "1.1.23"}}},
{xmpp, ".*", {git, "https://github.com/processone/xmpp", {tag, "1.1.11"}}},
{xmpp, ".*", {git, "https://github.com/processone/xmpp", {tag, "1.1.13"}}},
{fast_yaml, ".*", {git, "https://github.com/processone/fast_yaml", {tag, "1.0.10"}}},
{jiffy, ".*", {git, "https://github.com/davisp/jiffy", {tag, "0.14.8"}}},
{p1_oauth2, ".*", {git, "https://github.com/processone/p1_oauth2", {tag, "0.6.1"}}},
{luerl, ".*", {git, "https://github.com/rvirding/luerl", {tag, "v0.2"}}},
{if_var_true, stun, {stun, ".*", {git, "https://github.com/processone/stun", {tag, "1.0.11"}}}},
{if_var_true, sip, {esip, ".*", {git, "https://github.com/processone/esip", {tag, "1.0.12"}}}},
{if_var_true, stun, {stun, ".*", {git, "https://github.com/processone/stun", {tag, "1.0.12"}}}},
{if_var_true, sip, {esip, ".*", {git, "https://github.com/processone/esip", {tag, "1.0.13"}}}},
{if_var_true, mysql, {p1_mysql, ".*", {git, "https://github.com/processone/p1_mysql",
{tag, "1.0.3"}}}},
{if_var_true, pgsql, {p1_pgsql, ".*", {git, "https://github.com/processone/p1_pgsql",
@@ -38,7 +39,7 @@
{if_var_true, sqlite, {sqlite3, ".*", {git, "https://github.com/processone/erlang-sqlite3",
{tag, "1.1.5"}}}},
{if_var_true, pam, {epam, ".*", {git, "https://github.com/processone/epam",
{tag, "1.0.2"}}}},
{tag, "1.0.3"}}}},
{if_var_true, zlib, {ezlib, ".*", {git, "https://github.com/processone/ezlib",
{tag, "1.0.2"}}}},
{if_var_true, riak, {riakc, ".*", {git, "https://github.com/basho/riak-erlang-client",
+4 -1
View File
@@ -67,7 +67,10 @@
start(SockData, Opts) ->
case proplists:get_value(supervisor, Opts, true) of
true ->
supervisor:start_child(ejabberd_c2s_sup, [SockData, Opts]);
case supervisor:start_child(ejabberd_c2s_sup, [SockData, Opts]) of
{ok, undefined} -> ignore;
Res -> Res
end;
_ ->
xmpp_stream_in:start(?MODULE, [SockData, Opts],
ejabberd_config:fsm_limit_opts(Opts))
+63 -43
View File
@@ -69,9 +69,9 @@ list_join_with([El|Tail], M) ->
end, [El], Tail)).
md_tag(dt, V) ->
[<<"\n">>, V, <<"\n">>];
[<<"- ">>, V];
md_tag(dd, V) ->
[<<"\n: ">>, V, <<"\n">>];
[<<" : ">>, V, <<"\n">>];
md_tag(li, V) ->
[<<"- ">>, V, <<"\n">>];
md_tag(pre, V) ->
@@ -87,13 +87,8 @@ md_tag(strong, V) ->
md_tag(_, V) ->
V.
%% rescode_to_int(ok) ->
%% 0;
%% rescode_to_int(true) ->
%% 0;
%% rescode_to_int(_) ->
%% 1.
unbinarize(binary) -> string;
unbinarize(Other) -> Other.
perl_gen({Name, integer}, Int, _Indent, HTMLOutput) ->
[?ARG(Name), ?OP_L(" => "), ?NUM(Int)];
@@ -324,18 +319,35 @@ gen_calls(#ejabberd_commands{args_example=Values, args=ArgsDesc,
case lists:member(<<"xmlrpc">>, Langs) of true -> ?TAG(li, ?TAG(pre, XML)); _ -> [] end,
case lists:member(<<"json">>, Langs) of true -> ?TAG(li, ?TAG(pre, JSON)); _ -> [] end])];
true ->
[<<"\n">>, case lists:member(<<"java">>, Langs) of true -> <<"* Java\n">>; _ -> [] end,
case lists:member(<<"perl">>, Langs) of true -> <<"* Perl\n">>; _ -> [] end,
case lists:member(<<"xmlrpc">>, Langs) of true -> <<"* XmlRPC\n">>; _ -> [] end,
case lists:member(<<"json">>, Langs) of true -> <<"* JSON\n">>; _ -> [] end,
<<"{: .code-samples-labels}\n">>,
case lists:member(<<"java">>, Langs) of true -> [<<"\n* ">>, ?TAG(pre, Java), <<"~~~\n">>]; _ -> [] end,
case lists:member(<<"perl">>, Langs) of true -> [<<"\n* ">>, ?TAG(pre, Perl), <<"~~~\n">>]; _ -> [] end,
case lists:member(<<"xmlrpc">>, Langs) of true -> [<<"\n* ">>, ?TAG(pre, XML), <<"~~~\n">>]; _ -> [] end,
case lists:member(<<"json">>, Langs) of true -> [<<"\n* ">>, ?TAG(pre, JSON), <<"~~~\n">>]; _ -> [] end,
<<"{: .code-samples-tabs}\n\n">>]
case Langs of
Val when length(Val) == 0 orelse length(Val) == 1 ->
[case lists:member(<<"java">>, Langs) of true -> [<<"\n">>, ?TAG(pre, Java), <<"~~~\n">>]; _ -> [] end,
case lists:member(<<"perl">>, Langs) of true -> [<<"\n">>, ?TAG(pre, Perl), <<"~~~\n">>]; _ -> [] end,
case lists:member(<<"xmlrpc">>, Langs) of true -> [<<"\n">>, ?TAG(pre, XML), <<"~~~\n">>]; _ -> [] end,
case lists:member(<<"json">>, Langs) of true -> [<<"\n">>, ?TAG(pre, JSON), <<"~~~\n">>]; _ -> [] end,
<<"\n\n">>];
_ ->
[<<"\n">>, case lists:member(<<"java">>, Langs) of true -> <<"* Java\n">>; _ -> [] end,
case lists:member(<<"perl">>, Langs) of true -> <<"* Perl\n">>; _ -> [] end,
case lists:member(<<"xmlrpc">>, Langs) of true -> <<"* XmlRPC\n">>; _ -> [] end,
case lists:member(<<"json">>, Langs) of true -> <<"* JSON\n">>; _ -> [] end,
<<"{: .code-samples-labels}\n">>,
case lists:member(<<"java">>, Langs) of true -> [<<"\n* ">>, ?TAG(pre, Java), <<"~~~\n">>]; _ -> [] end,
case lists:member(<<"perl">>, Langs) of true -> [<<"\n* ">>, ?TAG(pre, Perl), <<"~~~\n">>]; _ -> [] end,
case lists:member(<<"xmlrpc">>, Langs) of true -> [<<"\n* ">>, ?TAG(pre, XML), <<"~~~\n">>]; _ -> [] end,
case lists:member(<<"json">>, Langs) of true -> [<<"\n* ">>, ?TAG(pre, JSON), <<"~~~\n">>]; _ -> [] end,
<<"{: .code-samples-tabs}\n\n">>]
end
end.
gen_param(Name, Type, undefined, HTMLOutput) ->
[?TAG(li, [?TAG_R(strong, atom_to_list(Name)), <<" :: ">>,
?RAW(io_lib:format("~p", [unbinarize(Type)]))])];
gen_param(Name, Type, Desc, HTMLOutput) ->
[?TAG(dt, [?TAG_R(strong, atom_to_list(Name)), <<" :: ">>,
?RAW(io_lib:format("~p", [unbinarize(Type)]))]),
?TAG(dd, ?RAW(Desc))].
gen_doc(#ejabberd_commands{name=Name, tags=_Tags, desc=Desc, longdesc=LongDesc,
args=Args, args_desc=ArgsDesc,
result=Result, result_desc=ResultDesc}=Cmd, HTMLOutput, Langs) ->
@@ -345,34 +357,42 @@ gen_doc(#ejabberd_commands{name=Name, tags=_Tags, desc=Desc, longdesc=LongDesc,
end,
ArgsText = case ArgsDesc of
none ->
[?TAG(ul, "args-list", lists:map(fun({AName, Type}) ->
[?TAG(li, [?TAG_R(strong, atom_to_list(AName)), <<" :: ">>,
?RAW(io_lib:format("~p", [Type]))])]
end, Args))];
[?TAG(ul, "args-list", [gen_param(AName, Type, undefined, HTMLOutput)
|| {AName, Type} <- Args])];
_ ->
[?TAG(dl, "args-list", lists:map(fun({{AName, Type}, ADesc}) ->
[?TAG(dt, [?TAG_R(strong, atom_to_list(AName)), <<" :: ">>,
?RAW(io_lib:format("~p", [Type]))]),
?TAG(dd, ?RAW(ADesc))]
end, lists:zip(Args, ArgsDesc)))]
[?TAG(dl, "args-list", [gen_param(AName, Type, ADesc, HTMLOutput)
|| {{AName, Type}, ADesc} <- lists:zip(Args, ArgsDesc)])]
end,
ResultText = case ResultDesc of
none ->
[?RAW(io_lib:format("~p", [Result]))];
_ ->
[?TAG(dl, [
?TAG(dt, io_lib:format("~p", [Result])),
?TAG_R(dd, ResultDesc)])]
ResultText = case Result of
{res,rescode} ->
[?TAG(dl, [gen_param(res, integer,
"Status code (0 on success, 1 otherwise)",
HTMLOutput)])];
{res,restuple} ->
[?TAG(dl, [gen_param(res, string,
"Raw result string",
HTMLOutput)])];
{RName, Type} ->
case ResultDesc of
none ->
[?TAG(ul, [gen_param(RName, Type, undefined, HTMLOutput)])];
_ ->
[?TAG(dl, [gen_param(RName, Type, ResultDesc, HTMLOutput)])]
end
end,
[?TAG(h1, [?TAG(strong, atom_to_list(Name)), <<" - ">>, ?RAW(Desc)]),
?TAG(p, ?RAW(LDesc)),
?TAG(h2, <<"Arguments:">>),
ArgsText,
?TAG(h2, <<"Result:">>),
ResultText,
?TAG(h2, <<"Examples:">>),
gen_calls(Cmd, HTMLOutput, Langs)].
try
[?TAG(h1, [?TAG(strong, atom_to_list(Name)), <<" - ">>, ?RAW(Desc)]),
?TAG(p, ?RAW(LDesc)),
?TAG(h2, <<"Arguments:">>), ArgsText,
?TAG(h2, <<"Result:">>), ResultText,
?TAG(h2, <<"Examples:">>), gen_calls(Cmd, HTMLOutput, Langs)]
catch
_:Ex ->
throw(iolist_to_binary(io_lib:format(
<<"Error when generating documentation for command '~p': ~p">>,
[Name, Ex])))
end.
find_commands_definitions() ->
case code:lib_dir(ejabberd, ebin) of
+8 -2
View File
@@ -81,8 +81,14 @@ start_link(WS) ->
gen_fsm:start_link(?MODULE, [WS], ?FSMOPTS).
send_xml({http_ws, FsmRef, _IP}, Packet) ->
gen_fsm:sync_send_all_state_event(FsmRef,
{send_xml, Packet}).
case catch gen_fsm:sync_send_all_state_event(FsmRef,
{send_xml, Packet},
15000)
of
{'EXIT', {timeout, _}} -> {error, timeout};
{'EXIT', _} -> {error, einval};
Res -> Res
end.
setopts({http_ws, FsmRef, _IP}, Opts) ->
case lists:member({active, once}, Opts) of
+4 -1
View File
@@ -57,7 +57,10 @@
start(SockData, Opts) ->
case proplists:get_value(supervisor, Opts, true) of
true ->
supervisor:start_child(ejabberd_s2s_in_sup, [SockData, Opts]);
case supervisor:start_child(ejabberd_s2s_in_sup, [SockData, Opts]) of
{ok, undefined} -> ignore;
Res -> Res
end;
_ ->
xmpp_stream_in:start(?MODULE, [SockData, Opts],
ejabberd_config:fsm_limit_opts(Opts))
+7 -4
View File
@@ -54,10 +54,13 @@
%%%===================================================================
start(From, To, Opts) ->
case proplists:get_value(supervisor, Opts, true) of
true ->
supervisor:start_child(ejabberd_s2s_out_sup,
[From, To, Opts]);
_ ->
true ->
case supervisor:start_child(ejabberd_s2s_out_sup,
[From, To, Opts]) of
{ok, undefined} -> ignore;
Res -> Res
end;
_ ->
xmpp_stream_out:start(?MODULE, [ejabberd_socket, From, To, Opts],
ejabberd_config:fsm_limit_opts([]))
end.
+1 -1
View File
@@ -87,7 +87,7 @@
%% API
%%====================================================================
-spec start(atom(), sockmod(), socket(), [proplists:property()])
-> {ok, pid() | independent} | {error, inet:posix() | any()}.
-> {ok, pid() | independent} | {error, inet:posix() | any()} | ignore.
start(Module, SockMod, Socket, Opts) ->
case Module:socket_type() of
independent -> {ok, independent};
+5 -5
View File
@@ -84,7 +84,7 @@ get_commands_spec() ->
longdesc = "",
module = ?MODULE, function = update,
args = [],
result = {res, integer}},
result = {res, rescode}},
#ejabberd_commands{name = modules_available,
tags = [admin,modules],
desc = "",
@@ -111,28 +111,28 @@ get_commands_spec() ->
longdesc = "",
module = ?MODULE, function = install,
args = [{module, binary}],
result = {res, integer}},
result = {res, rescode}},
#ejabberd_commands{name = module_uninstall,
tags = [admin,modules],
desc = "",
longdesc = "",
module = ?MODULE, function = uninstall,
args = [{module, binary}],
result = {res, integer}},
result = {res, rescode}},
#ejabberd_commands{name = module_upgrade,
tags = [admin,modules],
desc = "",
longdesc = "",
module = ?MODULE, function = upgrade,
args = [{module, binary}],
result = {res, integer}},
result = {res, rescode}},
#ejabberd_commands{name = module_check,
tags = [admin,modules],
desc = "",
longdesc = "",
module = ?MODULE, function = check,
args = [{module, binary}],
result = {res, integer}}
result = {res, rescode}}
].
%% -- public modules functions
+2 -2
View File
@@ -1401,11 +1401,11 @@ srg_get_members(Group, Host) ->
|| {MUser, MServer} <- Members].
srg_user_add(User, Host, Group, GroupHost) ->
{atomic, _} = mod_shared_roster:add_user_to_group(GroupHost, {User, Host}, Group),
mod_shared_roster:add_user_to_group(GroupHost, {User, Host}, Group),
ok.
srg_user_del(User, Host, Group, GroupHost) ->
{atomic, _} = mod_shared_roster:remove_user_from_group(GroupHost, {User, Host}, Group),
mod_shared_roster:remove_user_from_group(GroupHost, {User, Host}, Group),
ok.
+7 -2
View File
@@ -58,9 +58,12 @@ filter_packet({#message{} = Msg, State} = Acc) ->
LFrom = jid:tolower(From),
LBFrom = jid:remove_resource(LFrom),
#{pres_a := PresA, jid := JID, lserver := LServer} = State,
AllowLocalUsers =
gen_mod:get_module_opt(LServer, ?MODULE, allow_local_users, true),
case (Msg#message.body == [] andalso
Msg#message.subject == [])
orelse ejabberd_router:is_my_route(From#jid.lserver)
orelse (AllowLocalUsers andalso
ejabberd_router:is_my_route(From#jid.lserver))
orelse (?SETS):is_element(LFrom, PresA)
orelse (?SETS):is_element(LBFrom, PresA)
orelse sets_bare_member(LBFrom, PresA) of
@@ -128,4 +131,6 @@ mod_opt_type(drop) ->
fun (B) when is_boolean(B) -> B end;
mod_opt_type(log) ->
fun (B) when is_boolean(B) -> B end;
mod_opt_type(_) -> [drop, log].
mod_opt_type(allow_local_users) ->
fun (B) when is_boolean(B) -> B end;
mod_opt_type(_) -> [drop, log, allow_local_users].
+2 -2
View File
@@ -199,8 +199,8 @@ c2s_authenticated_packet(C2SState, _) ->
C2SState.
-spec c2s_copy_session(c2s_state(), c2s_state()) -> c2s_state().
c2s_copy_session(C2SState, #{csi_state := State, csi_queue := Q}) ->
C2SState#{csi_state => State, csi_queue => Q};
c2s_copy_session(C2SState, #{csi_queue := Q}) ->
C2SState#{csi_queue => Q};
c2s_copy_session(C2SState, _) ->
C2SState.
+3 -4
View File
@@ -198,15 +198,14 @@ export(_Server) ->
[]
end},
{archive_msg,
fun(Host, #archive_msg{us ={_LUser, LServer},
fun(Host, #archive_msg{us ={LUser, LServer},
id = _ID, timestamp = TS, peer = Peer,
bare_peer = {PUser, PServer, <<>>},
type = Type, nick = Nick, packet = Pkt})
when LServer == Host ->
TStmp = now_to_usec(TS),
SUser = case Type of
chat -> PUser;
groupchat -> jid:encode({PUser, PServer, <<>>})
chat -> LUser;
groupchat -> jid:encode({LUser, LServer, <<>>})
end,
BarePeer = jid:encode(jid:tolower(jid:remove_resource(Peer))),
LPeer = jid:encode(jid:tolower(Peer)),
+2 -1
View File
@@ -179,7 +179,8 @@ get_socket(N) ->
mod_opt_type(ip) ->
fun(S) ->
{ok, IP} = inet:parse_ipv4_address(iolist_to_binary(S)),
{ok, IP} = inet:parse_ipv4_address(
binary_to_list(iolist_to_binary(S))),
IP
end;
mod_opt_type(port) ->
+7 -4
View File
@@ -208,8 +208,11 @@ get_commands_spec() ->
module = ?MODULE, function = send_direct_invitation,
args_desc = ["Room name", "MUC service", "Password, or none",
"Reason text, or none", "Users JIDs separated with : characters"],
args_example = ["room1", "muc.example.com", none, none, "user2@localhost:user3@example.com"],
args = [{name, binary}, {service, binary}, {password, binary}, {reason, binary}, {users, binary}],
args_example = [<<"room1">>, <<"muc.example.com">>,
<<>>, <<"Check this out!">>,
"user2@localhost:user3@example.com"],
args = [{name, binary}, {service, binary}, {password, binary},
{reason, binary}, {users, binary}],
result = {res, rescode}},
#ejabberd_commands{name = change_room_option, tags = [muc_room],
@@ -277,7 +280,7 @@ get_commands_spec() ->
args_desc = ["Room name", "MUC service"],
args_example = ["room1", "muc.example.com"],
result_desc = "The list of affiliations with username, domain, affiliation and reason",
result_example = [{"user1", "example.com", "member"}],
result_example = [{"user1", "example.com", member, "member"}],
args = [{name, binary}, {service, binary}],
result = {affiliations, {list,
{affiliation, {tuple,
@@ -1009,7 +1012,7 @@ set_room_affiliation(Name, Service, JID, AffiliationString) ->
case mod_muc:find_online_room(Name, Service) of
{ok, Pid} ->
%% Get the PID for the online room so we can get the state of the room
{ok, StateData} = gen_fsm:sync_send_all_state_event(Pid, {process_item_change, {jid:decode(JID), affiliation, Affiliation, <<"">>}, <<"">>}),
{ok, StateData} = gen_fsm:sync_send_all_state_event(Pid, {process_item_change, {jid:decode(JID), affiliation, Affiliation, <<"">>}, undefined}),
mod_muc:store_room(StateData#state.server_host, StateData#state.host, StateData#state.room, make_opts(StateData)),
ok;
error ->
+10 -3
View File
@@ -2608,7 +2608,7 @@ process_item_change(UJID) ->
-type admin_action() :: {jid(), affiliation | role,
affiliation() | role(), binary()}.
-spec process_item_change(admin_action(), state(), jid()) -> state() | {error, stanza_error()}.
-spec process_item_change(admin_action(), state(), undefined | jid()) -> state() | {error, stanza_error()}.
process_item_change(Item, SD, UJID) ->
try case Item of
{JID, affiliation, owner, _} when JID#jid.luser == <<"">> ->
@@ -2658,8 +2658,15 @@ process_item_change(Item, SD, UJID) ->
SD1
end
catch E:R ->
?ERROR_MSG("failed to set item ~p from ~s: ~p",
[Item, jid:encode(UJID),
FromSuffix = case UJID of
#jid{} ->
JidString = jid:encode(UJID),
<<" from ", JidString/binary>>;
undefined ->
<<"">>
end,
?ERROR_MSG("failed to set item ~p~s: ~p",
[Item, FromSuffix,
{E, {R, erlang:get_stacktrace()}}]),
{error, xmpp:err_internal_server_error()}
end.
+12 -6
View File
@@ -998,9 +998,8 @@ build_service_limit_record(LimitOpts) ->
build_limit_record(LimitOptsR, remote)}.
get_from_limitopts(LimitOpts, SenderT) ->
[{StanzaT, Number}
|| {SenderT2, StanzaT, Number} <- LimitOpts,
SenderT =:= SenderT2].
{SenderT, Result} = lists:keyfind(SenderT, 1, LimitOpts),
Result.
build_remote_limit_record(LimitOpts, SenderT) ->
build_limit_record(LimitOpts, SenderT).
@@ -1118,6 +1117,13 @@ depends(_Host, _Opts) ->
mod_opt_type(access) ->
fun acl:access_rules_validator/1;
mod_opt_type(host) -> fun iolist_to_binary/1;
mod_opt_type(limits) ->
fun (A) when is_list(A) -> A end;
mod_opt_type(_) -> [access, host, limits].
mod_opt_type({limits, Type}) when (Type == local) or (Type == remote) ->
fun(L) ->
lists:map(
fun ({message, infinite}) -> infinite;
({presence, infinite}) -> infinite;
({message, I}) when is_integer(I) -> I;
({presence, I}) when is_integer(I) -> I
end, L)
end;
mod_opt_type(_) -> [access, host, {limits, local}, {limits, remote}].
+1 -1
View File
@@ -671,7 +671,7 @@ user_queue(User, Server, Query, Lang) ->
Mod = gen_mod:db_mod(LServer, ?MODULE),
Res = user_queue_parse_query(LUser, LServer, Query),
HdrsAll = Mod:read_message_headers(LUser, LServer),
Hdrs = get_messages_subset(US, Server, HdrsAll),
Hdrs = get_messages_subset(User, Server, HdrsAll),
FMsgs = format_user_queue(Hdrs),
[?XC(<<"h1">>,
(str:format(?T(<<"~s's Offline Messages Queue">>),
+8 -2
View File
@@ -181,6 +181,13 @@ count_messages(LUser, LServer) ->
export(_Server) ->
[{offline_msg,
fun(Host, #offline_msg{us = {LUser, LServer}})
when LServer == Host ->
[?SQL("delete from spool where username=%(LUser)s;")];
(_Host, _R) ->
[]
end},
{offline_msg,
fun(Host, #offline_msg{us = {LUser, LServer},
timestamp = TimeStamp, from = From, to = To,
packet = El})
@@ -192,8 +199,7 @@ export(_Server) ->
Packet1, jid:make(LServer),
TimeStamp, <<"Offline Storage">>),
XML = fxml:element_to_binary(xmpp:encode(Packet2)),
[?SQL("delete from spool where username=%(LUser)s;"),
?SQL("insert into spool(username, xml) values ("
[?SQL("insert into spool(username, xml) values ("
"%(LUser)s, %(XML)s);")]
catch _:{xmpp_codec, Why} ->
?ERROR_MSG("failed to decode packet ~p of user ~s@~s: ~s",
+54 -53
View File
@@ -3009,60 +3009,61 @@ c2s_handle_info(C2SState, _) ->
subscribed_nodes_by_jid(NotifyType, SubsByDepth) ->
NodesToDeliver = fun (Depth, Node, Subs, Acc) ->
NodeName = case Node#pubsub_node.nodeid of
{_, N} -> N;
Other -> Other
end,
NodeOptions = Node#pubsub_node.options,
lists:foldl(fun({LJID, SubID, SubOptions}, {JIDs, Recipients}) ->
case is_to_deliver(LJID, NotifyType, Depth, NodeOptions, SubOptions) of
true ->
case state_can_deliver(LJID, SubOptions) of
[] -> {JIDs, Recipients};
JIDsToDeliver ->
lists:foldl(
fun(JIDToDeliver, {JIDsAcc, RecipientsAcc}) ->
case lists:member(JIDToDeliver, JIDs) of
%% check if the JIDs co-accumulator contains the Subscription Jid,
false ->
%% - if not,
%% - add the Jid to JIDs list co-accumulator ;
%% - create a tuple of the Jid, Nidx, and SubID (as list),
%% and add the tuple to the Recipients list co-accumulator
{[JIDToDeliver | JIDsAcc],
[{JIDToDeliver, NodeName, [SubID]}
| RecipientsAcc]};
true ->
%% - if the JIDs co-accumulator contains the Jid
%% get the tuple containing the Jid from the Recipient list co-accumulator
{_, {JIDToDeliver, NodeName1, SubIDs}} =
lists:keysearch(JIDToDeliver, 1, RecipientsAcc),
%% delete the tuple from the Recipients list
% v1 : Recipients1 = lists:keydelete(LJID, 1, Recipients),
% v2 : Recipients1 = lists:keyreplace(LJID, 1, Recipients, {LJID, Nidx1, [SubID | SubIDs]}),
%% add the SubID to the SubIDs list in the tuple,
%% and add the tuple back to the Recipients list co-accumulator
% v1.1 : {JIDs, lists:append(Recipients1, [{LJID, Nidx1, lists:append(SubIDs, [SubID])}])}
% v1.2 : {JIDs, [{LJID, Nidx1, [SubID | SubIDs]} | Recipients1]}
% v2: {JIDs, Recipients1}
{JIDsAcc,
lists:keyreplace(JIDToDeliver, 1,
RecipientsAcc,
{JIDToDeliver, NodeName1,
[SubID | SubIDs]})}
end
end, {JIDs, Recipients}, JIDsToDeliver)
end;
false ->
{JIDs, Recipients}
end
end, Acc, Subs)
end,
NodeName = case Node#pubsub_node.nodeid of
{_, N} -> N;
Other -> Other
end,
NodeOptions = Node#pubsub_node.options,
lists:foldl(fun({LJID, SubID, SubOptions}, {JIDs, Recipients}) ->
case is_to_deliver(LJID, NotifyType, Depth, NodeOptions, SubOptions) of
true ->
case state_can_deliver(LJID, SubOptions) of
[] -> {JIDs, Recipients};
[LJID] -> {JIDs, [{LJID, NodeName, [SubID]} | Recipients]};
JIDsToDeliver ->
lists:foldl(
fun(JIDToDeliver, {JIDsAcc, RecipientsAcc}) ->
case lists:member(JIDToDeliver, JIDs) of
%% check if the JIDs co-accumulator contains the Subscription Jid,
false ->
%% - if not,
%% - add the Jid to JIDs list co-accumulator ;
%% - create a tuple of the Jid, Nidx, and SubID (as list),
%% and add the tuple to the Recipients list co-accumulator
{[JIDToDeliver | JIDsAcc],
[{JIDToDeliver, NodeName, [SubID]}
| RecipientsAcc]};
true ->
%% - if the JIDs co-accumulator contains the Jid
%% get the tuple containing the Jid from the Recipient list co-accumulator
{_, {JIDToDeliver, NodeName1, SubIDs}} =
lists:keysearch(JIDToDeliver, 1, RecipientsAcc),
%% delete the tuple from the Recipients list
% v1 : Recipients1 = lists:keydelete(LJID, 1, Recipients),
% v2 : Recipients1 = lists:keyreplace(LJID, 1, Recipients, {LJID, Nidx1, [SubID | SubIDs]}),
%% add the SubID to the SubIDs list in the tuple,
%% and add the tuple back to the Recipients list co-accumulator
% v1.1 : {JIDs, lists:append(Recipients1, [{LJID, Nidx1, lists:append(SubIDs, [SubID])}])}
% v1.2 : {JIDs, [{LJID, Nidx1, [SubID | SubIDs]} | Recipients1]}
% v2: {JIDs, Recipients1}
{JIDsAcc,
lists:keyreplace(JIDToDeliver, 1,
RecipientsAcc,
{JIDToDeliver, NodeName1,
[SubID | SubIDs]})}
end
end, {JIDs, Recipients}, JIDsToDeliver)
end;
false ->
{JIDs, Recipients}
end
end, Acc, Subs)
end,
DepthsToDeliver = fun({Depth, SubsByNode}, Acc1) ->
lists:foldl(fun({Node, Subs}, Acc2) ->
NodesToDeliver(Depth, Node, Subs, Acc2)
end, Acc1, SubsByNode)
end,
lists:foldl(fun({Node, Subs}, Acc2) ->
NodesToDeliver(Depth, Node, Subs, Acc2)
end, Acc1, SubsByNode)
end,
{_, JIDSubs} = lists:foldl(DepthsToDeliver, {[], []}, SubsByDepth),
JIDSubs.
+2
View File
@@ -441,6 +441,7 @@ update_num_stanzas_in(#{mgmt_state := MgmtState,
update_num_stanzas_in(State, _El) ->
State.
-spec send_rack(state()) -> state().
send_rack(#{mgmt_ack_timer := _} = State) ->
State;
send_rack(#{mgmt_xmlns := Xmlns,
@@ -450,6 +451,7 @@ send_rack(#{mgmt_xmlns := Xmlns,
State1 = State#{mgmt_ack_timer => TRef, mgmt_stanzas_req => NumStanzasOut},
send(State1, #sm_r{xmlns = Xmlns}).
-spec resend_rack(state()) -> state().
resend_rack(#{mgmt_ack_timer := _,
mgmt_queue := Queue,
mgmt_stanzas_out := NumStanzasOut,
+124 -2
View File
@@ -50,7 +50,7 @@ from_dir(ProsodyDir) ->
convert_dir(Path, Host, SubDir)
end, ["vcard", "accounts", "roster",
"private", "config", "offline",
"privacy"])
"privacy", "pubsub"])
end, HostDirs);
{error, Why} = Err ->
?ERROR_MSG("failed to list ~s: ~s",
@@ -115,7 +115,7 @@ maybe_get_scram_auth(Data) ->
#scram{
storedkey = misc:hex_to_base64(proplists:get_value(<<"stored_key">>, Data, <<"">>)),
serverkey = misc:hex_to_base64(proplists:get_value(<<"server_key">>, Data, <<"">>)),
salt = misc:hex_to_base64(proplists:get_value(<<"salt">>, Data, <<"">>)),
salt = base64:encode(proplists:get_value(<<"salt">>, Data, <<"">>)),
iterationcount = round(IC)
};
_ -> <<"">>
@@ -212,6 +212,46 @@ convert_data(Host, "privacy", User, [Data]) ->
end
end, Lists)},
mod_privacy:set_list(Priv);
convert_data(PubSub, "pubsub", NodeId, [Data]) ->
Host = url_decode(PubSub),
Node = url_decode(NodeId),
Type = node_type(Host, Node),
NodeData = convert_node_config(Host, Data),
DefaultConfig = mod_pubsub:config(Host, default_node_config, []),
Owner = proplists:get_value(owner, NodeData),
Options = lists:foldl(
fun({_Opt, undefined}, Acc) ->
Acc;
({Opt, Val}, Acc) ->
lists:keystore(Opt, 1, Acc, {Opt, Val})
end, DefaultConfig, proplists:get_value(options, NodeData)),
case mod_pubsub:tree_action(Host, create_node, [Host, Node, Type, Owner, Options, []]) of
{ok, Nidx} ->
case mod_pubsub:node_action(Host, Type, create_node, [Nidx, Owner]) of
{result, _} ->
Access = open, % always allow subscriptions proplists:get_value(access_model, Options),
Publish = open, % always allow publications proplists:get_value(publish_model, Options),
MaxItems = proplists:get_value(max_items, Options),
Affiliations = proplists:get_value(affiliations, NodeData),
Subscriptions = proplists:get_value(subscriptions, NodeData),
Items = proplists:get_value(items, NodeData),
[mod_pubsub:node_action(Host, Type, set_affiliation,
[Nidx, Entity, Aff])
|| {Entity, Aff} <- Affiliations, Entity =/= Owner],
[mod_pubsub:node_action(Host, Type, subscribe_node,
[Nidx, jid:make(Entity), Entity, Access, never, [], [], []])
|| Entity <- Subscriptions],
[mod_pubsub:node_action(Host, Type, publish_item,
[Nidx, Publisher, Publish, MaxItems, ItemId, Payload, []])
|| {ItemId, Publisher, Payload} <- Items];
Error ->
Error
end;
Error ->
?ERROR_MSG("failed to import pubsub node ~s on host ~s:~n~p",
[Node, Host, NodeData]),
Error
end;
convert_data(_Host, _Type, _User, _Data) ->
ok.
@@ -333,6 +373,88 @@ convert_privacy_item({_, Item}) ->
match_presence_in = MatchPresIn,
match_presence_out = MatchPresOut}.
url_decode(Encoded) ->
url_decode(Encoded, <<>>).
url_decode(<<$%, Hi, Lo, Tail/binary>>, Acc) ->
Hex = list_to_integer([Hi, Lo], 16),
url_decode(Tail, <<Acc/binary, Hex>>);
url_decode(<<H, Tail/binary>>, Acc) ->
url_decode(Tail, <<Acc/binary, H>>);
url_decode(<<>>, Acc) ->
Acc.
node_type(_Host, <<"urn:", _Tail/binary>>) -> <<"pep">>;
node_type(_Host, <<"http:", _Tail/binary>>) -> <<"pep">>;
node_type(_Host, <<"https:", _Tail/binary>>) -> <<"pep">>;
node_type(Host, _) -> hd(mod_pubsub:plugins(Host)).
max_items(Config, Default) ->
case round(proplists:get_value(<<"max_items">>, Config, Default)) of
I when I =< 0 -> Default;
I -> I
end.
convert_node_affiliations(Data) ->
lists:flatmap(
fun({J, Aff}) ->
try jid:decode(J) of
JID ->
[{JID, misc:binary_to_atom(Aff)}]
catch _:{bad_jid, _} ->
[]
end
end, proplists:get_value(<<"affiliations">>, Data, [])).
convert_node_subscriptions(Data) ->
lists:flatmap(
fun({J, true}) ->
try jid:decode(J) of
JID ->
[jid:tolower(JID)]
catch _:{bad_jid, _} ->
[]
end;
(_) ->
[]
end, proplists:get_value(<<"subscribers">>, Data, [])).
convert_node_items(Host, Data) ->
Authors = proplists:get_value(<<"data_author">>, Data, []),
lists:flatmap(
fun({ItemId, Item}) ->
try catch jid:decode(proplists:get_value(ItemId, Authors, Host)) of
JID ->
[El] = deserialize(Item),
[{ItemId, JID, El#xmlel.children}]
catch _:{bad_jid, _} ->
[]
end
end, proplists:get_value(<<"data">>, Data, [])).
convert_node_config(Host, Data) ->
Config = proplists:get_value(<<"config">>, Data, []),
[{affiliations, convert_node_affiliations(Data)},
{subscriptions, convert_node_subscriptions(Data)},
{owner, jid:decode(proplists:get_value(<<"creator">>, Config, Host))},
{items, convert_node_items(Host, Data)},
{options, [
{deliver_notifications,
proplists:get_value(<<"deliver_notifications">>, Config, true)},
{deliver_payloads,
proplists:get_value(<<"deliver_payloads">>, Config, true)},
{persist_items,
proplists:get_value(<<"persist_items">>, Config, true)},
{max_items,
max_items(Config, 10)},
{access_model,
misc:binary_to_atom(proplists:get_value(<<"access_model">>, Config, <<"open">>))},
{publish_model,
misc:binary_to_atom(proplists:get_value(<<"publish_model">>, Config, <<"publishers">>))},
{title,
proplists:get_value(<<"title">>, Config, <<"">>)}
]}
].
el_to_offline_msg(LUser, LServer, #xmlel{attrs = Attrs} = El) ->
try
TS = xmpp_util:decode_timestamp(
+1 -1
View File
@@ -99,7 +99,7 @@ run_elixir_test(Func) ->
'Elixir.Code':load_file(list_to_binary(filename:join(test_dir(), atom_to_list(Func)))),
%% I did not use map syntax, so that this file can still be build under R16
'Elixir.ExUnit.Server':cases_loaded(),
catch 'Elixir.ExUnit.Server':cases_loaded(),
ResultMap = 'Elixir.ExUnit':run(),
case maps:find(failures, ResultMap) of
{ok, 0} ->
+4 -4
View File
@@ -45,7 +45,7 @@
-define(ERROR_MSG(Fmt, Args), error_logger:error_msg(Fmt, Args)).
-define(TCP_SEND_TIMEOUT, 32000).
-define(SERVER, ?MODULE).
-define(SERVER, ?MODULE).
-record(state, {listener = make_ref() :: reference()}).
@@ -122,7 +122,7 @@ accept(ListenSocket, Tree) ->
process(Socket, Tree) ->
case gen_tcp:recv(Socket, 0) of
{ok, B} ->
case asn1rt:decode('ELDAPv3', 'LDAPMessage', B) of
case 'ELDAPv3':decode('LDAPMessage', B) of
{ok, Msg} ->
Replies = process_msg(Msg, Tree),
Id = Msg#'LDAPMessage'.messageID,
@@ -131,8 +131,8 @@ process(Socket, Tree) ->
Reply = #'LDAPMessage'{messageID = Id,
protocolOp = ReplyOp},
%%?DEBUG("sent:~n~p", [Reply]),
{ok, Bytes} = asn1rt:encode(
'ELDAPv3', 'LDAPMessage', Reply),
{ok, Bytes} = 'ELDAPv3':encode(
'LDAPMessage', Reply),
gen_tcp:send(Socket, Bytes)
end, Replies),
process(Socket, Tree);
+55 -26
View File
@@ -22,7 +22,11 @@ sub get_deps {
return { } unless $config =~ /\{\s*deps\s*,\s*\[(.*?)\]/s;
my $sdeps = $1;
while ($sdeps =~ /\{\s*(\w+)\s*,\s*".*?"\s*,\s*\{\s*git\s*,\s*"(.*?)"\s*,\s*(?:{\s*tag\s*,\s*"(.*?)"|"(.*?)" )/sg) {
while ($sdeps =~ /\{\s* (\w+) \s*,\s* ".*?" \s*,\s* \{\s*git \s*,\s* "(.*?)" \s*,\s*
(?:
(?:{\s*tag \s*,\s* "(.*?)") |
"(.*?)" |
( \{ (?: (?-1) | [^{}]+ )+ \} ) )/sgx) {
next unless not %fdeps or exists $fdeps{$1};
$deps{$1} = { repo => $2, commit => $3 || $4 };
}
@@ -52,11 +56,11 @@ sub update_deps_repos {
if (not -d $dd) {
say "Downloading $dep...";
my $repo = $deps->{$dep}->{repo};
$repo =~ s/^https?/git/;
$repo =~ s!^https?://github.com/!git\@github.com:!;
system("git", "-C", ".deps-update", "clone", $repo);
} elsif (time() - stat($dd)->mtime > 24 * 60 * 60) {
say "Updating $dep...";
system("git", "-C", $dd, "fetch");
system("git", "-C", $dd, "pull");
touch($dd)
}
}
@@ -130,7 +134,7 @@ sub update_deps_versions {
my $config = slurp $config_path;
for (keys %deps) {
$config =~ s/(\{\s*$_\s*,\s*".*?"\s*,\s*\{\s*git\s*,\s*".*?"\s*,\s*)(?:{\s*tag\s*,\s*"(.*?)"\s*}|"(.*?)" )/$1\{tag, "$deps{$_}"}/s;
$config =~ s/(\{\s*$_\s*,\s*".*?"\s*,\s*\{\s*git\s*,\s*".*?"\s*,\s*)(?:{\s*tag\s*,\s*"(.*?)"\s*}|"(.*?)")/$1\{tag, "$deps{$_}"}/s;
}
write_file($config_path, $config);
@@ -218,10 +222,19 @@ sub schedule_operation {
my $idx = first { $operations[$_]->{dep} eq $dep } 0..$#operations;
if (defined $idx) {
push @{$operations[$idx]->{reasons}}, $reason;
push @{$operations[$idx]->{operations}}, $op;
my $mop = $operations[$idx];
if (defined $op) {
my $oidx = first { $mop->{operations}->[$_]->[0] eq $op->[0] } 0..$#{$mop->{operations}};
if (defined $oidx) {
$mop->{reasons}->[$oidx] = $reason;
$mop->{operations}->[$oidx] = $op;
} else {
push @{$mop->{reasons}}, $reason;
push @{$mop->{operations}}, $op;
}
}
return if $type eq "update";
$operations[$idx]->{type} = $type;
$mop->{type} = $type;
$info_updates{$dep}->{new_commits} = [];
return;
}
@@ -350,7 +363,9 @@ while (1) {
for my $dep (keys %$top_deps) {
for my $sdep (keys %{$sub_deps->{$dep}}) {
next if $sub_deps->{$dep}->{$sdep}->{commit} eq $top_deps->{$sdep}->{commit};
next if not defined $top_deps->{$sdep} or
$sub_deps->{$dep}->{$sdep}->{commit} eq $top_deps->{$sdep}->{commit};
say "$dep $sdep ",$sub_deps->{$dep}->{$sdep}->{commit}," <=> $sdep ",$top_deps->{$sdep}->{commit};
schedule_operation("update", $dep, $git_info->{$dep}->{new_tag},
"Updating $sdep to version $top_deps->{$sdep}->{commit}.", [$sdep, $top_deps->{$sdep}->{commit}]);
}
@@ -364,26 +379,40 @@ while (1) {
$git_info = deps_git_info();
$sub_deps = sub_deps();
my %top_changes;
print color("bold blue"), "List of operations:\n", color("reset");
for my $op (@operations) {
update_changelog($op->{dep}, $op->{version}, @{$op->{reasons}})
if @{$op->{reasons}};
update_deps_versions(".deps-update/$op->{dep}/rebar.config", unpairs(@{$op->{operations}}))
if @{$op->{operations}};
if ($git_info->{$op->{dep}}->{last_tag} ne $op->{version}) {
update_app_src($op->{dep}, $op->{version});
git_tag($op->{dep}, $op->{version}, "Release $op->{version}");
}
$top_changes{$op->{dep}} = $op->{version};
}
update_deps_versions("rebar.config", %top_changes);
for my $op (@operations) {
if ($git_info->{$op->{dep}}->{last_tag} ne $op->{version}) {
git_push($op->{dep});
print color("red"), $op->{dep}, color("reset"), " ($top_deps->{$op->{dep}}->{commit} -> $op->{version})";
if (@{$op->{operations}}) {
say ":";
say " $_->[0] -> $_->[1]" for @{$op->{operations}};
} else {
say "";
}
}
last;
say "";
my $cmd = show_commands(A => "Apply", E => "Exit");
if ($cmd eq "A") {
my %top_changes;
for my $op (@operations) {
update_changelog($op->{dep}, $op->{version}, @{$op->{reasons}})
if @{$op->{reasons}};
update_deps_versions(".deps-update/$op->{dep}/rebar.config", unpairs(@{$op->{operations}}))
if @{$op->{operations}};
if ($git_info->{$op->{dep}}->{last_tag} ne $op->{version}) {
update_app_src($op->{dep}, $op->{version});
git_tag($op->{dep}, $op->{version}, "Release $op->{version}");
}
$top_changes{$op->{dep}} = $op->{version};
}
update_deps_versions("rebar.config", %top_changes);
for my $op (@operations) {
if ($git_info->{$op->{dep}}->{last_tag} ne $op->{version}) {
git_push($op->{dep});
}
}
last;
}
}
}