diff options
-rw-r--r-- | src/rebar_prv_as.erl | 50 | ||||
-rw-r--r-- | src/rebar_prv_do.erl | 1 | ||||
-rw-r--r-- | src/rebar_utils.erl | 4 | ||||
-rw-r--r-- | test/rebar_as_SUITE.erl | 88 |
4 files changed, 128 insertions, 15 deletions
diff --git a/src/rebar_prv_as.erl b/src/rebar_prv_as.erl index 1ad22ed..7ac5465 100644 --- a/src/rebar_prv_as.erl +++ b/src/rebar_prv_as.erl @@ -32,21 +32,45 @@ init(State) -> -spec do(rebar_state:t()) -> {ok, rebar_state:t()} | {error, string()}. do(State) -> - [Profile | Rest] = rebar_state:command_args(State), - Tasks = args_to_tasks(Rest), - Profiles = [list_to_atom(X) || X <- string:tokens(Profile, ",")], - State1 = rebar_state:apply_profiles(State, Profiles), - lists:foldl(fun(TaskArgs, {ok, StateAcc}) -> - [TaskStr | Args] = string:tokens(TaskArgs, " "), - Task = list_to_atom(TaskStr), - StateAcc1 = rebar_state:set(StateAcc, task, Task), - StateAcc2 = rebar_state:command_args(StateAcc1, Args), - rebar_core:process_command(StateAcc2, Task) - end, {ok, State1}, Tasks). + {Profiles, Tasks} = args_to_profiles_and_tasks(rebar_state:command_args(State)), + case Profiles of + [] -> + {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) + end. -spec format_error(any()) -> iolist(). format_error(Reason) -> io_lib:format("~p", [Reason]). -args_to_tasks(Args) -> - [string:strip(T) || T <- string:tokens(string:join(Args, " "), ",")]. +args_to_profiles_and_tasks(Args) -> + first_profile(Args). + +first_profile([]) -> {[], []}; +first_profile([ProfileList|Rest]) -> + case re:split(ProfileList, ",", [{return, list}, {parts, 2}]) of + %% profile terminated by comma + [P, More] -> profiles([More] ++ Rest, [P]); + %% profile not terminated by comma + [P] -> comma_or_end(Rest, [P]) + end. + +profiles([], Acc) -> {lists:reverse(Acc), rebar_utils:args_to_tasks([])}; +profiles([ProfileList|Rest], Acc) -> + case re:split(ProfileList, ",", [{return, list}, {parts, 2}]) of + %% profile terminated by comma + [P, More] -> profiles([More] ++ Rest, [P|Acc]); + %% profile not terminated by comma + [P] -> comma_or_end(Rest, [P|Acc]) + end. + +%% `, foo...` +comma_or_end([","|Rest], Acc) -> + profiles(Rest, Acc); +%% `,foo...` +comma_or_end(["," ++ Profile|Rest], Acc) -> + profiles([Profile|Rest], Acc); +comma_or_end(Tasks, Acc) -> + {lists:reverse(Acc), rebar_utils:args_to_tasks(Tasks)}. diff --git a/src/rebar_prv_do.erl b/src/rebar_prv_do.erl index 8e6ee3a..5ecd987 100644 --- a/src/rebar_prv_do.erl +++ b/src/rebar_prv_do.erl @@ -7,6 +7,7 @@ -export([init/1, do/1, + do_tasks/2, format_error/1]). -include("rebar.hrl"). diff --git a/src/rebar_utils.erl b/src/rebar_utils.erl index 0c95c69..1a7bf98 100644 --- a/src/rebar_utils.erl +++ b/src/rebar_utils.erl @@ -477,8 +477,8 @@ new_task([], Acc) -> lists:reverse(Acc); new_task([TaskList|Rest], Acc) -> case re:split(TaskList, ",", [{return, list}, {parts, 2}]) of %% `do` consumes all remaining args - ["do" = Task|RestArgs] -> - lists:reverse([{Task, RestArgs ++ Rest}|Acc]); + ["do" = Task] -> + lists:reverse([{Task, Rest}|Acc]); %% single task terminated by a comma [Task, ""] -> new_task(Rest, [{Task, []}|Acc]); %% sequence of two or more tasks diff --git a/test/rebar_as_SUITE.erl b/test/rebar_as_SUITE.erl new file mode 100644 index 0000000..5566c98 --- /dev/null +++ b/test/rebar_as_SUITE.erl @@ -0,0 +1,88 @@ +-module(rebar_as_SUITE). + +-export([suite/0, + init_per_suite/1, + end_per_suite/1, + init_per_testcase/2, + all/0, + as_basic/1, + as_multiple_profiles/1, + as_multiple_tasks/1, + as_multiple_profiles_multiple_tasks/1, + as_comma_placement/1]). + +-include_lib("common_test/include/ct.hrl"). +-include_lib("eunit/include/eunit.hrl"). +-include_lib("kernel/include/file.hrl"). + +suite() -> []. + +init_per_suite(Config) -> Config. + +end_per_suite(_Config) -> ok. + +init_per_testcase(_, Config) -> + rebar_test_utils:init_rebar_state(Config, "do_as_"). + +all() -> [as_basic, as_multiple_profiles, as_multiple_tasks, + as_multiple_profiles_multiple_tasks]. + +as_basic(Config) -> + AppDir = ?config(apps, Config), + + Name = rebar_test_utils:create_random_name("as_basic_"), + Vsn = rebar_test_utils:create_random_vsn(), + rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), + + rebar_test_utils:run_and_check(Config, + [], + ["as", "default", "compile"], + {ok, [{app, Name}]}). + +as_multiple_profiles(Config) -> + AppDir = ?config(apps, Config), + + Name = rebar_test_utils:create_random_name("as_multiple_profiles_"), + Vsn = rebar_test_utils:create_random_vsn(), + rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), + + rebar_test_utils:run_and_check(Config, + [], + ["as", "foo", ",", "bar", "compile"], + {ok, [{app, Name}]}). + +as_multiple_tasks(Config) -> + AppDir = ?config(apps, Config), + + Name = rebar_test_utils:create_random_name("as_multiple_tasks_"), + Vsn = rebar_test_utils:create_random_vsn(), + rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), + + rebar_test_utils:run_and_check(Config, + [], + ["as", "foo", "clean", ",", "compile"], + {ok, [{app, Name}]}). + +as_multiple_profiles_multiple_tasks(Config) -> + AppDir = ?config(apps, Config), + + Name = rebar_test_utils:create_random_name("as_multiple_profiles_multiple_tasks_"), + Vsn = rebar_test_utils:create_random_vsn(), + rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), + + rebar_test_utils:run_and_check(Config, + [], + ["as", "foo", ",", "bar", "clean", ",", "compile"], + {ok, [{app, Name}]}). + +as_comma_placement(Config) -> + AppDir = ?config(apps, Config), + + Name = rebar_test_utils:create_random_name("do_as_crazy_"), + Vsn = rebar_test_utils:create_random_vsn(), + rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), + + rebar_test_utils:run_and_check(Config, + [], + ["as", "foo,bar", ",", "baz", ",qux", "compile"], + {ok, [{app, Name}]}). |