From 676f2487adbdef87f3c31d0480e3113f91ca3bff Mon Sep 17 00:00:00 2001 From: Fred Hebert Date: Sun, 21 Dec 2014 12:53:05 -0500 Subject: Dynamic 'do' provider for namespaces Using a namespace such as 'rebar3 lfe new' will look for the 'new' command in 'lfe' namespace without the need for a 'do' provider to be registered in that namespace. Manually checked that 'rebar3 as command' works, as well with 'default' and 'do'. Test suite still needed. --- src/rebar_core.erl | 44 +++++++++++++++++++++++++++++++------------- src/rebar_state.erl | 8 ++++++++ 2 files changed, 39 insertions(+), 13 deletions(-) diff --git a/src/rebar_core.erl b/src/rebar_core.erl index 96ba426..cfe040a 100644 --- a/src/rebar_core.erl +++ b/src/rebar_core.erl @@ -35,23 +35,41 @@ process_command(State, Command) -> %% ? rebar_prv_install_deps:setup_env(State), Providers = rebar_state:providers(State), - TargetProviders = providers:get_target_providers(Command, Providers), - case providers:get_provider(Command, Providers) of - not_found when is_atom(Command) -> - Namespace = Command, - process_command(State, {Namespace, do}); - not_found when is_tuple(Command) -> - case Command of - {default,Cmd} -> - {error, io_lib:format("Command ~p not found", [Cmd])}; - {Namespace,Cmd} -> + Namespace = rebar_state:namespace(State), + {TargetProviders, CommandProvider} = + case Namespace of + undefined -> + %% undefined namespace means 'default', but on the first run; + %% it is used as an implicit counter for the first vs. subsequent + %% runs. + {providers:get_target_providers(Command, Providers, default), + providers:get_provider(Command, Providers, default)}; + _ -> + {providers:get_target_providers(Command, Providers, Namespace), + providers:get_provider(Command, Providers, Namespace)} + end, + case CommandProvider of + not_found -> + case Namespace of + undefined -> + %% On the first run (Namespace = undefined), we use the + %% unfound command name to be a namespace. + do([{default, do} | TargetProviders], + rebar_state:namespace(State, Command)); + default -> + {error, io_lib:format("Command ~p not found", [Command])}; + _ -> {error, io_lib:format("Command ~p not found in namespace ~p", - [Cmd, Namespace])} + [Command, Namespace])} end; CommandProvider -> case Command of - Command when Command =:= do - ; Command =:= as -> + Command when Command =:= do, Namespace =:= undefined -> + %% We're definitely in the default namespace. 'do' doesn't + %% properly exist for non-default namespaces outside of + %% dynamic dispatch calls for namespaces. + do(TargetProviders, rebar_state:namespace(State, default)); + Command when Command =:= do; Command =:= as -> do(TargetProviders, State); _ -> Profile = providers:profile(CommandProvider), diff --git a/src/rebar_state.erl b/src/rebar_state.erl index 09becca..657c7d2 100644 --- a/src/rebar_state.erl +++ b/src/rebar_state.erl @@ -23,6 +23,7 @@ project_apps/1, project_apps/2, deps_to_build/1, deps_to_build/2, all_deps/1, all_deps/2, + namespace/1, namespace/2, deps_names/1, @@ -39,6 +40,7 @@ lock = [], current_profiles = [default] :: [atom()], + namespace = undefined :: [atom()], command_args = [], command_parsed_args = [], @@ -220,6 +222,12 @@ all_deps(#state_t{all_deps=Apps}) -> all_deps(State=#state_t{}, NewApps) -> State#state_t{all_deps=NewApps}. +namespace(#state_t{namespace=Namespace}) -> + Namespace. + +namespace(State=#state_t{}, Namespace) -> + State#state_t{namespace=Namespace}. + providers(#state_t{providers=Providers}) -> Providers. -- cgit v1.1