소스 검색

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.
pull/268/head
Fred Hebert 10 년 전
부모
커밋
ad18970cd7
3개의 변경된 파일50개의 추가작업 그리고 53개의 파일을 삭제
  1. +1
    -1
      src/rebar3.erl
  2. +38
    -51
      src/rebar_core.erl
  3. +11
    -1
      src/rebar_prv_as.erl

+ 1
- 1
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

+ 38
- 51
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

+ 11
- 1
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().

불러오는 중...
취소
저장