summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFred Hebert <mononcqc@ferd.ca>2015-03-13 16:07:02 +0000
committerFred Hebert <mononcqc@ferd.ca>2015-03-13 16:07:02 +0000
commitad18970cd7bbcffd4d868ab1a9372f4e883a1728 (patch)
treeb57631539fec33348f995e5d88940f6f2257e676
parent400140a4c449076ee91a9cd67716b523b8abf64d (diff)
Fix #267, refactor as/do/namespace interactions
Breaking up initial call to parse from the ones deep inside the provider parsing to do smarter namespace detection, added 'as' the ability to look into these also, and cleaned up the code a whole lot that would depend on implicit assumptions. A side-effect is that 'do' is now valid for all namespaces, although it can be overriden.
-rw-r--r--src/rebar3.erl2
-rw-r--r--src/rebar_core.erl89
-rw-r--r--src/rebar_prv_as.erl12
3 files changed, 50 insertions, 53 deletions
diff --git a/src/rebar3.erl b/src/rebar3.erl
index 1b840cb..4f54c89 100644
--- a/src/rebar3.erl
+++ b/src/rebar3.erl
@@ -133,7 +133,7 @@ run_aux(State, GlobalPluginProviders, RawArgs) ->
{Task, Args} = parse_args(RawArgs),
- rebar_core:process_command(rebar_state:command_args(State6, Args), Task).
+ rebar_core:init_command(rebar_state:command_args(State6, Args), Task).
init_config() ->
%% Initialize logging system
diff --git a/src/rebar_core.erl b/src/rebar_core.erl
index 12cd1fc..db82766 100644
--- a/src/rebar_core.erl
+++ b/src/rebar_core.erl
@@ -26,69 +26,61 @@
%% -------------------------------------------------------------------
-module(rebar_core).
--export([process_command/2]).
+-export([init_command/2, process_namespace/2, process_command/2]).
-include("rebar.hrl").
+init_command(State, do) ->
+ process_command(rebar_state:namespace(State, default), do);
+init_command(State, as) ->
+ process_command(rebar_state:namespace(State, default), as);
+init_command(State, Command) ->
+ case process_namespace(State, Command) of
+ {ok, State1, Command1} ->
+ process_command(State1, Command1);
+ {error, Reason} ->
+ {error, Reason}
+ end.
+
+process_namespace(_State, as) ->
+ {error, "Namespace 'as' is forbidden"};
+process_namespace(State, Command) ->
+ Providers = rebar_state:providers(State),
+ CommandProvider = providers:get_provider(Command, Providers, default),
+ case CommandProvider of
+ not_found ->
+ case providers:get_providers_by_namespace(Command, Providers) of
+ [] ->
+ {error, io_lib:format("Command ~p not found", [Command])};
+ _ ->
+ %% Replay 'do' as a command of that namespace
+ {ok, rebar_state:namespace(State, Command), do}
+ end;
+ _ ->
+ {ok, rebar_state:namespace(State, default), Command}
+ end.
+
-spec process_command(rebar_state:t(), atom()) -> {ok, rebar_state:t()} | {error, string()}.
process_command(State, Command) ->
%% ? rebar_prv_install_deps:setup_env(State),
Providers = rebar_state:providers(State),
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,
-
+ TargetProviders = providers:get_target_providers(Command, Providers, Namespace),
+ CommandProvider = providers:get_provider(Command, Providers, Namespace),
case CommandProvider of
- not_found ->
+ not_found when Command =/= do ->
case Namespace of
- undefined ->
- %% On the first run (Namespace = undefined), we use the
- %% unfound command name to be a namespace.
- case providers:get_providers_by_namespace(Command, Providers) of
- [] ->
- {error, io_lib:format("Command ~p not found", [Command])};
- _ ->
- do([{default, do} | TargetProviders],
- rebar_state:namespace(State, Command))
- end;
default ->
{error, io_lib:format("Command ~p not found", [Command])};
_ ->
{error, io_lib:format("Command ~p not found in namespace ~p",
[Command, Namespace])}
end;
+ not_found when Command =:= do, Namespace =/= default ->
+ do([{default, do} | TargetProviders], State);
CommandProvider ->
case Command of
- 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 =:= as, Namespace =:= undefined ->
- %% Because of the possible forms such as:
- %% 'rebar3 as profile task`, `rebar3 as profile do task`
- %% and `rebar3 as profile namespace task`, we can only know
- %% whether we're in the first 'as' or a namespace 'as' by
- %% looking at profiles (as makes them non-default).
- %% The namespace 'as' is banned. It also makes it impossible
- %% to have both $REBAR_PROFILE set and use 'as' in a command
- case rebar_state:current_profiles(State) of
- [default] ->
- do(TargetProviders, State);
- _ ->
- {error, "Namespace 'as' is forbidden"}
- end;
- Command when Command =:= do ->
+ do ->
do(TargetProviders, State);
_ ->
Profiles = providers:profiles(CommandProvider),
@@ -97,12 +89,7 @@ process_command(State, Command) ->
case getopt:parse(Opts, rebar_state:command_args(State1)) of
{ok, Args} ->
State2 = rebar_state:command_parsed_args(State1, Args),
- case Namespace of
- undefined -> % we're executing commands, set the default namespace
- do(TargetProviders, rebar_state:namespace(State2, default));
- _ ->
- do(TargetProviders, State2)
- end;
+ do(TargetProviders, State2);
{error, {invalid_option, Option}} ->
{error, io_lib:format("Invalid option ~s on task ~p", [Option, Command])}
end
diff --git a/src/rebar_prv_as.erl b/src/rebar_prv_as.erl
index beee00d..6e3825f 100644
--- a/src/rebar_prv_as.erl
+++ b/src/rebar_prv_as.erl
@@ -38,7 +38,17 @@ do(State) ->
{error, "At least one profile must be specified when using `as`"};
_ ->
State1 = rebar_state:apply_profiles(State, [list_to_atom(X) || X <- Profiles]),
- rebar_prv_do:do_tasks(Tasks, State1)
+ {FirstTask, FirstTaskArgs} = hd(Tasks),
+ FirstTaskAtom = list_to_atom(FirstTask),
+ case rebar_core:process_namespace(State1, FirstTaskAtom) of
+ {ok, State2, NewTask} ->
+ rebar_prv_do:do_tasks(
+ [{atom_to_list(NewTask),FirstTaskArgs}|tl(Tasks)],
+ State2
+ );
+ {error, Reason} ->
+ {error, Reason}
+ end
end.
-spec format_error(any()) -> iolist().