From d4b76391475ab5ddda80f7799bda3ee1745e8244 Mon Sep 17 00:00:00 2001 From: Tuncer Ayaz Date: Tue, 30 Aug 2016 12:17:52 +0200 Subject: Print stacktrace in a more conventional way Insert a newline before printing the stacktrace so that the term is easier to read and copy. This is a more conventional way to print traces, and is, for instance, the way it's done by make and python. --- src/rebar3.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/rebar3.erl') diff --git a/src/rebar3.erl b/src/rebar3.erl index d3ea15f..c665f20 100644 --- a/src/rebar3.erl +++ b/src/rebar3.erl @@ -292,7 +292,7 @@ handle_error(Error) -> case erlang:get_stacktrace() of [] -> ok; Trace -> - ?DEBUG("Stack trace to the error location: ~p", [Trace]) + ?DEBUG("Stack trace to the error location:~n~p", [Trace]) end, ?INFO("When submitting a bug report, please include the output of `rebar3 report \"your command\"`", []), erlang:halt(1). -- cgit v1.1 From 294fd72f4d8f3beb2e856f085e634549d978b7fd Mon Sep 17 00:00:00 2001 From: Alexander Sedov Date: Thu, 13 Oct 2016 12:46:18 +0300 Subject: Get stacktrace only once and as soon as possible. Fixes #1347. It turns out that pretty-printing uses throw-catch and thus garbages out the stack trace sometimes, so we should get it only once. --- src/rebar3.erl | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src/rebar3.erl') diff --git a/src/rebar3.erl b/src/rebar3.erl index c665f20..47dc25a 100644 --- a/src/rebar3.erl +++ b/src/rebar3.erl @@ -286,10 +286,11 @@ handle_error({error, Error}) when is_list(Error) -> handle_error(Error) -> %% Nothing should percolate up from rebar_core; %% Dump this error to console - ?CRASHDUMP("Error: ~p~n~p~n~n", [Error, erlang:get_stacktrace()]), + StackTrace = erlang:get_stacktrace(), + ?CRASHDUMP("Error: ~p~n~p~n~n", [Error, StackTrace]), ?ERROR("Uncaught error in rebar_core. Run with DEBUG=1 to see stacktrace or consult rebar3.crashdump", []), ?DEBUG("Uncaught error: ~p", [Error]), - case erlang:get_stacktrace() of + case StackTrace of [] -> ok; Trace -> ?DEBUG("Stack trace to the error location:~n~p", [Trace]) -- cgit v1.1 From 5323fdc377d6034cdb625547600144881ae1af46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eric=20Meadows-J=C3=B6nsson?= Date: Tue, 22 Nov 2016 22:22:05 +0100 Subject: Always read REBAR_CONFIG env var when loading config --- src/rebar3.erl | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'src/rebar3.erl') diff --git a/src/rebar3.erl b/src/rebar3.erl index 47dc25a..4e7e284 100644 --- a/src/rebar3.erl +++ b/src/rebar3.erl @@ -149,12 +149,7 @@ init_config() -> Verbosity = log_level(), ok = rebar_log:init(command_line, Verbosity), - Config = case os:getenv("REBAR_CONFIG") of - false -> - rebar_config:consult_file(?DEFAULT_CONFIG_FILE); - ConfigFile -> - rebar_config:consult_file(ConfigFile) - end, + Config = rebar_config:consult(), Config1 = rebar_config:merge_locks(Config, rebar_config:consult_lock_file(?LOCK_FILE)), %% If $HOME/.config/rebar3/rebar.config exists load and use as global config -- cgit v1.1 From 3da4cc222197e01886d3baaeca7a380e02ff3125 Mon Sep 17 00:00:00 2001 From: Fred Hebert Date: Fri, 25 Nov 2016 21:32:43 -0500 Subject: Type specifications and edocs improvements Includes improvments and function documentation for all modules (in alphabetical order) up to rebar_core, and may have included more in other modules as I saw fit to dig and understand more of the internals. --- src/rebar3.erl | 76 ++++++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 61 insertions(+), 15 deletions(-) (limited to 'src/rebar3.erl') diff --git a/src/rebar3.erl b/src/rebar3.erl index 4e7e284..fa26ab2 100644 --- a/src/rebar3.erl +++ b/src/rebar3.erl @@ -24,6 +24,16 @@ %% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN %% THE SOFTWARE. %% ------------------------------------------------------------------- +%% +%% @doc Main module for rebar3. Supports two interfaces; one for escripts, +%% and one for usage as a library (although rebar3 makes a lot of +%% assumptions about its environment, making it a bit tricky to use as +%% a lib). +%% +%% This module's job is mostly to set up the root environment for rebar3 +%% and handle global options (mostly all from the ENV) and make them +%% accessible to the rest of the run. +%% @end -module(rebar3). -export([main/0, @@ -43,14 +53,14 @@ %% Public API %% ==================================================================== -%% For running with: +%% @doc For running with: %% erl +sbtu +A0 -noinput -mode minimal -boot start_clean -s rebar3 main -extra "$@" -spec main() -> no_return(). main() -> List = init:get_plain_arguments(), main(List). -%% escript Entry point +%% @doc escript Entry point -spec main(list()) -> no_return(). main(Args) -> try run(Args) of @@ -63,7 +73,8 @@ main(Args) -> handle_error(Error) end. -%% Erlang-API entry point +%% @doc Erlang-API entry point +-spec run(rebar_state:t(), [string()]) -> {ok, rebar_state:t()} | {error, term()}. run(BaseState, Commands) -> start_and_load_apps(api), BaseState1 = rebar_state:set(BaseState, task, Commands), @@ -78,6 +89,10 @@ run(BaseState, Commands) -> %% Internal functions %% ==================================================================== +%% @private sets up the rebar3 environment based on the command line +%% arguments passed, if they have any relevance; used to translate +%% from the escript call-site into a common one with the library +%% usage. run(RawArgs) -> start_and_load_apps(command_line), @@ -95,7 +110,13 @@ run(RawArgs) -> {BaseState2, _Args1} = set_options(BaseState1, {[], []}), run_aux(BaseState2, RawArgs). +%% @private Junction point between the CLI and library entry points. +%% From here on the module's role is a shared path here to finish +%% up setting the environment for the run. +-spec run_aux(rebar_state:t(), [string()]) -> + {ok, rebar_state:t()} | {error, term()}. run_aux(State, RawArgs) -> + %% Profile override; can only support one profile State1 = case os:getenv("REBAR_PROFILE") of false -> State; @@ -108,6 +129,7 @@ run_aux(State, RawArgs) -> rebar_utils:check_min_otp_version(rebar_state:get(State1, minimum_otp_vsn, undefined)), rebar_utils:check_blacklisted_otp_versions(rebar_state:get(State1, blacklisted_otp_vsns, undefined)), + %% Change the default hex CDN State2 = case os:getenv("HEX_CDN") of false -> State1; @@ -144,6 +166,9 @@ run_aux(State, RawArgs) -> rebar_core:init_command(rebar_state:command_args(State10, Args), Task). +%% @doc set up base configuration having to do with verbosity, where +%% to find config files, and so on, and return an internal rebar3 state term. +-spec init_config() -> rebar_state:t(). init_config() -> %% Initialize logging system Verbosity = log_level(), @@ -188,6 +213,17 @@ init_config() -> %% Initialize vsn cache rebar_state:set(State1, vsn_cache, dict:new()). +%% @doc Parse basic rebar3 arguments to find the top-level task +%% to be run; this parsing is only partial from the point of view that +%% runs done with arguments like `as $PROFILE do $TASK' will just +%% return `as', which is then in charge of doing a more dynamic +%% dispatch. +%% If no arguments are given, the `help' task is returned. +%% If special arguments like `-h' or `-v' are translated to `help' +%% and `version' tasks. +%% The unparsed parts of arguments are returned in: +%% `{Task, Rest}'. +-spec parse_args([string()]) -> {atom(), [string()]}. parse_args([]) -> parse_args(["help"]); parse_args([H | Rest]) when H =:= "-h" @@ -199,6 +235,7 @@ parse_args([H | Rest]) when H =:= "-v" parse_args([Task | RawRest]) -> {list_to_atom(Task), RawRest}. +%% @private actually not too sure what this does anymore. set_options(State, {Options, NonOptArgs}) -> GlobalDefines = proplists:get_all_values(defines, Options), @@ -211,9 +248,8 @@ set_options(State, {Options, NonOptArgs}) -> {rebar_state:set(State2, task, Task), NonOptArgs}. -%% -%% get log level based on getopt option -%% +%% @doc get log level based on getopt options and ENV +-spec log_level() -> integer(). log_level() -> case os:getenv("QUIET") of Q when Q == false; Q == "" -> @@ -228,18 +264,16 @@ log_level() -> rebar_log:error_level() end. -%% -%% show version information and halt -%% +%% @doc show version information +-spec version() -> ok. version() -> {ok, Vsn} = application:get_key(rebar, vsn), ?CONSOLE("rebar ~s on Erlang/OTP ~s Erts ~s", [Vsn, erlang:system_info(otp_release), erlang:system_info(version)]). +%% @private set global flag based on getopt option boolean value %% TODO: Actually make it 'global' -%% -%% set global flag based on getopt option boolean value -%% +-spec set_global_flag(rebar_state:t(), list(), term()) -> rebar_state:t(). set_global_flag(State, Options, Flag) -> Value = case proplists:get_bool(Flag, Options) of true -> @@ -249,9 +283,9 @@ set_global_flag(State, Options, Flag) -> end, rebar_state:set(State, Flag, Value). -%% -%% options accepted via getopt -%% + +%% @doc options accepted via getopt +-spec global_option_spec_list() -> [{atom(), char(), string(), atom(), string()}, ...]. global_option_spec_list() -> [ %% {Name, ShortOpt, LongOpt, ArgSpec, HelpMsg} @@ -260,6 +294,9 @@ global_option_spec_list() -> {task, undefined, undefined, string, "Task to run."} ]. +%% @private translate unhandled errors and internal return codes into proper +%% erroneous program exits. +-spec handle_error(term()) -> no_return(). handle_error(rebar_abort) -> erlang:halt(1); handle_error({error, rebar_abort}) -> @@ -293,6 +330,11 @@ handle_error(Error) -> ?INFO("When submitting a bug report, please include the output of `rebar3 report \"your command\"`", []), erlang:halt(1). +%% @private Boot Erlang dependencies; problem is that escripts don't auto-boot +%% stuff the way releases do and we have to do it by hand. +%% This also lets us detect and show nicer errors when a critical lib is +%% not supported +-spec start_and_load_apps(command_line|api) -> term(). start_and_load_apps(Caller) -> _ = application:load(rebar), %% Make sure crypto is running @@ -303,6 +345,9 @@ start_and_load_apps(Caller) -> inets:start(), inets:start(httpc, [{profile, rebar}]). +%% @doc Make sure a required app is running, or display an error message +%% and abort if there's a problem. +-spec ensure_running(atom(), command_line|api) -> ok | no_return(). ensure_running(App, Caller) -> case application:start(App) of ok -> ok; @@ -319,6 +364,7 @@ ensure_running(App, Caller) -> throw(rebar_abort) end. +-spec state_from_global_config([term()], file:filename()) -> rebar_state:t(). state_from_global_config(Config, GlobalConfigFile) -> rebar_utils:set_httpc_options(), GlobalConfigTerms = rebar_config:consult_file(GlobalConfigFile), -- cgit v1.1 From ffc2cf98d390a35cf3f61c7c0bf5f26e3552fd2c Mon Sep 17 00:00:00 2001 From: Artem Pervin Date: Wed, 30 Nov 2016 13:45:06 -0500 Subject: 1394: added fix for rebar_utils, moved setting of http_options into init_config, added unit tests --- src/rebar3.erl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/rebar3.erl') diff --git a/src/rebar3.erl b/src/rebar3.erl index 4e7e284..1059904 100644 --- a/src/rebar3.erl +++ b/src/rebar3.erl @@ -145,6 +145,8 @@ run_aux(State, RawArgs) -> rebar_core:init_command(rebar_state:command_args(State10, Args), Task). init_config() -> + rebar_utils:set_httpc_options(), + %% Initialize logging system Verbosity = log_level(), ok = rebar_log:init(command_line, Verbosity), @@ -320,7 +322,6 @@ ensure_running(App, Caller) -> end. state_from_global_config(Config, GlobalConfigFile) -> - rebar_utils:set_httpc_options(), GlobalConfigTerms = rebar_config:consult_file(GlobalConfigFile), GlobalConfig = rebar_state:new(GlobalConfigTerms), -- cgit v1.1 From 0bc0aeba9c19531025967862cde7b9e32d7bc300 Mon Sep 17 00:00:00 2001 From: Fred Hebert Date: Fri, 24 Feb 2017 21:09:43 -0500 Subject: REBAR_CONFIG impacts file project root only --- src/rebar3.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/rebar3.erl') diff --git a/src/rebar3.erl b/src/rebar3.erl index 56bf3e8..5c593cc 100644 --- a/src/rebar3.erl +++ b/src/rebar3.erl @@ -176,7 +176,7 @@ init_config() -> Verbosity = log_level(), ok = rebar_log:init(command_line, Verbosity), - Config = rebar_config:consult(), + Config = rebar_config:consult_root(), Config1 = rebar_config:merge_locks(Config, rebar_config:consult_lock_file(?LOCK_FILE)), %% If $HOME/.config/rebar3/rebar.config exists load and use as global config -- cgit v1.1 From 3d9e5dff85fd4193f8aab7a6dbd0cffeeea0c1de Mon Sep 17 00:00:00 2001 From: Carlo Carraro Date: Sun, 5 Mar 2017 11:14:45 +0100 Subject: Properly warn on missing rebar3 deps: add inets --- src/rebar3.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/rebar3.erl') diff --git a/src/rebar3.erl b/src/rebar3.erl index 5c593cc..1e1d0b0 100644 --- a/src/rebar3.erl +++ b/src/rebar3.erl @@ -344,7 +344,7 @@ start_and_load_apps(Caller) -> ensure_running(asn1, Caller), ensure_running(public_key, Caller), ensure_running(ssl, Caller), - inets:start(), + ensure_running(inets, Caller), inets:start(httpc, [{profile, rebar}]). %% @doc Make sure a required app is running, or display an error message -- cgit v1.1 From 963c49f5eb9ab5b34e1843fb43305743720917ac Mon Sep 17 00:00:00 2001 From: Fred Hebert Date: Sun, 6 Aug 2017 07:26:21 -0400 Subject: Unicode support in all the places This is done through 3 main change groups: - replacing `~s` by `~ts` in format strings, so that strings that contain unicode are properly printed rather than crashing - adding the `unicode` argument to all function of the `re` module to ensure transformations on strings containing unicode data are valid instead of crashing (see issue #1302) - replacing `ec_cnv:to_binary/1` and `ec_cnv:to_list/1` with matching functions in `rebar_utils`. The last point has been done, rather than modifying and updating erlware commons, because binary and list conversions can be a contentious subject. For example, if what is being handled is actually bytes from a given binary stream, then forcing a byte-oriented interpretation of the data can corrupt it. As such, it does not appear safe to modify erlware commons' conversion functions since it may not be safe for all its users. Instead, rebar3 reimplements a subset of them (only converting atoms and chardata, ignoring numbers) with the explicit purpose of handling unicode string data. Tests were left as unchanged as possible. This may impact the ability to run rebar3's own suites in a unicode path, but respects a principle of least change for such a large patch. --- src/rebar3.erl | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'src/rebar3.erl') diff --git a/src/rebar3.erl b/src/rebar3.erl index 1e1d0b0..eec8968 100644 --- a/src/rebar3.erl +++ b/src/rebar3.erl @@ -183,11 +183,11 @@ init_config() -> GlobalConfigFile = rebar_dir:global_config(), State = case filelib:is_regular(GlobalConfigFile) of true -> - ?DEBUG("Load global config file ~s", [GlobalConfigFile]), + ?DEBUG("Load global config file ~ts", [GlobalConfigFile]), try state_from_global_config(Config1, GlobalConfigFile) catch _:_ -> - ?WARN("Global config ~s exists but can not be read. Ignoring global config values.", [GlobalConfigFile]), + ?WARN("Global config ~ts exists but can not be read. Ignoring global config values.", [GlobalConfigFile]), rebar_state:new(Config1) end; false -> @@ -270,7 +270,7 @@ log_level() -> -spec version() -> ok. version() -> {ok, Vsn} = application:get_key(rebar, vsn), - ?CONSOLE("rebar ~s on Erlang/OTP ~s Erts ~s", + ?CONSOLE("rebar ~ts on Erlang/OTP ~ts Erts ~ts", [Vsn, erlang:system_info(otp_release), erlang:system_info(version)]). %% @private set global flag based on getopt option boolean value @@ -311,11 +311,11 @@ handle_error({error, {Module, Reason}}) -> ?DEBUG("Uncaught error: ~p ~p", [Module, Reason]), ?INFO("When submitting a bug report, please include the output of `rebar3 report \"your command\"`", []); _ -> - ?ERROR("~s", [Module:format_error(Reason)]) + ?ERROR("~ts", [Module:format_error(Reason)]) end, erlang:halt(1); handle_error({error, Error}) when is_list(Error) -> - ?ERROR("~s", [Error]), + ?ERROR("~ts", [Error]), erlang:halt(1); handle_error(Error) -> %% Nothing should percolate up from rebar_core; -- cgit v1.1 From 13bdb75b2961e1ae43e43e7c8d06bf463571d541 Mon Sep 17 00:00:00 2001 From: Fred Hebert Date: Fri, 11 Aug 2017 13:58:13 -0400 Subject: Fix recursive profile merging in umbrella apps When a config file exists at the root of a project, defines a given configuration value for a given profile, and that a sub-application (umbrella app) also has the same profile defined with the same key (but different values), the configuration values of the sub-application's profile would get silently dropped. The problem being that when the function to merge profiles is applied recursively, it is applied to each profile (so it will merge on the keys test, prod, etc.) rather than to each of the values of each profile. This patch reworks the profile merging so that the current behaviour is respected overall (a profile cannot be cancelled by a subdep's non-existant profile since its value should have been ignored), but ensures that sub-deps' profiles are otherwise applied recursively with the proper rules: - dependencies favor prior values - plugins favor new values - erl_first_files combine the lists - relx uses the tuple merge algorithm - erl_opts has its own custom merge as well - otherwise the new value takes precedence A test has also been added. There is a risk of breakage in some applications that may have relied on the buggy behaviour to work, though at this time we are aware of none of them. --- src/rebar3.erl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/rebar3.erl') diff --git a/src/rebar3.erl b/src/rebar3.erl index eec8968..2b24bca 100644 --- a/src/rebar3.erl +++ b/src/rebar3.erl @@ -396,8 +396,8 @@ safe_define_test_macro(Opts) -> %% defining a compile macro twice results in an exception so %% make sure 'TEST' is only defined once case test_defined(Opts) of - true -> []; - false -> [{d, 'TEST'}] + true -> Opts; + false -> [{d, 'TEST'}|Opts] end. test_defined([{d, 'TEST'}|_]) -> true; -- cgit v1.1 From 1effb745a38ed0f3d001b24393bf8dc177033af2 Mon Sep 17 00:00:00 2001 From: Shunichi Shinohara Date: Thu, 22 Feb 2018 09:22:07 +0900 Subject: Set unicode option for starndard_io at entry point --- src/rebar3.erl | 1 + 1 file changed, 1 insertion(+) (limited to 'src/rebar3.erl') diff --git a/src/rebar3.erl b/src/rebar3.erl index 2b24bca..80b4e4d 100644 --- a/src/rebar3.erl +++ b/src/rebar3.erl @@ -116,6 +116,7 @@ run(RawArgs) -> -spec run_aux(rebar_state:t(), [string()]) -> {ok, rebar_state:t()} | {error, term()}. run_aux(State, RawArgs) -> + io:setopts([{encoding, unicode}]), %% Profile override; can only support one profile State1 = case os:getenv("REBAR_PROFILE") of false -> -- cgit v1.1 From 543fe579a6d7c71fb4ed6a898540b573f6255dd0 Mon Sep 17 00:00:00 2001 From: Fred Hebert Date: Fri, 20 Apr 2018 21:03:05 -0400 Subject: Fix precedence rules of erl_opts for test profile When adding the 'TEST' macro to the test profile, we mistakenly sourced the erl_opts values from the base profile rather than the test profile itself. This means that in cases where the base profile set an option such as 'no_debug_info' and a profile overrode it with 'debug_info', the default options would get injected within the test profile, and broke the precedence rules, yielding incompatible values. This patch fixes things by adding the macro to the values sourced from the test profile itself, fixing the issue. --- src/rebar3.erl | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'src/rebar3.erl') diff --git a/src/rebar3.erl b/src/rebar3.erl index 80b4e4d..eb5ad58 100644 --- a/src/rebar3.erl +++ b/src/rebar3.erl @@ -389,7 +389,11 @@ state_from_global_config(Config, GlobalConfigFile) -> rebar_state:providers(rebar_state:new(GlobalConfig3, Config), GlobalPlugins). test_state(State) -> - ErlOpts = rebar_state:get(State, erl_opts, []), + %% Fetch the test profile's erl_opts only + Opts = rebar_state:opts(State), + Profiles = rebar_opts:get(Opts, profiles, []), + ProfileOpts = proplists:get_value(test, Profiles, []), + ErlOpts = proplists:get_value(erl_opts, ProfileOpts, []), TestOpts = safe_define_test_macro(ErlOpts), [{extra_src_dirs, ["test"]}, {erl_opts, TestOpts}]. -- cgit v1.1 From 5f9b4293bc029e2132d7c442cb5b4480915ea0e4 Mon Sep 17 00:00:00 2001 From: Fred Hebert Date: Thu, 3 May 2018 07:12:11 -0400 Subject: Work around OTP-21 deprecation of get_stacktrace() Based off a macro by @okeuday at https://github.com/erlang/otp/pull/1783 --- src/rebar3.erl | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) (limited to 'src/rebar3.erl') diff --git a/src/rebar3.erl b/src/rebar3.erl index eb5ad58..8e9d4b1 100644 --- a/src/rebar3.erl +++ b/src/rebar3.erl @@ -67,10 +67,10 @@ main(Args) -> {ok, _State} -> erlang:halt(0); Error -> - handle_error(Error) + handle_error(Error, []) catch - _:Error -> - handle_error(Error) + ?WITH_STACKTRACE(_,Error,Stacktrace) + handle_error(Error, Stacktrace) end. %% @doc Erlang-API entry point @@ -299,15 +299,15 @@ global_option_spec_list() -> %% @private translate unhandled errors and internal return codes into proper %% erroneous program exits. --spec handle_error(term()) -> no_return(). -handle_error(rebar_abort) -> +-spec handle_error(term(), term()) -> no_return(). +handle_error(rebar_abort, _) -> erlang:halt(1); -handle_error({error, rebar_abort}) -> +handle_error({error, rebar_abort}, _) -> erlang:halt(1); -handle_error({error, {Module, Reason}}) -> +handle_error({error, {Module, Reason}}, Stacktrace) -> case code:which(Module) of non_existing -> - ?CRASHDUMP("~p: ~p~n~p~n~n", [Module, Reason, erlang:get_stacktrace()]), + ?CRASHDUMP("~p: ~p~n~p~n~n", [Module, Reason, Stacktrace]), ?ERROR("Uncaught error in rebar_core. Run with DEBUG=1 to stacktrace or consult rebar3.crashdump", []), ?DEBUG("Uncaught error: ~p ~p", [Module, Reason]), ?INFO("When submitting a bug report, please include the output of `rebar3 report \"your command\"`", []); @@ -315,13 +315,12 @@ handle_error({error, {Module, Reason}}) -> ?ERROR("~ts", [Module:format_error(Reason)]) end, erlang:halt(1); -handle_error({error, Error}) when is_list(Error) -> +handle_error({error, Error}, _) when is_list(Error) -> ?ERROR("~ts", [Error]), erlang:halt(1); -handle_error(Error) -> +handle_error(Error, StackTrace) -> %% Nothing should percolate up from rebar_core; %% Dump this error to console - StackTrace = erlang:get_stacktrace(), ?CRASHDUMP("Error: ~p~n~p~n~n", [Error, StackTrace]), ?ERROR("Uncaught error in rebar_core. Run with DEBUG=1 to see stacktrace or consult rebar3.crashdump", []), ?DEBUG("Uncaught error: ~p", [Error]), -- cgit v1.1 From c5ae9f3fed035d2ef8f072da53647c212f92db8b Mon Sep 17 00:00:00 2001 From: Grigory Starinkin Date: Tue, 8 May 2018 21:42:43 +0100 Subject: start at least one async thread in async thread pool fixes an issue when shell is terminated with an error "Bus error: 10", on attempt to run rebar shell with verbose logging --- src/rebar3.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/rebar3.erl') diff --git a/src/rebar3.erl b/src/rebar3.erl index 8e9d4b1..9a5486d 100644 --- a/src/rebar3.erl +++ b/src/rebar3.erl @@ -54,7 +54,7 @@ %% ==================================================================== %% @doc For running with: -%% erl +sbtu +A0 -noinput -mode minimal -boot start_clean -s rebar3 main -extra "$@" +%% erl +sbtu +A1 -noinput -mode minimal -boot start_clean -s rebar3 main -extra "$@" -spec main() -> no_return(). main() -> List = init:get_plain_arguments(), -- cgit v1.1 From 70f063dc15d4003f0a5dc85523de02397d9cc250 Mon Sep 17 00:00:00 2001 From: Bryan Paxton Date: Sat, 9 Jun 2018 18:25:17 -0500 Subject: Finish adding specs for private funs in rebar3.erl - added type specs for following private functions: - run/1 - set_options/2 - test_state/1 - safe_define_test_macro/1 - test_defined/1 --- src/rebar3.erl | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src/rebar3.erl') diff --git a/src/rebar3.erl b/src/rebar3.erl index 9a5486d..ec8e953 100644 --- a/src/rebar3.erl +++ b/src/rebar3.erl @@ -93,6 +93,7 @@ run(BaseState, Commands) -> %% arguments passed, if they have any relevance; used to translate %% from the escript call-site into a common one with the library %% usage. +-spec run([any(), ...]) -> {ok, rebar_state:t()} | {error, term()}. run(RawArgs) -> start_and_load_apps(command_line), @@ -239,6 +240,7 @@ parse_args([Task | RawRest]) -> {list_to_atom(Task), RawRest}. %% @private actually not too sure what this does anymore. +-spec set_options(rebar_state:t(),{[any()],[any()]}) -> {rebar_state:t(),[any()]}. set_options(State, {Options, NonOptArgs}) -> GlobalDefines = proplists:get_all_values(defines, Options), @@ -387,6 +389,7 @@ state_from_global_config(Config, GlobalConfigFile) -> GlobalConfig3 = rebar_state:set(GlobalConfig2, {plugins, global}, rebar_state:get(GlobalConfigThrowAway, plugins, [])), rebar_state:providers(rebar_state:new(GlobalConfig3, Config), GlobalPlugins). +-spec test_state(rebar_state:t()) -> [{'extra_src_dirs',[string()]} | {'erl_opts',[any()]}]. test_state(State) -> %% Fetch the test profile's erl_opts only Opts = rebar_state:opts(State), @@ -396,6 +399,7 @@ test_state(State) -> TestOpts = safe_define_test_macro(ErlOpts), [{extra_src_dirs, ["test"]}, {erl_opts, TestOpts}]. +-spec safe_define_test_macro([any()]) -> [any()] | [{'d',atom()} | any()]. safe_define_test_macro(Opts) -> %% defining a compile macro twice results in an exception so %% make sure 'TEST' is only defined once @@ -404,6 +408,7 @@ safe_define_test_macro(Opts) -> false -> [{d, 'TEST'}|Opts] end. +-spec test_defined([{d, atom()} | {d, atom(), term()} | term()]) -> boolean(). test_defined([{d, 'TEST'}|_]) -> true; test_defined([{d, 'TEST', true}|_]) -> true; test_defined([_|Rest]) -> test_defined(Rest); -- cgit v1.1 From 56b7d88975aa8da6446857cfd92de0825024bf63 Mon Sep 17 00:00:00 2001 From: Tristan Sloughter Date: Thu, 13 Sep 2018 19:36:00 -0600 Subject: support for hex v2, multiple repository fetching, private organizations (#1884) * update to hex_core for hex-v2 repo support (#1865) * update to hex_core for hex-v2 repo support This patch adds only single repo hex-v2 support through hex_core. Packages no longer filtered out by buildtool metadata and the package index is updated per-package instead of fetched as one large ets dump. * tell travis to also build hex_core branch * support list of repos for hex packages (#1866) * support list of repos for hex packages repos are defined under the hex key in rebar configs. They can be defined at the top level of a project or globally, but not in profiles and the repos configured in dependencies are also ignored. Searching for packages involves first checking for a match in the local repo index cache, in the order repos are defined. If not found each repo is checked through the hex api for any known versions of the package and the first repo with a version that fits the constraint is used. * add {repos, replace, []} for overriding the global & default repos * add hex auth handling for repos (#1874) auth token are kept in a hex.config file that is modified by the rebar3 hex plugin. Repo names that have a : separating a parent and child are considered organizations. The parent repo's auth will be included with the child. So an organization named hexpm:rebar3_test will include any hexpm auth tokens found in the rebar3_test organization's configuration. * move packages to top level of of hexpm cache dir (#1876) * move packages to top level of of hexpm cache dir * append organization name to parent's repo_url when parsing repos * only eval config scripts and apply overrides once per app (#1879) * only eval config scripts and apply overrides once per app * move new resource behaviour to rebar_resource_v2 and keep v1 * cleanup use of rebar_resource module and unused functions * cleanup error messages and unused code * when discovering apps support mix packages as unbuilt apps (#1882) * use hex_core tarball unpacking support in pkg resource (#1883) * use hex_core tarball unpacking support in pkg resource * ignore etag if package doesn't exist and delete if checksum fails * add back tests for bad package checksums * improve bad registry checksum error message --- src/rebar3.erl | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) (limited to 'src/rebar3.erl') diff --git a/src/rebar3.erl b/src/rebar3.erl index ec8e953..e87cb19 100644 --- a/src/rebar3.erl +++ b/src/rebar3.erl @@ -103,7 +103,7 @@ run(RawArgs) -> case erlang:system_info(version) of "6.1" -> ?WARN("Due to a filelib bug in Erlang 17.1 it is recommended" - "you update to a newer release.", []); + "you update to a newer release.", []); _ -> ok end, @@ -139,8 +139,14 @@ run_aux(State, RawArgs) -> rebar_state:set(State1, rebar_packages_cdn, CDN) end, + %% TODO: this means use of REBAR_PROFILE=profile will replace the repos with + %% the repos defined in the profile. But it will not work with `as profile`. + %% Maybe it shouldn't work with either to be consistent? + Resources = application:get_env(rebar, resources, []), + State2_ = rebar_state:create_resources(Resources, State2), + %% bootstrap test profile - State3 = rebar_state:add_to_profile(State2, test, test_state(State1)), + State3 = rebar_state:add_to_profile(State2_, test, test_state(State1)), %% Process each command, resetting any state between each one BaseDir = rebar_state:get(State, base_dir, ?DEFAULT_BASE_DIR), @@ -375,7 +381,11 @@ state_from_global_config(Config, GlobalConfigFile) -> %% We don't want to worry about global plugin install state effecting later %% usage. So we throw away the global profile state used for plugin install. - GlobalConfigThrowAway = rebar_state:current_profiles(GlobalConfig, [global]), + GlobalConfigThrowAway0 = rebar_state:current_profiles(GlobalConfig, [global]), + + Resources = application:get_env(rebar, resources, []), + GlobalConfigThrowAway = rebar_state:create_resources(Resources, GlobalConfigThrowAway0), + GlobalState = case rebar_state:get(GlobalConfigThrowAway, plugins, []) of [] -> GlobalConfigThrowAway; @@ -386,7 +396,8 @@ state_from_global_config(Config, GlobalConfigFile) -> end, GlobalPlugins = rebar_state:providers(GlobalState), GlobalConfig2 = rebar_state:set(GlobalConfig, plugins, []), - GlobalConfig3 = rebar_state:set(GlobalConfig2, {plugins, global}, rebar_state:get(GlobalConfigThrowAway, plugins, [])), + GlobalConfig3 = rebar_state:set(GlobalConfig2, {plugins, global}, + rebar_state:get(GlobalConfigThrowAway, plugins, [])), rebar_state:providers(rebar_state:new(GlobalConfig3, Config), GlobalPlugins). -spec test_state(rebar_state:t()) -> [{'extra_src_dirs',[string()]} | {'erl_opts',[any()]}]. -- cgit v1.1 From dec484643c233fda9c17d38c1854ba7f3f37547b Mon Sep 17 00:00:00 2001 From: Tristan Sloughter Date: Fri, 5 Oct 2018 08:29:07 -0600 Subject: compiler behaviour (#1893) * add compile type for dynamic project compilation * new rebar_compiler abstraction for running multiple compilers rebar_compiler is a new behaviour that a plugin can implement to be called on any ues of the compile provider to compile source files and keep track of their dependencies. * fix check that modules in .app modules list are from src_dirs * use project_type to find module for building projects * allow plugins to add project builders and compilers --- src/rebar3.erl | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src/rebar3.erl') diff --git a/src/rebar3.erl b/src/rebar3.erl index e87cb19..c931a85 100644 --- a/src/rebar3.erl +++ b/src/rebar3.erl @@ -139,11 +139,14 @@ run_aux(State, RawArgs) -> rebar_state:set(State1, rebar_packages_cdn, CDN) end, + Compilers = application:get_env(rebar, compilers, []), + State0 = rebar_state:compilers(State2, Compilers), + %% TODO: this means use of REBAR_PROFILE=profile will replace the repos with %% the repos defined in the profile. But it will not work with `as profile`. %% Maybe it shouldn't work with either to be consistent? Resources = application:get_env(rebar, resources, []), - State2_ = rebar_state:create_resources(Resources, State2), + State2_ = rebar_state:create_resources(Resources, State0), %% bootstrap test profile State3 = rebar_state:add_to_profile(State2_, test, test_state(State1)), -- cgit v1.1 From dada4e36e6d9a5c4b41bbe1f68389520e7c59ace Mon Sep 17 00:00:00 2001 From: Fred Hebert Date: Thu, 11 Oct 2018 08:38:37 -0400 Subject: Optimize path handling - Only set paths that need to be put as a priority - Clean up paths before leaving API mode The first point accounted for some performance cost, but the latter one explains the 40% overhead in test runs: since rebar3 calls rebar3 a lot with a bunch of fake apps, and that the new mechanism for path handling by default does not _remove_ paths, it just _orders_ them, we would end up in a situation where as the tests ran, more and more fake paths would get added to the VM. By the time the run was over, all path handling would take longer since more paths needed filtering every time. By resetting paths at the end of an API run, we prevent a given 'project' from polluting another one's runtime and performance once the API successfully returns. --- src/rebar3.erl | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) (limited to 'src/rebar3.erl') diff --git a/src/rebar3.erl b/src/rebar3.erl index c931a85..059d530 100644 --- a/src/rebar3.erl +++ b/src/rebar3.erl @@ -175,7 +175,20 @@ run_aux(State, RawArgs) -> State10 = rebar_state:code_paths(State9, default, code:get_path()), - rebar_core:init_command(rebar_state:command_args(State10, Args), Task). + case rebar_core:init_command(rebar_state:command_args(State10, Args), Task) of + {ok, State11} -> + case rebar_state:get(State11, caller, command_line) of + api -> + rebar_paths:unset_paths([deps, plugins], State11), + {ok, State11}; + _ -> + {ok, State11} + end; + Other -> + Other + end. + + %% @doc set up base configuration having to do with verbosity, where %% to find config files, and so on, and return an internal rebar3 state term. -- cgit v1.1 From 60dc0504bf46e9ece179da9b20c54e0e2a3e11c6 Mon Sep 17 00:00:00 2001 From: Tristan Sloughter Date: Thu, 8 Nov 2018 14:09:07 -0700 Subject: fix compilation of global plugins (#1935) --- src/rebar3.erl | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'src/rebar3.erl') diff --git a/src/rebar3.erl b/src/rebar3.erl index 059d530..a490a15 100644 --- a/src/rebar3.erl +++ b/src/rebar3.erl @@ -402,18 +402,21 @@ state_from_global_config(Config, GlobalConfigFile) -> Resources = application:get_env(rebar, resources, []), GlobalConfigThrowAway = rebar_state:create_resources(Resources, GlobalConfigThrowAway0), - GlobalState = case rebar_state:get(GlobalConfigThrowAway, plugins, []) of + Compilers = application:get_env(rebar, compilers, []), + GlobalConfigThrowAway1 = rebar_state:compilers(GlobalConfigThrowAway, Compilers), + + GlobalState = case rebar_state:get(GlobalConfigThrowAway1, plugins, []) of [] -> - GlobalConfigThrowAway; + GlobalConfigThrowAway1; GlobalPluginsToInstall -> rebar_plugins:handle_plugins(global, GlobalPluginsToInstall, - GlobalConfigThrowAway) + GlobalConfigThrowAway1) end, GlobalPlugins = rebar_state:providers(GlobalState), GlobalConfig2 = rebar_state:set(GlobalConfig, plugins, []), GlobalConfig3 = rebar_state:set(GlobalConfig2, {plugins, global}, - rebar_state:get(GlobalConfigThrowAway, plugins, [])), + rebar_state:get(GlobalConfigThrowAway1, plugins, [])), rebar_state:providers(rebar_state:new(GlobalConfig3, Config), GlobalPlugins). -spec test_state(rebar_state:t()) -> [{'extra_src_dirs',[string()]} | {'erl_opts',[any()]}]. -- cgit v1.1