Merging bug 24945 into default
This commit is contained in:
commit
bf96c3de07
|
@ -720,7 +720,7 @@
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><cmdsynopsis><command>list_user_permissions</command> <arg choice="opt">-p <replaceable>vhostpath</replaceable></arg> <arg choice="req"><replaceable>username</replaceable></arg></cmdsynopsis></term>
|
<term><cmdsynopsis><command>list_user_permissions</command> <arg choice="req"><replaceable>username</replaceable></arg></cmdsynopsis></term>
|
||||||
<listitem>
|
<listitem>
|
||||||
<variablelist>
|
<variablelist>
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
|
@ -978,7 +978,8 @@
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term>type</term>
|
<term>type</term>
|
||||||
<listitem><para>The exchange type (one of [<command>direct</command>,
|
<listitem><para>The exchange type (such as
|
||||||
|
[<command>direct</command>,
|
||||||
<command>topic</command>, <command>headers</command>,
|
<command>topic</command>, <command>headers</command>,
|
||||||
<command>fanout</command>]).</para></listitem>
|
<command>fanout</command>]).</para></listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
12
src/gm.erl
12
src/gm.erl
|
@ -693,9 +693,13 @@ terminate(Reason, State = #state { module = Module,
|
||||||
code_change(_OldVsn, State, _Extra) ->
|
code_change(_OldVsn, State, _Extra) ->
|
||||||
{ok, State}.
|
{ok, State}.
|
||||||
|
|
||||||
prioritise_info(flush, _State) -> 1;
|
prioritise_info(flush, _State) ->
|
||||||
prioritise_info({'DOWN', _MRef, process, _Pid, _Reason}, _State) -> 1;
|
1;
|
||||||
prioritise_info(_ , _State) -> 0.
|
prioritise_info({'DOWN', _MRef, process, _Pid, _Reason},
|
||||||
|
#state { members_state = MS }) when MS /= undefined ->
|
||||||
|
1;
|
||||||
|
prioritise_info(_, _State) ->
|
||||||
|
0.
|
||||||
|
|
||||||
|
|
||||||
handle_msg(check_neighbours, State) ->
|
handle_msg(check_neighbours, State) ->
|
||||||
|
@ -853,7 +857,7 @@ flush_broadcast_buffer(State = #state { self = Self,
|
||||||
members_state = MembersState,
|
members_state = MembersState,
|
||||||
broadcast_buffer = Buffer,
|
broadcast_buffer = Buffer,
|
||||||
pub_count = PubCount }) ->
|
pub_count = PubCount }) ->
|
||||||
[{PubCount, _Msg}|_] = Buffer,
|
[{PubCount, _Msg}|_] = Buffer, %% ASSERTION match on PubCount
|
||||||
Pubs = lists:reverse(Buffer),
|
Pubs = lists:reverse(Buffer),
|
||||||
Activity = activity_cons(Self, Pubs, [], activity_nil()),
|
Activity = activity_cons(Self, Pubs, [], activity_nil()),
|
||||||
ok = maybe_send_activity(activity_finalise(Activity), State),
|
ok = maybe_send_activity(activity_finalise(Activity), State),
|
||||||
|
|
|
@ -26,6 +26,61 @@
|
||||||
-define(NODE_OPT, "-n").
|
-define(NODE_OPT, "-n").
|
||||||
-define(VHOST_OPT, "-p").
|
-define(VHOST_OPT, "-p").
|
||||||
|
|
||||||
|
-define(QUIET_DEF, {?QUIET_OPT, flag}).
|
||||||
|
-define(NODE_DEF(Node), {?NODE_OPT, {option, Node}}).
|
||||||
|
-define(VHOST_DEF, {?VHOST_OPT, {option, "/"}}).
|
||||||
|
|
||||||
|
-define(GLOBAL_DEFS(Node), [?QUIET_DEF, ?NODE_DEF(Node)]).
|
||||||
|
|
||||||
|
-define(COMMANDS,
|
||||||
|
[stop,
|
||||||
|
stop_app,
|
||||||
|
start_app,
|
||||||
|
wait,
|
||||||
|
reset,
|
||||||
|
force_reset,
|
||||||
|
rotate_logs,
|
||||||
|
|
||||||
|
cluster,
|
||||||
|
force_cluster,
|
||||||
|
cluster_status,
|
||||||
|
|
||||||
|
add_user,
|
||||||
|
delete_user,
|
||||||
|
change_password,
|
||||||
|
clear_password,
|
||||||
|
set_user_tags,
|
||||||
|
list_users,
|
||||||
|
|
||||||
|
add_vhost,
|
||||||
|
delete_vhost,
|
||||||
|
list_vhosts,
|
||||||
|
{set_permissions, [?VHOST_DEF]},
|
||||||
|
{clear_permissions, [?VHOST_DEF]},
|
||||||
|
{list_permissions, [?VHOST_DEF]},
|
||||||
|
list_user_permissions,
|
||||||
|
|
||||||
|
set_parameter,
|
||||||
|
clear_parameter,
|
||||||
|
list_parameters,
|
||||||
|
|
||||||
|
{list_queues, [?VHOST_DEF]},
|
||||||
|
{list_exchanges, [?VHOST_DEF]},
|
||||||
|
{list_bindings, [?VHOST_DEF]},
|
||||||
|
{list_connections, [?VHOST_DEF]},
|
||||||
|
list_channels,
|
||||||
|
{list_consumers, [?VHOST_DEF]},
|
||||||
|
status,
|
||||||
|
environment,
|
||||||
|
report,
|
||||||
|
eval,
|
||||||
|
|
||||||
|
close_connection,
|
||||||
|
{trace_on, [?VHOST_DEF]},
|
||||||
|
{trace_off, [?VHOST_DEF]},
|
||||||
|
set_vm_memory_high_watermark
|
||||||
|
]).
|
||||||
|
|
||||||
-define(GLOBAL_QUERIES,
|
-define(GLOBAL_QUERIES,
|
||||||
[{"Connections", rabbit_networking, connection_info_all,
|
[{"Connections", rabbit_networking, connection_info_all,
|
||||||
connection_info_keys},
|
connection_info_keys},
|
||||||
|
@ -57,19 +112,18 @@
|
||||||
|
|
||||||
start() ->
|
start() ->
|
||||||
{ok, [[NodeStr|_]|_]} = init:get_argument(nodename),
|
{ok, [[NodeStr|_]|_]} = init:get_argument(nodename),
|
||||||
{[Command0 | Args], Opts} =
|
{Command, Opts, Args} =
|
||||||
case rabbit_misc:get_options([{flag, ?QUIET_OPT},
|
case rabbit_misc:parse_arguments(?COMMANDS, ?GLOBAL_DEFS(NodeStr),
|
||||||
{option, ?NODE_OPT, NodeStr},
|
init:get_plain_arguments())
|
||||||
{option, ?VHOST_OPT, "/"}],
|
of
|
||||||
init:get_plain_arguments()) of
|
{ok, Res} -> Res;
|
||||||
{[], _Opts} -> usage();
|
no_command -> print_error("could not recognise command", []),
|
||||||
CmdArgsAndOpts -> CmdArgsAndOpts
|
usage()
|
||||||
end,
|
end,
|
||||||
Opts1 = [case K of
|
Opts1 = [case K of
|
||||||
?NODE_OPT -> {?NODE_OPT, rabbit_nodes:make(V)};
|
?NODE_OPT -> {?NODE_OPT, rabbit_nodes:make(V)};
|
||||||
_ -> {K, V}
|
_ -> {K, V}
|
||||||
end || {K, V} <- Opts],
|
end || {K, V} <- Opts],
|
||||||
Command = list_to_atom(Command0),
|
|
||||||
Quiet = proplists:get_bool(?QUIET_OPT, Opts1),
|
Quiet = proplists:get_bool(?QUIET_OPT, Opts1),
|
||||||
Node = proplists:get_value(?NODE_OPT, Opts1),
|
Node = proplists:get_value(?NODE_OPT, Opts1),
|
||||||
Inform = case Quiet of
|
Inform = case Quiet of
|
||||||
|
@ -195,7 +249,6 @@ action(force_cluster, Node, ClusterNodeSs, _Opts, Inform) ->
|
||||||
action(wait, Node, [PidFile], _Opts, Inform) ->
|
action(wait, Node, [PidFile], _Opts, Inform) ->
|
||||||
Inform("Waiting for ~p", [Node]),
|
Inform("Waiting for ~p", [Node]),
|
||||||
wait_for_application(Node, PidFile, rabbit, Inform);
|
wait_for_application(Node, PidFile, rabbit, Inform);
|
||||||
|
|
||||||
action(wait, Node, [PidFile, App], _Opts, Inform) ->
|
action(wait, Node, [PidFile, App], _Opts, Inform) ->
|
||||||
Inform("Waiting for ~p on ~p", [App, Node]),
|
Inform("Waiting for ~p on ~p", [App, Node]),
|
||||||
wait_for_application(Node, PidFile, list_to_atom(App), Inform);
|
wait_for_application(Node, PidFile, list_to_atom(App), Inform);
|
||||||
|
|
|
@ -49,7 +49,7 @@
|
||||||
-export([version_compare/2, version_compare/3]).
|
-export([version_compare/2, version_compare/3]).
|
||||||
-export([dict_cons/3, orddict_cons/3, gb_trees_cons/3]).
|
-export([dict_cons/3, orddict_cons/3, gb_trees_cons/3]).
|
||||||
-export([gb_trees_fold/3, gb_trees_foreach/2]).
|
-export([gb_trees_fold/3, gb_trees_foreach/2]).
|
||||||
-export([get_options/2]).
|
-export([parse_arguments/3]).
|
||||||
-export([all_module_attributes/1, build_acyclic_graph/3]).
|
-export([all_module_attributes/1, build_acyclic_graph/3]).
|
||||||
-export([now_ms/0]).
|
-export([now_ms/0]).
|
||||||
-export([const_ok/0, const/1]).
|
-export([const_ok/0, const/1]).
|
||||||
|
@ -72,7 +72,7 @@
|
||||||
-type(ok_or_error() :: rabbit_types:ok_or_error(any())).
|
-type(ok_or_error() :: rabbit_types:ok_or_error(any())).
|
||||||
-type(thunk(T) :: fun(() -> T)).
|
-type(thunk(T) :: fun(() -> T)).
|
||||||
-type(resource_name() :: binary()).
|
-type(resource_name() :: binary()).
|
||||||
-type(optdef() :: {flag, string()} | {option, string(), any()}).
|
-type(optdef() :: flag | {option, string()}).
|
||||||
-type(channel_or_connection_exit()
|
-type(channel_or_connection_exit()
|
||||||
:: rabbit_types:channel_exit() | rabbit_types:connection_exit()).
|
:: rabbit_types:channel_exit() | rabbit_types:connection_exit()).
|
||||||
-type(digraph_label() :: term()).
|
-type(digraph_label() :: term()).
|
||||||
|
@ -182,8 +182,12 @@
|
||||||
-spec(gb_trees_fold/3 :: (fun ((any(), any(), A) -> A), A, gb_tree()) -> A).
|
-spec(gb_trees_fold/3 :: (fun ((any(), any(), A) -> A), A, gb_tree()) -> A).
|
||||||
-spec(gb_trees_foreach/2 ::
|
-spec(gb_trees_foreach/2 ::
|
||||||
(fun ((any(), any()) -> any()), gb_tree()) -> 'ok').
|
(fun ((any(), any()) -> any()), gb_tree()) -> 'ok').
|
||||||
-spec(get_options/2 :: ([optdef()], [string()])
|
-spec(parse_arguments/3 ::
|
||||||
-> {[string()], [{string(), any()}]}).
|
([{atom(), [{string(), optdef()}]} | atom()],
|
||||||
|
[{string(), optdef()}],
|
||||||
|
[string()])
|
||||||
|
-> {'ok', {atom(), [{string(), string()}], [string()]}} |
|
||||||
|
'no_command').
|
||||||
-spec(all_module_attributes/1 :: (atom()) -> [{atom(), [term()]}]).
|
-spec(all_module_attributes/1 :: (atom()) -> [{atom(), [term()]}]).
|
||||||
-spec(build_acyclic_graph/3 ::
|
-spec(build_acyclic_graph/3 ::
|
||||||
(graph_vertex_fun(), graph_edge_fun(), [{atom(), [term()]}])
|
(graph_vertex_fun(), graph_edge_fun(), [{atom(), [term()]}])
|
||||||
|
@ -736,39 +740,63 @@ gb_trees_fold1(Fun, Acc, {Key, Val, It}) ->
|
||||||
gb_trees_foreach(Fun, Tree) ->
|
gb_trees_foreach(Fun, Tree) ->
|
||||||
gb_trees_fold(fun (Key, Val, Acc) -> Fun(Key, Val), Acc end, ok, Tree).
|
gb_trees_fold(fun (Key, Val, Acc) -> Fun(Key, Val), Acc end, ok, Tree).
|
||||||
|
|
||||||
%% Separate flags and options from arguments.
|
%% Takes:
|
||||||
%% get_options([{flag, "-q"}, {option, "-p", "/"}],
|
%% * A list of [{atom(), [{string(), optdef()]} | atom()], where the atom()s
|
||||||
%% ["set_permissions","-p","/","guest",
|
%% are the accepted commands and the optional [string()] is the list of
|
||||||
%% "-q",".*",".*",".*"])
|
%% accepted options for that command
|
||||||
%% == {["set_permissions","guest",".*",".*",".*"],
|
%% * A list [{string(), optdef()}] of options valid for all commands
|
||||||
%% [{"-q",true},{"-p","/"}]}
|
%% * The list of arguments given by the user
|
||||||
get_options(Defs, As) ->
|
%%
|
||||||
lists:foldl(fun(Def, {AsIn, RsIn}) ->
|
%% Returns either {ok, {atom(), [{string(), string()}], [string()]} which are
|
||||||
{K, {AsOut, V}} =
|
%% respectively the command, the key-value pairs of the options and the leftover
|
||||||
case Def of
|
%% arguments; or no_command if no command could be parsed.
|
||||||
{flag, Key} ->
|
parse_arguments(Commands, GlobalDefs, As) ->
|
||||||
{Key, get_flag(Key, AsIn)};
|
lists:foldl(maybe_process_opts(GlobalDefs, As), no_command, Commands).
|
||||||
{option, Key, Default} ->
|
|
||||||
{Key, get_option(Key, Default, AsIn)}
|
|
||||||
end,
|
|
||||||
{AsOut, [{K, V} | RsIn]}
|
|
||||||
end, {As, []}, Defs).
|
|
||||||
|
|
||||||
get_option(K, _Default, [K, V | As]) ->
|
maybe_process_opts(GDefs, As) ->
|
||||||
{As, V};
|
fun({C, Os}, no_command) ->
|
||||||
get_option(K, Default, [Nk | As]) ->
|
process_opts(atom_to_list(C), dict:from_list(GDefs ++ Os), As);
|
||||||
{As1, V} = get_option(K, Default, As),
|
(C, no_command) ->
|
||||||
{[Nk | As1], V};
|
(maybe_process_opts(GDefs, As))({C, []}, no_command);
|
||||||
get_option(_, Default, As) ->
|
(_, {ok, Res}) ->
|
||||||
{As, Default}.
|
{ok, Res}
|
||||||
|
end.
|
||||||
|
|
||||||
get_flag(K, [K | As]) ->
|
process_opts(C, Defs, As0) ->
|
||||||
{As, true};
|
KVs0 = dict:map(fun (_, flag) -> false;
|
||||||
get_flag(K, [Nk | As]) ->
|
(_, {option, V}) -> V
|
||||||
{As1, V} = get_flag(K, As),
|
end, Defs),
|
||||||
{[Nk | As1], V};
|
process_opts(Defs, C, As0, not_found, KVs0, []).
|
||||||
get_flag(_, []) ->
|
|
||||||
{[], false}.
|
%% Consume flags/options until you find the correct command. If there are no
|
||||||
|
%% arguments or the first argument is not the command we're expecting, fail.
|
||||||
|
%% Arguments to this are: definitions, cmd we're looking for, args we
|
||||||
|
%% haven't parsed, whether we have found the cmd, options we've found,
|
||||||
|
%% plain args we've found.
|
||||||
|
process_opts(_Defs, C, [], found, KVs, Outs) ->
|
||||||
|
{ok, {list_to_atom(C), dict:to_list(KVs), lists:reverse(Outs)}};
|
||||||
|
process_opts(_Defs, _C, [], not_found, _, _) ->
|
||||||
|
no_command;
|
||||||
|
process_opts(Defs, C, [A | As], Found, KVs, Outs) ->
|
||||||
|
OptType = case dict:find(A, Defs) of
|
||||||
|
error -> none;
|
||||||
|
{ok, flag} -> flag;
|
||||||
|
{ok, {option, _}} -> option
|
||||||
|
end,
|
||||||
|
case {OptType, C, Found} of
|
||||||
|
{flag, _, _} -> process_opts(
|
||||||
|
Defs, C, As, Found, dict:store(A, true, KVs),
|
||||||
|
Outs);
|
||||||
|
{option, _, _} -> case As of
|
||||||
|
[] -> no_command;
|
||||||
|
[V | As1] -> process_opts(
|
||||||
|
Defs, C, As1, Found,
|
||||||
|
dict:store(A, V, KVs), Outs)
|
||||||
|
end;
|
||||||
|
{none, A, _} -> process_opts(Defs, C, As, found, KVs, Outs);
|
||||||
|
{none, _, found} -> process_opts(Defs, C, As, found, KVs, [A | Outs]);
|
||||||
|
{none, _, _} -> no_command
|
||||||
|
end.
|
||||||
|
|
||||||
now_ms() ->
|
now_ms() ->
|
||||||
timer:now_diff(now(), {0,0,0}) div 1000.
|
timer:now_diff(now(), {0,0,0}) div 1000.
|
||||||
|
|
|
@ -25,6 +25,18 @@
|
||||||
-define(ENABLED_OPT, "-E").
|
-define(ENABLED_OPT, "-E").
|
||||||
-define(ENABLED_ALL_OPT, "-e").
|
-define(ENABLED_ALL_OPT, "-e").
|
||||||
|
|
||||||
|
-define(VERBOSE_DEF, {?VERBOSE_OPT, flag}).
|
||||||
|
-define(MINIMAL_DEF, {?MINIMAL_OPT, flag}).
|
||||||
|
-define(ENABLED_DEF, {?ENABLED_OPT, flag}).
|
||||||
|
-define(ENABLED_ALL_DEF, {?ENABLED_ALL_OPT, flag}).
|
||||||
|
|
||||||
|
-define(GLOBAL_DEFS, []).
|
||||||
|
|
||||||
|
-define(COMMANDS,
|
||||||
|
[{list, [?VERBOSE_DEF, ?MINIMAL_DEF, ?ENABLED_DEF, ?ENABLED_ALL_DEF]},
|
||||||
|
enable,
|
||||||
|
disable]).
|
||||||
|
|
||||||
%%----------------------------------------------------------------------------
|
%%----------------------------------------------------------------------------
|
||||||
|
|
||||||
-ifdef(use_specs).
|
-ifdef(use_specs).
|
||||||
|
@ -45,16 +57,15 @@ start() ->
|
||||||
{ok, [[PluginsFile|_]|_]} =
|
{ok, [[PluginsFile|_]|_]} =
|
||||||
init:get_argument(enabled_plugins_file),
|
init:get_argument(enabled_plugins_file),
|
||||||
{ok, [[PluginsDir|_]|_]} = init:get_argument(plugins_dist_dir),
|
{ok, [[PluginsDir|_]|_]} = init:get_argument(plugins_dist_dir),
|
||||||
{[Command0 | Args], Opts} =
|
{Command, Opts, Args} =
|
||||||
case rabbit_misc:get_options([{flag, ?VERBOSE_OPT},
|
case rabbit_misc:parse_arguments(?COMMANDS, ?GLOBAL_DEFS,
|
||||||
{flag, ?MINIMAL_OPT},
|
init:get_plain_arguments())
|
||||||
{flag, ?ENABLED_OPT},
|
of
|
||||||
{flag, ?ENABLED_ALL_OPT}],
|
{ok, Res} -> Res;
|
||||||
init:get_plain_arguments()) of
|
no_command -> print_error("could not recognise command", []),
|
||||||
{[], _Opts} -> usage();
|
usage()
|
||||||
CmdArgsAndOpts -> CmdArgsAndOpts
|
|
||||||
end,
|
end,
|
||||||
Command = list_to_atom(Command0),
|
|
||||||
PrintInvalidCommandError =
|
PrintInvalidCommandError =
|
||||||
fun () ->
|
fun () ->
|
||||||
print_error("invalid command '~s'",
|
print_error("invalid command '~s'",
|
||||||
|
@ -396,4 +407,3 @@ report_change() ->
|
||||||
_ ->
|
_ ->
|
||||||
ok
|
ok
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
|
|
@ -50,7 +50,7 @@ all_tests() ->
|
||||||
passed = test_app_management(),
|
passed = test_app_management(),
|
||||||
passed = test_log_management_during_startup(),
|
passed = test_log_management_during_startup(),
|
||||||
passed = test_statistics(),
|
passed = test_statistics(),
|
||||||
passed = test_option_parser(),
|
passed = test_arguments_parser(),
|
||||||
passed = test_cluster_management(),
|
passed = test_cluster_management(),
|
||||||
passed = test_user_management(),
|
passed = test_user_management(),
|
||||||
passed = test_runtime_parameters(),
|
passed = test_runtime_parameters(),
|
||||||
|
@ -801,27 +801,57 @@ test_log_management_during_startup() ->
|
||||||
ok = control_action(start_app, []),
|
ok = control_action(start_app, []),
|
||||||
passed.
|
passed.
|
||||||
|
|
||||||
test_option_parser() ->
|
test_arguments_parser() ->
|
||||||
%% command and arguments should just pass through
|
GlobalOpts1 = [{"-f1", flag}, {"-o1", {option, "foo"}}],
|
||||||
ok = check_get_options({["mock_command", "arg1", "arg2"], []},
|
Commands1 = [command1, {command2, [{"-f2", flag}, {"-o2", {option, "bar"}}]}],
|
||||||
[], ["mock_command", "arg1", "arg2"]),
|
|
||||||
|
|
||||||
%% get flags
|
GetOptions =
|
||||||
ok = check_get_options(
|
fun (Args) ->
|
||||||
{["mock_command", "arg1"], [{"-f", true}, {"-f2", false}]},
|
rabbit_misc:parse_arguments(Commands1, GlobalOpts1, Args)
|
||||||
[{flag, "-f"}, {flag, "-f2"}], ["mock_command", "arg1", "-f"]),
|
end,
|
||||||
|
|
||||||
%% get options
|
check_parse_arguments(no_command, GetOptions, []),
|
||||||
ok = check_get_options(
|
check_parse_arguments(no_command, GetOptions, ["foo", "bar"]),
|
||||||
{["mock_command"], [{"-foo", "bar"}, {"-baz", "notbaz"}]},
|
check_parse_arguments(
|
||||||
[{option, "-foo", "notfoo"}, {option, "-baz", "notbaz"}],
|
{ok, {command1, [{"-f1", false}, {"-o1", "foo"}], []}},
|
||||||
["mock_command", "-foo", "bar"]),
|
GetOptions, ["command1"]),
|
||||||
|
check_parse_arguments(
|
||||||
|
{ok, {command1, [{"-f1", false}, {"-o1", "blah"}], []}},
|
||||||
|
GetOptions, ["command1", "-o1", "blah"]),
|
||||||
|
check_parse_arguments(
|
||||||
|
{ok, {command1, [{"-f1", true}, {"-o1", "foo"}], []}},
|
||||||
|
GetOptions, ["command1", "-f1"]),
|
||||||
|
check_parse_arguments(
|
||||||
|
{ok, {command1, [{"-f1", false}, {"-o1", "blah"}], []}},
|
||||||
|
GetOptions, ["-o1", "blah", "command1"]),
|
||||||
|
check_parse_arguments(
|
||||||
|
{ok, {command1, [{"-f1", false}, {"-o1", "blah"}], ["quux"]}},
|
||||||
|
GetOptions, ["-o1", "blah", "command1", "quux"]),
|
||||||
|
check_parse_arguments(
|
||||||
|
{ok, {command1, [{"-f1", true}, {"-o1", "blah"}], ["quux", "baz"]}},
|
||||||
|
GetOptions, ["command1", "quux", "-f1", "-o1", "blah", "baz"]),
|
||||||
|
%% For duplicate flags, the last one counts
|
||||||
|
check_parse_arguments(
|
||||||
|
{ok, {command1, [{"-f1", false}, {"-o1", "second"}], []}},
|
||||||
|
GetOptions, ["-o1", "first", "command1", "-o1", "second"]),
|
||||||
|
%% If the flag "eats" the command, the command won't be recognised
|
||||||
|
check_parse_arguments(no_command, GetOptions,
|
||||||
|
["-o1", "command1", "quux"]),
|
||||||
|
%% If a flag eats another flag, the eaten flag won't be recognised
|
||||||
|
check_parse_arguments(
|
||||||
|
{ok, {command1, [{"-f1", false}, {"-o1", "-f1"}], []}},
|
||||||
|
GetOptions, ["command1", "-o1", "-f1"]),
|
||||||
|
|
||||||
%% shuffled and interleaved arguments and options
|
%% Now for some command-specific flags...
|
||||||
ok = check_get_options(
|
check_parse_arguments(
|
||||||
{["a1", "a2", "a3"], [{"-o1", "hello"}, {"-o2", "noto2"}, {"-f", true}]},
|
{ok, {command2, [{"-f1", false}, {"-f2", false},
|
||||||
[{option, "-o1", "noto1"}, {flag, "-f"}, {option, "-o2", "noto2"}],
|
{"-o1", "foo"}, {"-o2", "bar"}], []}},
|
||||||
["-f", "a1", "-o1", "hello", "a2", "a3"]),
|
GetOptions, ["command2"]),
|
||||||
|
|
||||||
|
check_parse_arguments(
|
||||||
|
{ok, {command2, [{"-f1", false}, {"-f2", true},
|
||||||
|
{"-o1", "baz"}, {"-o2", "bar"}], ["quux", "foo"]}},
|
||||||
|
GetOptions, ["-f2", "command2", "quux", "-o1", "baz", "foo"]),
|
||||||
|
|
||||||
passed.
|
passed.
|
||||||
|
|
||||||
|
@ -1605,10 +1635,13 @@ expand_options(As, Bs) ->
|
||||||
end
|
end
|
||||||
end, Bs, As).
|
end, Bs, As).
|
||||||
|
|
||||||
check_get_options({ExpArgs, ExpOpts}, Defs, Args) ->
|
check_parse_arguments(ExpRes, Fun, As) ->
|
||||||
{ExpArgs, ResOpts} = rabbit_misc:get_options(Defs, Args),
|
SortRes =
|
||||||
true = lists:sort(ExpOpts) == lists:sort(ResOpts), % don't care about the order
|
fun (no_command) -> no_command;
|
||||||
ok.
|
({ok, {C, KVs, As1}}) -> {ok, {C, lists:sort(KVs), As1}}
|
||||||
|
end,
|
||||||
|
|
||||||
|
true = SortRes(ExpRes) =:= SortRes(Fun(As)).
|
||||||
|
|
||||||
empty_files(Files) ->
|
empty_files(Files) ->
|
||||||
[case file:read_file_info(File) of
|
[case file:read_file_info(File) of
|
||||||
|
|
Loading…
Reference in New Issue