rabbitmq-server/deps/rabbitmq_cli/lib/rabbitmq/cli/ctl/command_modules.ex

111 lines
2.7 KiB
Elixir
Raw Normal View History

2016-03-05 01:42:43 +08:00
## The contents of this file are subject to the Mozilla Public License
## Version 1.1 (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.mozilla.org/MPL/
##
## Software distributed under the License is distributed on an "AS IS"
## basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
## the License for the specific language governing rights and
## limitations under the License.
##
## The Original Code is RabbitMQ.
##
## The Initial Developer of the Original Code is GoPivotal, Inc.
## Copyright (c) 2007-2016 Pivotal Software, Inc. All rights reserved.
defmodule RabbitMQ.CLI.Ctl.CommandModules do
def module_map do
case Application.get_env(:rabbitmqctl, :commands) do
nil -> load;
val -> val
end
end
def load do
scope = script_scope
commands = load_commands(scope)
Application.put_env(:rabbitmqctl, :commands, commands)
commands
end
def script_scope do
script_name = Path.basename(:escript.script_name()) |> String.to_atom
scopes = Application.get_env(:rabbitmqctl, :scopes, [])
scopes[script_name] || :all
end
defp load_commands(scope) do
modules = loadable_modules()
modules
|> Enum.filter(fn(path) ->
to_string(path) =~ ~r/RabbitMQ.CLI.Ctl.Commands/
end)
|> Enum.map(fn(path) ->
Path.rootname(path, '.beam')
|> String.to_atom
|> Code.ensure_loaded
end)
|> Enum.filter_map(fn({res, _}) -> res == :module end,
fn({_, mod}) -> command_tuple(mod) end)
|> Enum.filter(fn({_, cmd}) -> command_in_scope(cmd, scope) end)
2016-03-05 01:42:43 +08:00
|> Map.new
end
defp loadable_modules do
:code.get_path()
|> Enum.flat_map(fn(path) ->
{:ok, modules} = :erl_prim_loader.list_dir(path)
modules
end)
2016-03-05 01:42:43 +08:00
end
defp command_tuple(cmd) do
2016-03-05 01:42:43 +08:00
{
cmd
|> to_string
|> strip_namespace
|> to_snake_case
|> String.replace_suffix("_command", ""),
cmd
2016-03-05 01:42:43 +08:00
}
end
def strip_namespace(str) do
str
|> String.split(".")
|> List.last
end
def to_snake_case(<<c, str :: binary>>) do
tail = for <<c <- str>>, into: "", do: snake(c)
<<to_lower_char(c), tail :: binary >>
end
defp snake(c) do
if (c >= ?A) and (c <= ?Z) do
<<"_", c+32>>
else
<<c>>
end
end
defp to_lower_char(c) do
if (c >= ?A) and (c <= ?Z) do
c+32
else
c
end
end
defp command_in_scope(_cmd, :all) do
true
end
defp command_in_scope(cmd, scope) do
Code.ensure_loaded(cmd)
if :erlang.function_exported(cmd, :scopes, 0) do
Enum.member?(cmd.scopes(), scope)
end
end
2016-03-05 01:42:43 +08:00
end