diff options
-rw-r--r-- | README.md | 2 | ||||
-rw-r--r-- | priv/templates/plugin.erl.dtl | 14 | ||||
-rw-r--r-- | src/rebar_api.erl | 20 | ||||
-rw-r--r-- | src/rebar_plugins.erl | 9 | ||||
-rw-r--r-- | src/rebar_prv_clean.erl | 2 | ||||
-rw-r--r-- | src/rebar_prv_cover.erl | 36 | ||||
-rw-r--r-- | src/rebar_prv_do.erl | 43 | ||||
-rw-r--r-- | src/rebar_prv_escriptize.erl | 2 | ||||
-rw-r--r-- | src/rebar_prv_help.erl | 4 | ||||
-rw-r--r-- | src/rebar_prv_new.erl | 2 | ||||
-rw-r--r-- | src/rebar_prv_wtf.erl | 4 | ||||
-rw-r--r-- | src/rebar_prv_xref.erl | 2 | ||||
-rw-r--r-- | src/rebar_utils.erl | 5 | ||||
-rw-r--r-- | test/rebar_cover_SUITE.erl | 22 | ||||
-rw-r--r-- | test/rebar_namespace_SUITE.erl | 38 |
15 files changed, 152 insertions, 53 deletions
@@ -125,7 +125,7 @@ $ git clone https://github.com/rebar/rebar3 $ cd rebar $ ./bootstrap/bootstrap ==> rebar (compile) -Congratulations! You now have a self-contained script called "rebar" in +Congratulations! You now have a self-contained script called "rebar3" in your current working directory. Place this script anywhere in your path and you can use rebar to build OTP-compliant apps. ``` diff --git a/priv/templates/plugin.erl.dtl b/priv/templates/plugin.erl.dtl index d3528c0..abf4648 100644 --- a/priv/templates/plugin.erl.dtl +++ b/priv/templates/plugin.erl.dtl @@ -12,14 +12,14 @@ -spec init(rebar_state:t()) -> {ok, rebar_state:t()}. init(State) -> Provider = providers:create([ - {name, ?PROVIDER}, % The 'user friendly' name of the task - {module, ?MODULE}, % The module implementation of the task - {bare, true}, % The task can be run by the user, always true - {deps, ?DEPS}, % The list of dependencies - {example, "rebar {{name}}"}, % How to use the plugin - {opts, []}, % list of options understood by the plugin + {name, ?PROVIDER}, % The 'user friendly' name of the task + {module, ?MODULE}, % The module implementation of the task + {bare, true}, % The task can be run by the user, always true + {deps, ?DEPS}, % The list of dependencies + {example, "rebar3 {{name}}"}, % How to use the plugin + {opts, []}, % list of options understood by the plugin {short_desc, "{{desc}}"}, - {desc, ""} + {desc, "{{desc}}"} ]), {ok, rebar_state:add_provider(State, Provider)}. diff --git a/src/rebar_api.erl b/src/rebar_api.erl index a01391d..3fc7f61 100644 --- a/src/rebar_api.erl +++ b/src/rebar_api.erl @@ -5,7 +5,11 @@ -include_lib("providers/include/providers.hrl"). -export([abort/0, abort/2, console/2, - debug/2, info/2, warn/2, error/2]). + debug/2, info/2, warn/2, error/2, + expand_env_variable/3, + get_arch/0, + wordsize/0]). + -export_type([rebar_dict/0, rebar_digraph/0]). %%%%%%%%%%%%%%%%%%%%%%% @@ -30,3 +34,17 @@ info(Str, Args) -> ?INFO(Str, Args). warn(Str, Args) -> ?WARN(Str, Args). %% @doc logs with severity `error' error(Str, Args) -> ?ERROR(Str, Args). + +%% +%% Given env. variable FOO we want to expand all references to +%% it in InStr. References can have two forms: $FOO and ${FOO} +%% The end of form $FOO is delimited with whitespace or eol +%% +expand_env_variable(InStr, VarName, RawVarValue) -> + rebar_utils:expand_env_variable(InStr, VarName, RawVarValue). + +get_arch() -> + rebar_utils:get_arch(). + +wordsize() -> + rebar_utils:wordsize(). diff --git a/src/rebar_plugins.erl b/src/rebar_plugins.erl index 333d8a1..5a0ca3c 100644 --- a/src/rebar_plugins.erl +++ b/src/rebar_plugins.erl @@ -61,13 +61,10 @@ validate_plugin(Plugin) -> {ok, Providers} -> {true, Providers}; undefined -> - Exports = sets:from_list(Plugin:module_info(exports)), - Required = sets:from_list([{init,1}, - {do,1}, - {format_error,1}]), - case sets:is_subset(Required, Exports) of + Exports = Plugin:module_info(exports), + case lists:member({init,1}, Exports) of false -> - ?WARN("Plugin ~p is not a provider. It will not be used.~n", [Plugin]), + ?WARN("Plugin ~p does not export init/1. It will not be used.~n", [Plugin]), false; true -> {true, Plugin} diff --git a/src/rebar_prv_clean.erl b/src/rebar_prv_clean.erl index 8fbc516..0da286b 100644 --- a/src/rebar_prv_clean.erl +++ b/src/rebar_prv_clean.erl @@ -37,7 +37,7 @@ do(State) -> case All of true -> - DepsDir = rebar_state:get(State, deps_dir, ?DEFAULT_DEPS_DIR), + DepsDir = rebar_dir:deps_dir(State), DepApps = rebar_app_discover:find_apps([DepsDir], all); false -> DepApps = [] diff --git a/src/rebar_prv_cover.erl b/src/rebar_prv_cover.erl index d6e18dc..13c12d1 100644 --- a/src/rebar_prv_cover.erl +++ b/src/rebar_prv_cover.erl @@ -14,7 +14,7 @@ -include("rebar.hrl"). -define(PROVIDER, cover). --define(DEPS, []). +-define(DEPS, [app_discovery]). %% =================================================================== %% Public API @@ -29,7 +29,8 @@ init(State) -> {example, "rebar3 cover"}, {short_desc, "Perform coverage analysis."}, {desc, ""}, - {opts, cover_opts(State)}])), + {opts, cover_opts(State)}, + {profiles, [test]}])), {ok, State1}. -spec do(rebar_state:t()) -> {ok, rebar_state:t()} | {error, string()}. @@ -135,14 +136,25 @@ import(CoverData) -> end. analysis(State, Task) -> + OldPath = code:get_path(), + ok = restore_cover_paths(State), Mods = cover:imported_modules(), - lists:map( - fun(Mod) -> - {ok, Answer} = cover:analyze(Mod, coverage, line), - {ok, File} = analyze_to_file(Mod, State, Task), - {Mod, process(Answer), File} - end, - Mods). + Analysis = lists:map(fun(Mod) -> + {ok, Answer} = cover:analyze(Mod, coverage, line), + {ok, File} = analyze_to_file(Mod, State, Task), + {Mod, process(Answer), File} + end, + Mods), + true = code:set_path(OldPath), + Analysis. + +restore_cover_paths(State) -> + lists:foreach(fun(App) -> + AppDir = rebar_app_info:out_dir(App), + _ = code:add_path(filename:join([AppDir, "ebin"])) + end, rebar_state:project_apps(State)), + _ = code:add_path(filename:join([rebar_dir:base_dir(State), "ebin"])), + ok. analyze_to_file(Mod, State, Task) -> CoverDir = cover_dir(State), @@ -319,8 +331,7 @@ write_coverdata(State, Task) -> ExportFile = filename:join([DataDir, atom_to_list(Task) ++ ".coverdata"]), case cover:export(ExportFile) of ok -> - ?DEBUG("Cover data written to ~p.", [ExportFile]), - ok; + ?DEBUG("Cover data written to ~p.", [ExportFile]); {error, Reason} -> ?WARN("Cover data export failed: ~p", [Reason]) end. @@ -333,7 +344,8 @@ verbose(State) -> end. cover_dir(State) -> - rebar_state:get(State, cover_data_dir, filename:join(["_build", "cover"])). + rebar_state:get(State, cover_data_dir, filename:join([rebar_dir:base_dir(State), + "cover"])). cover_opts(_State) -> [{reset, $r, "reset", boolean, help(reset)}, diff --git a/src/rebar_prv_do.erl b/src/rebar_prv_do.erl index 5ecd987..fd1767a 100644 --- a/src/rebar_prv_do.erl +++ b/src/rebar_prv_do.erl @@ -42,13 +42,46 @@ do_tasks([{TaskStr, Args}|Tail], State) -> Task = list_to_atom(TaskStr), State1 = rebar_state:set(State, task, Task), State2 = rebar_state:command_args(State1, Args), - case rebar_core:process_command(State2, Task) of - {ok, _} -> - do_tasks(Tail, State); - Error -> - Error + Namespace = rebar_state:namespace(State2), + case Namespace of + default -> + %% The first task we hit might be a namespace! + case maybe_namespace(State2, Task, Args) of + {ok, _} -> + do_tasks(Tail, State); + {error, Reason} -> + {error, Reason} + end; + _ -> + %% We're already in a non-default namespace, check the + %% task directly. + case rebar_core:process_command(State2, Task) of + {ok, _} -> + do_tasks(Tail, State); + {error, Reason} -> + {error, Reason} + end end. + -spec format_error(any()) -> iolist(). format_error(Reason) -> io_lib:format("~p", [Reason]). + +maybe_namespace(State, Task, Args) -> + case rebar_core:process_namespace(State, Task) of + {ok, State2, Task} -> + %% The task exists after all. + rebar_core:process_command(State2, Task); + {ok, State2, do} when Args =/= [] -> + %% We are in 'do' so we can't apply it directly. + [NewTaskStr | NewArgs] = Args, + NewTask = list_to_atom(NewTaskStr), + State3 = rebar_state:command_args(State2, NewArgs), + rebar_core:process_command(State3, NewTask); + {ok, _, _} -> + %% No arguments to consider as a command. Woops. + {error, io_lib:format("Command ~p not found", [Task])}; + {error, Reason} -> + {error, Reason} + end. diff --git a/src/rebar_prv_escriptize.erl b/src/rebar_prv_escriptize.erl index 69ac7fe..d17699e 100644 --- a/src/rebar_prv_escriptize.erl +++ b/src/rebar_prv_escriptize.erl @@ -51,7 +51,7 @@ init(State) -> {deps, ?DEPS}, {example, "rebar3 escriptize"}, {opts, []}, - {short_desc, "Generate escript archive"}, + {short_desc, "Generate escript archive."}, {desc, desc()} ]), {ok, rebar_state:add_provider(State, Provider)}. diff --git a/src/rebar_prv_help.erl b/src/rebar_prv_help.erl index 9e22530..b450023 100644 --- a/src/rebar_prv_help.erl +++ b/src/rebar_prv_help.erl @@ -58,11 +58,11 @@ format_error(Reason) -> %% print help/usage string %% help(State) -> - ?CONSOLE("Rebar is a tool for working with Erlang projects.~n~n", []), + ?CONSOLE("Rebar3 is a tool for working with Erlang projects.~n~n", []), OptSpecList = rebar3:global_option_spec_list(), getopt:usage(OptSpecList, "rebar", "", []), ?CONSOLE("~nSeveral tasks are available:~n", []), providers:help(rebar_state:providers(State)), - ?CONSOLE("~nRun 'rebar help <TASK>' for details.~n~n", []). + ?CONSOLE("~nRun 'rebar3 help <TASK>' for details.~n~n", []). diff --git a/src/rebar_prv_new.erl b/src/rebar_prv_new.erl index 58e27fd..6bc9f53 100644 --- a/src/rebar_prv_new.erl +++ b/src/rebar_prv_new.erl @@ -67,7 +67,7 @@ format_error(Reason) -> info() -> io_lib:format( - "Create rebar project based on template and vars.~n" + "Create rebar3 project based on template and vars.~n" "~n" "Valid command line options:~n" " template= [var=foo,...]~n", []). diff --git a/src/rebar_prv_wtf.erl b/src/rebar_prv_wtf.erl index f876760..9be9a4b 100644 --- a/src/rebar_prv_wtf.erl +++ b/src/rebar_prv_wtf.erl @@ -26,8 +26,8 @@ init(State) -> {bare, false}, {deps, ?DEPS}, {example, "rebar3 wtf \"<task>\""}, - {short_desc, "Provide a crash report to be sent to the rebar3 issues page"}, - {desc, "Provide a crash report to be sent to the rebar3 issues page"}, + {short_desc, "Provide a crash report to be sent to the rebar3 issues page."}, + {desc, "Provide a crash report to be sent to the rebar3 issues page."}, {opts, [ {task, undefined, undefined, string, "Task to print details for."} ]}])), diff --git a/src/rebar_prv_xref.erl b/src/rebar_prv_xref.erl index aa1075f..67cd554 100644 --- a/src/rebar_prv_xref.erl +++ b/src/rebar_prv_xref.erl @@ -66,7 +66,7 @@ format_error(Reason) -> %% =================================================================== short_desc() -> - "Run cross reference analysis". + "Run cross reference analysis.". desc() -> io_lib:format( diff --git a/src/rebar_utils.erl b/src/rebar_utils.erl index df25997..d92ab80 100644 --- a/src/rebar_utils.erl +++ b/src/rebar_utils.erl @@ -49,7 +49,10 @@ erl_opts/1, indent/1, cleanup_code_path/1, - args_to_tasks/1]). + args_to_tasks/1, + expand_env_variable/3, + get_arch/0, + wordsize/0]). %% for internal use only -export([otp_release/0]). diff --git a/test/rebar_cover_SUITE.erl b/test/rebar_cover_SUITE.erl index f3c3248..0bead99 100644 --- a/test/rebar_cover_SUITE.erl +++ b/test/rebar_cover_SUITE.erl @@ -39,7 +39,7 @@ flag_coverdata_written(Config) -> Name = rebar_test_utils:create_random_name("cover_"), Vsn = rebar_test_utils:create_random_vsn(), - rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), + rebar_test_utils:create_eunit_app(AppDir, Name, Vsn, [kernel, stdlib]), RebarConfig = [{erl_opts, [{d, some_define}]}], rebar_test_utils:run_and_check(Config, @@ -47,14 +47,14 @@ flag_coverdata_written(Config) -> ["eunit", "--cover"], {ok, [{app, Name}]}), - true = filelib:is_file(filename:join(["_build", "cover", "eunit.coverdata"])). + true = filelib:is_file(filename:join([AppDir, "_build", "test", "cover", "eunit.coverdata"])). config_coverdata_written(Config) -> AppDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("cover_"), Vsn = rebar_test_utils:create_random_vsn(), - rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), + rebar_test_utils:create_eunit_app(AppDir, Name, Vsn, [kernel, stdlib]), RebarConfig = [{erl_opts, [{d, some_define}]}, {cover_enabled, true}], rebar_test_utils:run_and_check(Config, @@ -62,14 +62,14 @@ config_coverdata_written(Config) -> ["eunit"], {ok, [{app, Name}]}), - true = filelib:is_file(filename:join(["_build", "cover", "eunit.coverdata"])). + true = filelib:is_file(filename:join([AppDir, "_build", "test", "cover", "eunit.coverdata"])). index_written(Config) -> AppDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("cover_"), Vsn = rebar_test_utils:create_random_vsn(), - rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), + rebar_test_utils:create_eunit_app(AppDir, Name, Vsn, [kernel, stdlib]), RebarConfig = [{erl_opts, [{d, some_define}]}], rebar_test_utils:run_and_check(Config, @@ -77,14 +77,14 @@ index_written(Config) -> ["do", "eunit", "--cover", ",", "cover"], {ok, [{app, Name}]}), - true = filelib:is_file(filename:join(["_build", "cover", "index.html"])). + true = filelib:is_file(filename:join([AppDir, "_build", "test", "cover", "index.html"])). config_alt_coverdir(Config) -> AppDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("cover_"), Vsn = rebar_test_utils:create_random_vsn(), - rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), + rebar_test_utils:create_eunit_app(AppDir, Name, Vsn, [kernel, stdlib]), CoverDir = filename:join(["coverage", "goes", "here"]), @@ -101,7 +101,7 @@ flag_verbose(Config) -> Name = rebar_test_utils:create_random_name("cover_"), Vsn = rebar_test_utils:create_random_vsn(), - rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), + rebar_test_utils:create_eunit_app(AppDir, Name, Vsn, [kernel, stdlib]), RebarConfig = [{erl_opts, [{d, some_define}]}], rebar_test_utils:run_and_check(Config, @@ -109,14 +109,14 @@ flag_verbose(Config) -> ["do", "eunit", "--cover", ",", "cover", "--verbose"], {ok, [{app, Name}]}), - true = filelib:is_file(filename:join(["_build", "cover", "index.html"])). + true = filelib:is_file(filename:join([AppDir, "_build", "test", "cover", "index.html"])). config_verbose(Config) -> AppDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("cover_"), Vsn = rebar_test_utils:create_random_vsn(), - rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), + rebar_test_utils:create_eunit_app(AppDir, Name, Vsn, [kernel, stdlib]), RebarConfig = [{erl_opts, [{d, some_define}]}, {cover_print_enabled, true}], rebar_test_utils:run_and_check(Config, @@ -124,4 +124,4 @@ config_verbose(Config) -> ["do", "eunit", "--cover", ",", "cover"], {ok, [{app, Name}]}), - true = filelib:is_file(filename:join(["_build", "cover", "index.html"])). + true = filelib:is_file(filename:join([AppDir, "_build", "test", "cover", "index.html"])). diff --git a/test/rebar_namespace_SUITE.erl b/test/rebar_namespace_SUITE.erl index 3a55573..c267e7f 100644 --- a/test/rebar_namespace_SUITE.erl +++ b/test/rebar_namespace_SUITE.erl @@ -6,7 +6,8 @@ all() -> [implicit_compile, default_compile, do_compile, as_default_compile, as_do_compile, notfound, do_notfound, default_notfound, ns_notfound, ns_found, - as_ns_invalid]. + as_ns_invalid, + do_ns_chain, do_ns_chain2, do_ns_noarg, do_ns_badcmd]. init_per_testcase(Case, Config0) -> Config = rebar_test_utils:init_rebar_state(Config0), @@ -93,6 +94,41 @@ as_ns_invalid(Config) -> {error, "Namespace 'as' is forbidden"} ). +do_ns_chain(Config) -> + %% `do` is also able to resolve namespaces on + %% commands not found + Command = ["do", "deps,", "ns", "fake_provider,", "deps"], + rebar_test_utils:run_and_check( + add_fake_ns_provider(Config), [], Command, + {ok, []} + ). + +do_ns_chain2(Config) -> + %% `do` is also able to resolve namespaces on + %% commands not found + Command = ["do", "ns", "fake_provider,", "deps,", "ns", "fake_provider"], + rebar_test_utils:run_and_check( + add_fake_ns_provider(Config), [], Command, + {ok, []} + ). + +do_ns_noarg(Config) -> + %% `do` is also able to resolve namespaces on + %% commands not found + Command = ["do", "ns"], + rebar_test_utils:run_and_check( + add_fake_ns_provider(Config), [], Command, + {error, io_lib:format("Command ~p not found", [ns])} + ). + +do_ns_badcmd(Config) -> + %% `do` is also able to resolve namespaces on + %% commands not found + Command = ["do", "ns", "badcmd"], + rebar_test_utils:run_and_check( + add_fake_ns_provider(Config), [], Command, + {error, io_lib:format("Command ~p not found in namespace ~p", [badcmd, ns])} + ). %%% Helpers %%% add_fake_ns_provider(Config) -> |