diff options
40 files changed, 589 insertions, 104 deletions
@@ -1,12 +1,11 @@ -*.beam -rebar +/ebin/*.beam +/rebar *~ *.orig .*.swp -rt.work -.test -dialyzer_warnings -rebar.cmd -.eunit -deps -.rebar/* +/rt.work +/dialyzer_warnings +/rebar.cmd +/.eunit +/deps +/.rebar diff --git a/RELEASE-NOTES.md b/RELEASE-NOTES.md index bdfb3d7..a072d1b 100644 --- a/RELEASE-NOTES.md +++ b/RELEASE-NOTES.md @@ -1,3 +1,36 @@ +# Rebar 2.3.0 + +* rebar/56: [add preprocess support for edoc](https://github.com/basho/rebar/pull/56) +* rebar/90: [look for new and old versions in the target parent](https://github.com/basho/rebar/pull/90) +* rebar/95: [Propagate exit status from nodetool to runner script](https://github.com/basho/rebar/pull/95) +* rebar/98: [Restore R13B03 compatibility](https://github.com/basho/rebar/pull/98) +* rebar/115: [specify the erlang system module name while calling monitor/2](https://github.com/basho/rebar/pull/115) +* rebar/129: [Allow plugins to participate in pre and post processing](https://github.com/basho/rebar/pull/129) +* rebar/139: [@ characters before elses were causing the script to not run](https://github.com/basho/rebar/pull/139) +* rebar/175: [Common Test changes to add configurable log dir and improve testing framework overlaps.](https://github.com/basho/rebar/pull/175) +* rebar/188: [Generated rebar.cmd needs a tweak](https://github.com/basho/rebar/issues/188) +* rebar/208: [Is the "Release Handling" wiki page out of date?](https://github.com/basho/rebar/issues/208) +* rebar/219: [remove dependency on erl_interface](https://github.com/basho/rebar/pull/219) +* rebar/220: [add crypto, syntax_tools and tools to applications key as dependencies](https://github.com/basho/rebar/pull/220) +* rebar/221: [Versioning scheme](https://github.com/basho/rebar/issues/221) +* rebar/223: [ebadf if run under nohup](https://github.com/basho/rebar/issues/223) +* rebar/224: [When generating a release rebar should expand VCS version in the top directory (git)](https://github.com/basho/rebar/pull/224) +* rebar/226: [make check dialyzer error](https://github.com/basho/rebar/issues/226) +* rebar/228: [about load plugin modules](https://github.com/basho/rebar/issues/228) +* rebar/230: [Support ct_run using short name](https://github.com/basho/rebar/pull/230) +* rebar/232: [bug about ./rebar generate ](https://github.com/basho/rebar/issues/232) +* rebar/233: [Add {git_format, Format} notation for vsn entries](https://github.com/basho/rebar/pull/233) +* rebar/234: [Use ?INFO instead of ?CONSOLE when printing directory changes](https://github.com/basho/rebar/pull/234) +* rebar/237: [Allow rebar.config and reltool.config to be configured](https://github.com/basho/rebar/pull/237) +* rebar/252: [eunit suite=<suite name> fails if there is a rebar dependency defined.](https://github.com/basho/rebar/issues/252) +* rebar/253: [rebar creates templates in deps as well as main](https://github.com/basho/rebar/issues/253) +* rebar/254: [Force running eunit tests via -k cmdline switch](https://github.com/basho/rebar/pull/254) +* rebar/265: [Fix rebar_base_compiler:format_errors/3 for errors in include files](https://github.com/basho/rebar/pull/265) +* rebar/267: [Add 'eunit-compile' cmd (Suggested-by: Joe Norton)](https://github.com/basho/rebar/pull/267) +* rebar/268: [Add 'qc' command](https://github.com/basho/rebar/pull/268) +* rebar/269: [Add qc and test-compile commands](https://github.com/basho/rebar/pull/269) + + # Rebar 2.2.0 ## PR's Merged @@ -121,3 +121,4 @@ Sylvain Benner Oliver Ferrigni Dave Thomas Evgeniy Khramtsov +YeJun Su diff --git a/ebin/rebar.app b/ebin/rebar.app index 6b4702a..5d53718 100644 --- a/ebin/rebar.app +++ b/ebin/rebar.app @@ -3,7 +3,7 @@ {application, rebar, [{description, "Rebar: Erlang Build Tool"}, - {vsn, "2.2.0"}, + {vsn, "2.3.0"}, {modules, [ rebar, rebar_abnfc_compiler, rebar_app_utils, @@ -93,7 +93,7 @@ ]}, {recursive_cmds, [ 'check-deps', - 'compile', + compile, 'delete-deps', 'get-deps', 'list-deps', diff --git a/inttest/code_path_no_recurse/code_path_no_recurse_rt.erl b/inttest/code_path_no_recurse/code_path_no_recurse_rt.erl new file mode 100644 index 0000000..d884bcc --- /dev/null +++ b/inttest/code_path_no_recurse/code_path_no_recurse_rt.erl @@ -0,0 +1,19 @@ +-module(code_path_no_recurse_rt). +-export([files/0, + run/1]). + +files() -> + [ + {copy, "../../rebar", "rebar"}, + {copy, "rebar.config", "rebar.config"}, + {copy, "src", "src"}, + {copy, "test", "test"}, + {copy, "deps", "deps"} + ]. + +run(_Dir) -> + retest:log(info, "Compile project~n"), + {ok, _} = retest:sh("./rebar -v compile"), + retest:log(info, "Run eunit with referenced deps on the code path~n"), + {ok, _} = retest:sh("./rebar -v eunit"), + ok. diff --git a/inttest/code_path_no_recurse/deps/bazdep/src/bazdep.app.src b/inttest/code_path_no_recurse/deps/bazdep/src/bazdep.app.src new file mode 100644 index 0000000..7f7b3f9 --- /dev/null +++ b/inttest/code_path_no_recurse/deps/bazdep/src/bazdep.app.src @@ -0,0 +1,12 @@ +{application, bazdep, + [ + {description, ""}, + {vsn, "1"}, + {registered, []}, + {applications, [ + kernel, + stdlib + ]}, + {mod, {bazdep, []}}, + {env, []} + ]}. diff --git a/inttest/code_path_no_recurse/deps/bazdep/src/bazdep.erl b/inttest/code_path_no_recurse/deps/bazdep/src/bazdep.erl new file mode 100644 index 0000000..aef4cf3 --- /dev/null +++ b/inttest/code_path_no_recurse/deps/bazdep/src/bazdep.erl @@ -0,0 +1,6 @@ +-module(bazdep). + +-export([bazdep/0]). + +bazdep() -> + bazdep. diff --git a/inttest/code_path_no_recurse/deps/bazdep/test/bazdep_tests.erl b/inttest/code_path_no_recurse/deps/bazdep/test/bazdep_tests.erl new file mode 100644 index 0000000..b5190f6 --- /dev/null +++ b/inttest/code_path_no_recurse/deps/bazdep/test/bazdep_tests.erl @@ -0,0 +1,5 @@ +-module(bazdep_tests). +-include_lib("eunit/include/eunit.hrl"). + +bazdep_test() -> + ?assert(bazdep:bazdep() =:= bazdep). diff --git a/inttest/code_path_no_recurse/deps/foodep/rebar.config b/inttest/code_path_no_recurse/deps/foodep/rebar.config new file mode 100644 index 0000000..cdaf168 --- /dev/null +++ b/inttest/code_path_no_recurse/deps/foodep/rebar.config @@ -0,0 +1 @@ +{deps, [{bazdep, "1"}]}. diff --git a/inttest/code_path_no_recurse/deps/foodep/src/foodep.app.src b/inttest/code_path_no_recurse/deps/foodep/src/foodep.app.src new file mode 100644 index 0000000..c0642fb --- /dev/null +++ b/inttest/code_path_no_recurse/deps/foodep/src/foodep.app.src @@ -0,0 +1,12 @@ +{application, foodep, + [ + {description, ""}, + {vsn, "1"}, + {registered, []}, + {applications, [ + kernel, + stdlib + ]}, + {mod, {foodep, []}}, + {env, []} + ]}. diff --git a/inttest/code_path_no_recurse/deps/foodep/src/foodep.erl b/inttest/code_path_no_recurse/deps/foodep/src/foodep.erl new file mode 100644 index 0000000..3d43d0e --- /dev/null +++ b/inttest/code_path_no_recurse/deps/foodep/src/foodep.erl @@ -0,0 +1,6 @@ +-module(foodep). + +-export([foodep/0]). + +foodep() -> + bazdep:bazdep() =:= bazdep. diff --git a/inttest/code_path_no_recurse/deps/foodep/test/foodep_tests.erl b/inttest/code_path_no_recurse/deps/foodep/test/foodep_tests.erl new file mode 100644 index 0000000..66d7b8b --- /dev/null +++ b/inttest/code_path_no_recurse/deps/foodep/test/foodep_tests.erl @@ -0,0 +1,5 @@ +-module(foodep_tests). +-include_lib("eunit/include/eunit.hrl"). + +foodep_test() -> + ?assert(foodep:foodep()). diff --git a/inttest/code_path_no_recurse/deps/unuseddep/src/unuseddep.app.src b/inttest/code_path_no_recurse/deps/unuseddep/src/unuseddep.app.src new file mode 100644 index 0000000..d0bc233 --- /dev/null +++ b/inttest/code_path_no_recurse/deps/unuseddep/src/unuseddep.app.src @@ -0,0 +1,12 @@ +{application, unuseddep, + [ + {description, ""}, + {vsn, "1"}, + {registered, []}, + {applications, [ + kernel, + stdlib + ]}, + {mod, {unuseddep, []}}, + {env, []} + ]}. diff --git a/inttest/code_path_no_recurse/deps/unuseddep/src/unuseddep.erl b/inttest/code_path_no_recurse/deps/unuseddep/src/unuseddep.erl new file mode 100644 index 0000000..a990345 --- /dev/null +++ b/inttest/code_path_no_recurse/deps/unuseddep/src/unuseddep.erl @@ -0,0 +1,6 @@ +-module(unuseddep). + +-export([unuseddep/0]). + +unuseddep() -> + unuseddep. diff --git a/inttest/code_path_no_recurse/rebar.config b/inttest/code_path_no_recurse/rebar.config new file mode 100644 index 0000000..4b358de --- /dev/null +++ b/inttest/code_path_no_recurse/rebar.config @@ -0,0 +1 @@ +{deps, [{foodep, "1"}]}. diff --git a/inttest/code_path_no_recurse/src/codepath.app.src b/inttest/code_path_no_recurse/src/codepath.app.src new file mode 100644 index 0000000..3aa200f --- /dev/null +++ b/inttest/code_path_no_recurse/src/codepath.app.src @@ -0,0 +1,12 @@ +{application, codepath, + [ + {description, ""}, + {vsn, "1"}, + {registered, []}, + {applications, [ + kernel, + stdlib + ]}, + {mod, {codepath, []}}, + {env, []} + ]}. diff --git a/inttest/code_path_no_recurse/src/codepath.erl b/inttest/code_path_no_recurse/src/codepath.erl new file mode 100644 index 0000000..df4e6b0 --- /dev/null +++ b/inttest/code_path_no_recurse/src/codepath.erl @@ -0,0 +1,6 @@ +-module(codepath). + +-export([codepath/0]). + +codepath() -> + foodep:foodep(). diff --git a/inttest/code_path_no_recurse/test/codepath_tests.erl b/inttest/code_path_no_recurse/test/codepath_tests.erl new file mode 100644 index 0000000..01a1d2a --- /dev/null +++ b/inttest/code_path_no_recurse/test/codepath_tests.erl @@ -0,0 +1,12 @@ +-module(codepath_tests). +-include_lib("eunit/include/eunit.hrl"). + +codepath_test() -> + ?assertEqual({module, codepath}, code:ensure_loaded(codepath)), + ?assertEqual({module, foodep}, code:ensure_loaded(foodep)), + ?assertEqual({module, bazdep}, code:ensure_loaded(bazdep)), + ?assert(codepath:codepath()). + +unuseddep_test() -> + ?assertEqual(non_existing, code:which(unuseddep)), + ?assertEqual({error, nofile}, code:ensure_loaded(unuseddep)). diff --git a/inttest/erlc/asn1/SIMPLE-ASN.asn1 b/inttest/erlc/asn1/SIMPLE-ASN.asn1 new file mode 100644 index 0000000..62f0860 --- /dev/null +++ b/inttest/erlc/asn1/SIMPLE-ASN.asn1 @@ -0,0 +1,7 @@ +SIMPLE-ASN DEFINITIONS ::= BEGIN + + SimpleMessage ::= SEQUENCE { + id INTEGER + } + +END diff --git a/inttest/erlc/erlc_rt.erl b/inttest/erlc/erlc_rt.erl new file mode 100644 index 0000000..354ad29 --- /dev/null +++ b/inttest/erlc/erlc_rt.erl @@ -0,0 +1,98 @@ +-module(erlc_rt). +-export([files/0, + run/1]). + +-include_lib("eunit/include/eunit.hrl"). + +-define(MODULES, + [first_xrl, + first_yrl, + foo, + foo_app, + foo_sup, + foo_test_worker, + foo_worker, + 'SIMPLE-ASN']). + +-define(BEAM_FILES, + ["first_xrl.beam", + "first_yrl.beam", + "foo.beam", + "foo_app.beam", + "foo_sup.beam", + "foo_test_worker.beam", + "foo_worker.beam", + "SIMPLE-ASN.beam"]). + +files() -> + [ + {copy, "../../rebar", "rebar"}, + {copy, "rebar.config", "rebar.config"}, + {copy, "rebar-no_debug_info.config", "rebar-no_debug_info.config"}, + {copy, "include", "include"}, + {copy, "extra-include", "extra-include"}, + {copy, "src", "src"}, + {copy, "extra-src", "extra-src"}, + {copy, "mibs", "mibs"}, + {copy, "asn1", "asn1"}, + {create, "ebin/foo.app", app(foo, ?MODULES)} + ]. + +run(_Dir) -> + ?assertMatch({ok, _}, retest_sh:run("./rebar compile", [])), + ok = check_beams(true), + ok = check_debug_info(true), + MibResult = filename:join(["priv", "mibs", "SIMPLE-MIB.bin"]), + ?assertMatch(true, filelib:is_regular(MibResult)), + ?assertMatch({ok, _}, retest_sh:run("./rebar clean", [])), + ok = check_beams(false), + ?assertMatch(false, filelib:is_regular(MibResult)), + ?assertMatch( + {ok, _}, + retest_sh:run("./rebar -C rebar-no_debug_info.config compile", [])), + ok = check_beams(true), + ok = check_debug_info(false), + ?assertMatch(true, filelib:is_regular(MibResult)), + ok. + +check_beams(Exist) -> + check_files(Exist, fun filelib:is_regular/1). + +check_debug_info(HasDebugInfo) -> + check_files(HasDebugInfo, fun has_debug_info/1). + +check_files(Expected, Check) -> + lists:foreach( + fun(F) -> + File = filename:join("ebin", F), + ?assertEqual(Expected, Check(File)) + end, + ?BEAM_FILES). + +%% NOTE: Copied from dialyzer_utils:get_abstract_code_from_beam/1 and +%% modified for local use. We could have called the function directly, +%% but dialyzer_utils is not an official API to rely on. +has_debug_info(File) -> + case beam_lib:chunks(File, [abstract_code]) of + {ok, {_Mod, List}} -> + case lists:keyfind(abstract_code, 1, List) of + {abstract_code, {raw_abstract_v1, _Abstr}} -> + true; + _ -> + false + end; + _ -> + false + end. + +%% +%% Generate the contents of a simple .app file +%% +app(Name, Modules) -> + App = {application, Name, + [{description, atom_to_list(Name)}, + {vsn, "1"}, + {modules, Modules}, + {registered, []}, + {applications, [kernel, stdlib]}]}, + io_lib:format("~p.\n", [App]). diff --git a/inttest/erlc/extra-include/foo_extra.hrl b/inttest/erlc/extra-include/foo_extra.hrl new file mode 100644 index 0000000..228affa --- /dev/null +++ b/inttest/erlc/extra-include/foo_extra.hrl @@ -0,0 +1 @@ +-define(FOO_EXTRA, foo_extra). diff --git a/inttest/erlc/extra-src/foo_sup.erl b/inttest/erlc/extra-src/foo_sup.erl new file mode 100644 index 0000000..a0f06b6 --- /dev/null +++ b/inttest/erlc/extra-src/foo_sup.erl @@ -0,0 +1,13 @@ +-module(foo_sup). + +-behavior(supervisor). + +-export([start_link/0, + init/1]). + +start_link() -> + supervisor:start_link({local, ?MODULE}, ?MODULE, []). + +init(_Args) -> + FooChild = {foo,{foo, start_link, []}, permanent, 5000, worker, [foo]}, + {ok,{{one_for_all,1,1}, [FooChild]}}. diff --git a/inttest/erlc/include/foo_core.hrl b/inttest/erlc/include/foo_core.hrl new file mode 100644 index 0000000..2363140 --- /dev/null +++ b/inttest/erlc/include/foo_core.hrl @@ -0,0 +1 @@ +-define(FOO_CORE, foo_core). diff --git a/inttest/erlc/mibs/SIMPLE-MIB.mib b/inttest/erlc/mibs/SIMPLE-MIB.mib new file mode 100644 index 0000000..ca8735a --- /dev/null +++ b/inttest/erlc/mibs/SIMPLE-MIB.mib @@ -0,0 +1,26 @@ +-- SIMPLE-MIB. +-- This is just a simple MIB used for testing! +-- + + +SIMPLE-MIB DEFINITIONS ::= BEGIN + +IMPORTS + MODULE-IDENTITY, enterprises + FROM SNMPv2-SMI; + +ericsson MODULE-IDENTITY + LAST-UPDATED + "201403060000Z" + ORGANIZATION + "rebar" + CONTACT-INFO + "rebar <rebar@example.com> + or + whoever is currently responsible for the SIMPLE + enterprise MIB tree branch (enterprises.999)." + DESCRIPTION + "This very small module is made available + for mib-compilation testing." + ::= { enterprises 999 } +END diff --git a/inttest/erlc/rebar-no_debug_info.config b/inttest/erlc/rebar-no_debug_info.config new file mode 100644 index 0000000..1a7113a --- /dev/null +++ b/inttest/erlc/rebar-no_debug_info.config @@ -0,0 +1,11 @@ +%% -*- mode: erlang;erlang-indent-level: 4;indent-tabs-mode: nil -*- +%% ex: ts=4 sw=4 ft=erlang et +{erl_first_files, ["first_xrl.erl", "first_yrl.erl"]}. + +{erl_opts, + [ + no_debug_info, + {i, "extra-include"}, + {src_dirs, ["src", "extra-src"]}, + {platform_define, "R13|R14", 'NO_CALLBACK_ATTRIBUTE'} + ]}. diff --git a/inttest/erlc/rebar.config b/inttest/erlc/rebar.config new file mode 100644 index 0000000..6a1082a --- /dev/null +++ b/inttest/erlc/rebar.config @@ -0,0 +1,10 @@ +%% -*- mode: erlang;erlang-indent-level: 4;indent-tabs-mode: nil -*- +%% ex: ts=4 sw=4 ft=erlang et +{erl_first_files, ["first_xrl.erl", "first_yrl.erl"]}. + +{erl_opts, + [ + {i, "extra-include"}, + {src_dirs, ["src", "extra-src"]}, + {platform_define, "R13|R14", 'NO_CALLBACK_ATTRIBUTE'} + ]}. diff --git a/inttest/erlc/src/behaviour/foo_worker.erl b/inttest/erlc/src/behaviour/foo_worker.erl new file mode 100644 index 0000000..307c69a --- /dev/null +++ b/inttest/erlc/src/behaviour/foo_worker.erl @@ -0,0 +1,14 @@ +-module(foo_worker). + +-ifdef(NO_CALLBACK_ATTRIBUTE). + +-export([behaviour_info/1]). + +behaviour_info(callbacks) -> [{status, 0}]; +behaviour_info(_) -> undefined. + +-else. + +-callback status() -> 'idle' | 'busy'. + +-endif. diff --git a/inttest/erlc/src/first_xrl.xrl b/inttest/erlc/src/first_xrl.xrl new file mode 100644 index 0000000..0de4c70 --- /dev/null +++ b/inttest/erlc/src/first_xrl.xrl @@ -0,0 +1,13 @@ +Definitions. + +D = [0-9] + +Rules. + +{D}+ : + {token,{integer,TokenLine,list_to_integer(TokenChars)}}. + +{D}+\.{D}+((E|e)(\+|\-)?{D}+)? : + {token,{float,TokenLine,list_to_float(TokenChars)}}. + +Erlang code. diff --git a/inttest/erlc/src/first_yrl.yrl b/inttest/erlc/src/first_yrl.yrl new file mode 100644 index 0000000..8ccdb0e --- /dev/null +++ b/inttest/erlc/src/first_yrl.yrl @@ -0,0 +1,9 @@ +Nonterminals list elements element. +Terminals atom '(' ')'. +Rootsymbol list. +list -> '(' ')'. +list -> '(' elements ')'. +elements -> element. +elements -> element elements. +element -> atom. +element -> list. diff --git a/inttest/erlc/src/foo.erl b/inttest/erlc/src/foo.erl new file mode 100644 index 0000000..33e6cfc --- /dev/null +++ b/inttest/erlc/src/foo.erl @@ -0,0 +1,35 @@ +-module(foo). + +-export([start_link/0, + start_link/1, + init/1, + terminate/2, + handle_info/2, + handle_call/3, + handle_cast/2, + code_change/3]). + +-behavior(gen_server). + +-include("foo_core.hrl"). +-include("foo_extra.hrl"). +-include_lib("kernel/include/file.hrl"). + +-record(state, {node :: node()}). + +start_link() -> start_link(undefined). + +start_link(Args) -> + gen_server:start_link({local, ?MODULE}, ?MODULE, Args, []). + +init(_Args) -> {ok, #state{node=node()}}. + +terminate(_Reason, _Data) -> ok. + +handle_info(_Info, State) -> {noreply, State}. + +handle_cast(_Msg, State) -> {noreply, State}. + +handle_call(_Msg, _From, State) -> {reply, ok, State}. + +code_change(_OldVsn, State, _Extra) -> {ok, State}. diff --git a/inttest/erlc/src/foo_app.erl b/inttest/erlc/src/foo_app.erl new file mode 100644 index 0000000..a3c7a96 --- /dev/null +++ b/inttest/erlc/src/foo_app.erl @@ -0,0 +1,10 @@ +-module(foo_app). + +-behaviour(application). + +-export([start/2, + stop/1]). + +start(_Type, _Args) -> foo_sup:start_link(). + +stop(_State) -> ok. diff --git a/inttest/erlc/src/foo_test_worker.erl b/inttest/erlc/src/foo_test_worker.erl new file mode 100644 index 0000000..96ae932 --- /dev/null +++ b/inttest/erlc/src/foo_test_worker.erl @@ -0,0 +1,34 @@ +-module(foo_test_worker). + +-behaviour(gen_server). +-behaviour(foo_worker). + +-export([start_link/0, + start_link/1, + init/1, + handle_call/3, + handle_cast/2, + handle_info/2, + terminate/2, + code_change/3, + status/0]). + +-include_lib("kernel/include/inet.hrl"). + +start_link() -> start_link(undefined). + +start_link(Args) -> gen_server:start_link(?MODULE, Args, []). + +init([]) -> {ok, undefined}. + +handle_call(_Event, _From, State) -> {reply, ok, State}. + +handle_cast(_Event, State) -> {noreply, State}. + +handle_info(_Info, State) -> {noreply, State}. + +terminate(_Reason, _State) -> ok. + +code_change(_OldVsn, State, _Extra) -> {ok, State}. + +status() -> busy. diff --git a/src/rebar_core.erl b/src/rebar_core.erl index 81b9a6d..3a4f205 100644 --- a/src/rebar_core.erl +++ b/src/rebar_core.erl @@ -88,7 +88,7 @@ process_commands([Command | Rest], ParentConfig) -> %% path from inside a subdirectory. true = rebar_utils:expand_code_path(), {ParentConfig2, _DirSet} = process_dir(rebar_utils:get_cwd(), - ParentConfig1, Command, + Command, ParentConfig1, sets:new()), case get_operations(ParentConfig2) of Operations -> @@ -117,18 +117,13 @@ process_commands([Command | Rest], ParentConfig) -> end, process_commands(Rest, ParentConfig4). -process_dir(Dir, ParentConfig, Command, DirSet) -> +process_dir(Dir, Command, ParentConfig, DirSet) -> case filelib:is_dir(Dir) of false -> ?WARN("Skipping non-existent sub-dir: ~p\n", [Dir]), {ParentConfig, DirSet}; true -> - maybe_process_dir(Dir, ParentConfig, Command, DirSet) - end. - -maybe_process_dir(Dir, ParentConfig, Command, DirSet) -> - case should_cd_into_dir(Dir, ParentConfig, Command) of - true -> + WouldCd = would_cd_into_dir(Dir, Command, ParentConfig), ok = file:set_cwd(Dir), Config = maybe_load_local_config(Dir, ParentConfig), @@ -143,63 +138,89 @@ maybe_process_dir(Dir, ParentConfig, Command, DirSet) -> %% set of modules to process this dir. {ok, AvailModuleSets} = application:get_env(rebar, modules), ModuleSet = choose_module_set(AvailModuleSets, Dir), - skip_or_process_dir(ModuleSet, Config, CurrentCodePath, - Dir, Command, DirSet); + skip_or_process_dir(Dir, Command, Config, DirSet, CurrentCodePath, + ModuleSet, WouldCd) + end. + +would_cd_into_dir(Dir, Command, Config) -> + case would_cd_into_dir1(Dir, Command, Config) of + true -> + would_cd; false -> - {ParentConfig, DirSet} + would_not_cd end. -should_cd_into_dir(Dir, Config, Command) -> +would_cd_into_dir1(Dir, Command, Config) -> rebar_utils:processing_base_dir(Config, Dir) orelse rebar_config:is_recursive(Config) orelse - is_recursive_command(Config, Command). + is_recursive_command(Command, Config) orelse + is_generate_in_rel_dir(Command, Dir). -is_recursive_command(Config, Command) -> +%% Check whether the command is part of the built-in (or extended via +%% rebar.config) list of default-recursive commands. +is_recursive_command(Command, Config) -> {ok, AppCmds} = application:get_env(rebar, recursive_cmds), ConfCmds = rebar_config:get_local(Config, recursive_cmds, []), RecursiveCmds = AppCmds ++ ConfCmds, lists:member(Command, RecursiveCmds). -skip_or_process_dir({[], undefined}=ModuleSet, Config, CurrentCodePath, - Dir, Command, DirSet) -> - process_dir1(Dir, Command, DirSet, Config, CurrentCodePath, ModuleSet); -skip_or_process_dir({_, ModuleSetFile}=ModuleSet, Config, CurrentCodePath, - Dir, Command, DirSet) -> - case lists:suffix(".app.src", ModuleSetFile) - orelse lists:suffix(".app", ModuleSetFile) of +%% If the directory we're about to process contains +%% reltool.config[.script] and the command to be applied is +%% 'generate', then it's safe to process. We do this to retain the +%% behavior of specifying {sub_dirs, ["rel"]} and have "rebar generate" +%% pick up rel/reltool.config[.script]. Without this workaround you'd +%% have to run "rebar -r generate" (which you don't want to do if you +%% have deps or other sub_dirs) or "cd rel && rebar generate". +is_generate_in_rel_dir(generate, Dir) -> + case rebar_rel_utils:is_rel_dir(Dir) of + {true, _} -> + true; + false -> + false + end; +is_generate_in_rel_dir(_, _) -> + false. + +skip_or_process_dir(Dir, Command, Config, DirSet, CurrentCodePath, + {[], undefined}=ModuleSet, WouldCd) -> + process_dir1(Dir, Command, Config, DirSet, CurrentCodePath, ModuleSet, + WouldCd); +skip_or_process_dir(Dir, Command, Config, DirSet, CurrentCodePath, + {_, File}=ModuleSet, WouldCd) -> + case lists:suffix(".app.src", File) + orelse lists:suffix(".app", File) of true -> %% .app or .app.src file, check if is_skipped_app - skip_or_process_dir1(ModuleSetFile, ModuleSet, - Config, CurrentCodePath, Dir, - Command, DirSet); + skip_or_process_dir1(Dir, Command, Config, DirSet, CurrentCodePath, + ModuleSet, WouldCd, File); false -> %% not an app dir, no need to consider apps=/skip_apps= - process_dir1(Dir, Command, DirSet, Config, - CurrentCodePath, ModuleSet) + process_dir1(Dir, Command, Config, DirSet, CurrentCodePath, + ModuleSet, WouldCd) end. -skip_or_process_dir1(AppFile, ModuleSet, Config, CurrentCodePath, - Dir, Command, DirSet) -> +skip_or_process_dir1(Dir, Command, Config, DirSet, CurrentCodePath, ModuleSet, + WouldCd, AppFile) -> case rebar_app_utils:is_skipped_app(Config, AppFile) of {Config1, {true, _SkippedApp}} when Command == 'update-deps' -> %% update-deps does its own app skipping. Unfortunately there's no %% way to signal this to rebar_core, so we have to explicitly do it %% here... Otherwise if you use app=, it'll skip the toplevel %% directory and nothing will be updated. - process_dir1(Dir, Command, DirSet, Config1, - CurrentCodePath, ModuleSet); + process_dir1(Dir, Command, Config1, DirSet, CurrentCodePath, + ModuleSet, WouldCd); {Config1, {true, SkippedApp}} -> ?DEBUG("Skipping app: ~p~n", [SkippedApp]), - Config2 = increment_operations(Config1), - {Config2, DirSet}; + {increment_operations(Config1), DirSet}; {Config1, false} -> - process_dir1(Dir, Command, DirSet, Config1, - CurrentCodePath, ModuleSet) + process_dir1(Dir, Command, Config1, DirSet, CurrentCodePath, + ModuleSet, WouldCd) end. -process_dir1(Dir, Command, DirSet, Config, CurrentCodePath, - {DirModules, ModuleSetFile}) -> +process_dir1(Dir, Command, Config, DirSet, CurrentCodePath, + {DirModules, File}, WouldCd) -> Config0 = rebar_config:set_xconf(Config, current_command, Command), + %% Get the list of modules for "any dir". This is a catch-all list %% of modules that are processed in addition to modules associated %% with this directory type. These any_dir modules are processed @@ -210,8 +231,7 @@ process_dir1(Dir, Command, DirSet, Config, CurrentCodePath, %% Invoke 'preprocess' on the modules -- this yields a list of other %% directories that should be processed _before_ the current one. - {Config1, Predirs} = acc_modules(Modules, preprocess, Config0, - ModuleSetFile), + {Config1, Predirs} = acc_modules(Modules, preprocess, Config0, File), %% Remember associated pre-dirs (used for plugin lookup) PredirsAssoc = remember_cwd_predirs(Dir, Predirs), @@ -219,55 +239,33 @@ process_dir1(Dir, Command, DirSet, Config, CurrentCodePath, %% Get the list of plug-in modules from rebar.config. These %% modules may participate in preprocess and postprocess. {ok, PluginModules} = plugin_modules(Config1, PredirsAssoc), + AllModules = Modules ++ PluginModules, - {Config2, PluginPredirs} = acc_modules(PluginModules, preprocess, - Config1, ModuleSetFile), + {Config2, PluginPredirs} = acc_modules(PluginModules, preprocess, Config1, + File), AllPredirs = Predirs ++ PluginPredirs, ?DEBUG("Predirs: ~p\n", [AllPredirs]), - {Config3, DirSet2} = process_each(AllPredirs, Command, Config2, - ModuleSetFile, DirSet), + {Config3, DirSet2} = process_each(AllPredirs, Command, Config2, DirSet, + File), %% Make sure the CWD is reset properly; processing the dirs may have %% caused it to change ok = file:set_cwd(Dir), - %% Check that this directory is not on the skip list - Config7 = case rebar_config:is_skip_dir(Config3, Dir) of - true -> - %% Do not execute the command on the directory, as some - %% module has requested a skip on it. - ?INFO("Skipping ~s in ~s\n", [Command, Dir]), - Config3; - - false -> - %% Check for and get command specific environments - {Config4, Env} = setup_envs(Config3, Modules), - - %% Execute any before_command plugins on this directory - Config5 = execute_pre(Command, PluginModules, - Config4, ModuleSetFile, Env), - - %% Execute the current command on this directory - Config6 = execute(Command, Modules ++ PluginModules, - Config5, ModuleSetFile, Env), - - %% Execute any after_command plugins on this directory - execute_post(Command, PluginModules, - Config6, ModuleSetFile, Env) - end, + %% Maybe apply command to Dir + Config4 = maybe_execute(Dir, Command, Config3, Modules, PluginModules, + AllModules, File, WouldCd), %% Mark the current directory as processed DirSet3 = sets:add_element(Dir, DirSet2), %% Invoke 'postprocess' on the modules. This yields a list of other %% directories that should be processed _after_ the current one. - {Config8, Postdirs} = acc_modules(Modules ++ PluginModules, postprocess, - Config7, ModuleSetFile), + {Config5, Postdirs} = acc_modules(AllModules, postprocess, Config4, File), ?DEBUG("Postdirs: ~p\n", [Postdirs]), - Res = process_each(Postdirs, Command, Config8, - ModuleSetFile, DirSet3), + Res = process_each(Postdirs, Command, Config5, DirSet3, File), %% Make sure the CWD is reset properly; processing the dirs may have %% caused it to change @@ -280,6 +278,33 @@ process_dir1(Dir, Command, DirSet, Config, CurrentCodePath, %% Return the updated {config, dirset} as result Res. +maybe_execute(Dir, Command, Config, Modules, PluginModules, AllModules, File, + would_cd) -> + %% Check that this directory is not on the skip list + case rebar_config:is_skip_dir(Config, Dir) of + true -> + %% Do not execute the command on the directory, as some + %% module has requested a skip on it. + ?INFO("Skipping ~s in ~s\n", [Command, Dir]), + Config; + + false -> + %% Check for and get command specific environments + {Config1, Env} = setup_envs(Config, Modules), + + %% Execute any before_command plugins on this directory + Config2 = execute_pre(Command, PluginModules, Config1, File, Env), + + %% Execute the current command on this directory + Config3 = execute(Command, AllModules, Config2, File, Env), + + %% Execute any after_command plugins on this directory + execute_post(Command, PluginModules, Config3, File, Env) + end; +maybe_execute(_Dir, _Command, Config, _Modules, _PluginModules, _AllModules, + _File, would_not_cd) -> + Config. + remember_cwd_predirs(Cwd, Predirs) -> Store = fun(Dir, Dict) -> case dict:find(Dir, Dict) of @@ -310,21 +335,21 @@ maybe_load_local_config(Dir, ParentConfig) -> %% Given a list of directories and a set of previously processed directories, %% process each one we haven't seen yet %% -process_each([], _Command, Config, _ModuleSetFile, DirSet) -> +process_each([], _Command, Config, DirSet, _File) -> %% reset cached (setup_env) envs Config1 = rebar_config:reset_envs(Config), {Config1, DirSet}; -process_each([Dir | Rest], Command, Config, ModuleSetFile, DirSet) -> +process_each([Dir | Rest], Command, Config, DirSet, File) -> case sets:is_element(Dir, DirSet) of true -> ?DEBUG("Skipping ~s; already processed!\n", [Dir]), - process_each(Rest, Command, Config, ModuleSetFile, DirSet); + process_each(Rest, Command, Config, DirSet, File); false -> - {Config1, DirSet2} = process_dir(Dir, Config, Command, DirSet), + {Config1, DirSet2} = process_dir(Dir, Command, Config, DirSet), Config2 = rebar_config:clean_config(Config, Config1), %% reset cached (setup_env) envs Config3 = rebar_config:reset_envs(Config2), - process_each(Rest, Command, Config3, ModuleSetFile, DirSet2) + process_each(Rest, Command, Config3, DirSet2, File) end. %% @@ -358,20 +383,21 @@ execute_post(Command, Modules, Config, ModuleFile, Env) -> execute_plugin_hook(Hook, Command, Modules, Config, ModuleFile, Env) -> HookFunction = list_to_atom(Hook ++ atom_to_list(Command)), - execute(HookFunction, Modules, Config, ModuleFile, Env). + execute(HookFunction, hook, Modules, Config, ModuleFile, Env). %% %% Execute a command across all applicable modules %% execute(Command, Modules, Config, ModuleFile, Env) -> + execute(Command, not_a_hook, Modules, Config, ModuleFile, Env). + +execute(Command, Type, Modules, Config, ModuleFile, Env) -> case select_modules(Modules, Command, []) of [] -> - Cmd = atom_to_list(Command), - case lists:prefix("pre_", Cmd) - orelse lists:prefix("post_", Cmd) of - true -> + case Type of + hook -> ok; - false -> + not_a_hook -> ?WARN("'~p' command does not apply to directory ~s\n", [Command, rebar_utils:get_cwd()]) end, diff --git a/src/rebar_erlc_compiler.erl b/src/rebar_erlc_compiler.erl index 75d47fb..473a8aa 100644 --- a/src/rebar_erlc_compiler.erl +++ b/src/rebar_erlc_compiler.erl @@ -538,7 +538,7 @@ internal_erl_compile(Config, Source, OutDir, ErlOpts, G) -> %% Determine the target name and includes list by inspecting the source file Module = filename:basename(Source, ".erl"), Parents = get_parents(G, Source), - log_files(?FMT("~s depends on", [Source]), Parents), + log_files(?FMT("Dependencies of ~s", [Source]), Parents), %% Construct the target filename Target = filename:join([OutDir | string:tokens(Module, ".")]) ++ ".beam", diff --git a/src/rebar_file_utils.erl b/src/rebar_file_utils.erl index fcd9c5e..9ddbf27 100644 --- a/src/rebar_file_utils.erl +++ b/src/rebar_file_utils.erl @@ -46,7 +46,7 @@ rm_rf(Target) -> {unix, _} -> EscTarget = escape_spaces(Target), {ok, []} = rebar_utils:sh(?FMT("rm -rf ~s", [EscTarget]), - [{use_stdout, false}, return_on_error]), + [{use_stdout, false}, abort_on_error]), ok; {win32, _} -> Filelist = filelib:wildcard(Target), @@ -67,7 +67,7 @@ cp_r(Sources, Dest) -> SourceStr = string:join(EscSources, " "), {ok, []} = rebar_utils:sh(?FMT("cp -R ~s \"~s\"", [SourceStr, Dest]), - [{use_stdout, false}, return_on_error]), + [{use_stdout, false}, abort_on_error]), ok; {win32, _} -> lists:foreach(fun(Src) -> ok = cp_r_win32(Src,Dest) end, Sources), @@ -81,7 +81,7 @@ mv(Source, Dest) -> EscSource = escape_spaces(Source), EscDest = escape_spaces(Dest), {ok, []} = rebar_utils:sh(?FMT("mv ~s ~s", [EscSource, EscDest]), - [{use_stdout, false}, return_on_error]), + [{use_stdout, false}, abort_on_error]), ok; {win32, _} -> {ok, R} = rebar_utils:sh( diff --git a/src/rebar_qc.erl b/src/rebar_qc.erl index 99d37a2..1976722 100644 --- a/src/rebar_qc.erl +++ b/src/rebar_qc.erl @@ -73,7 +73,10 @@ info(help, qc) -> [ {qc_compile_opts, []}, {qc_first_files, []} - ]). + ]); +info(help, clean) -> + Description = ?FMT("Delete QuickCheck test dir (~s)", [?QC_DIR]), + ?CONSOLE("~s.~n", [Description]). -define(TRIQ_MOD, triq). -define(EQC_MOD, eqc). diff --git a/src/rebar_require_vsn.erl b/src/rebar_require_vsn.erl index 385f55c..af805c8 100644 --- a/src/rebar_require_vsn.erl +++ b/src/rebar_require_vsn.erl @@ -34,7 +34,8 @@ eunit/2]). %% for internal use only --export([info/2]). +-export([info/2, + version_tuple/2]). %% =================================================================== %% Public API @@ -110,7 +111,7 @@ check_versions(Config) -> end. version_tuple(OtpRelease, Type) -> - case re:run(OtpRelease, "R(\\d+)B?-?(\\d+)?", [{capture, all, list}]) of + case re:run(OtpRelease, "R?(\\d+)B?-?(\\d+)?", [{capture, all, list}]) of {match, [_Full, Maj, Min]} -> {list_to_integer(Maj), list_to_integer(Min)}; {match, [_Full, Maj]} -> diff --git a/src/rebar_utils.erl b/src/rebar_utils.erl index 2d227b6..517ac33 100644 --- a/src/rebar_utils.erl +++ b/src/rebar_utils.erl @@ -316,7 +316,8 @@ processing_base_dir(Config) -> processing_base_dir(Config, Cwd). processing_base_dir(Config, Dir) -> - Dir =:= base_dir(Config). + AbsDir = filename:absname(Dir), + AbsDir =:= base_dir(Config). %% ==================================================================== %% Internal functions @@ -398,8 +399,9 @@ log_msg_and_abort(Message) -> -spec log_and_abort(string(), {integer(), string()}) -> no_return(). log_and_abort(Command, {Rc, Output}) -> - ?ABORT("~s failed with error: ~w and output:~n~s~n", - [Command, Rc, Output]). + ?ABORT("sh(~s)~n" + "failed with return code ~w and the following output:~n" + "~s~n", [Command, Rc, Output]). sh_loop(Port, Fun, Acc) -> receive diff --git a/test/rebar_file_utils_tests.erl b/test/rebar_file_utils_tests.erl index 26a6f9f..a191765 100644 --- a/test/rebar_file_utils_tests.erl +++ b/test/rebar_file_utils_tests.erl @@ -191,7 +191,7 @@ cp_r_overwrite_file_fail_test_() -> filename:join([?TMP_DIR,"dest","file1"]),0) end, fun teardown/1, - [?_assertError({badmatch,_}, + [?_assertThrow(rebar_abort, rebar_file_utils:cp_r( [filename:join([?TMP_DIR,"source","file1"])], filename:join([?TMP_DIR,"dest"])))]}. @@ -210,7 +210,7 @@ cp_r_overwrite_dir_fail_test_() -> filename:join([?TMP_DIR,"dest","source","file1"]),0) end, fun teardown/1, - [?_assertError({badmatch,_}, + [?_assertThrow(rebar_abort, rebar_file_utils:cp_r( [filename:join([?TMP_DIR,"source"])], filename:join([?TMP_DIR,"dest"])))]}. diff --git a/test/rebar_require_vsn_tests.erl b/test/rebar_require_vsn_tests.erl new file mode 100644 index 0000000..2d3a1ec --- /dev/null +++ b/test/rebar_require_vsn_tests.erl @@ -0,0 +1,23 @@ +-module(rebar_require_vsn_tests). + +-compile(export_all). + +-include_lib("eunit/include/eunit.hrl"). + +version_tuple_test_() -> + [%% typical cases + ?_assert(rebar_require_vsn:version_tuple("R15B", "eunit") =:= {15, 0}), + ?_assert(rebar_require_vsn:version_tuple("R15B01", "eunit") =:= {15, 1}), + ?_assert(rebar_require_vsn:version_tuple("R15B02", "eunit") =:= {15, 2}), + ?_assert(rebar_require_vsn:version_tuple("R15B03-1", "eunit") =:= {15, 3}), + ?_assert(rebar_require_vsn:version_tuple("R15B03", "eunit") =:= {15, 3}), + ?_assert(rebar_require_vsn:version_tuple("R16B", "eunit") =:= {16, 0}), + ?_assert(rebar_require_vsn:version_tuple("R16B01", "eunit") =:= {16, 1}), + ?_assert(rebar_require_vsn:version_tuple("R16B02", "eunit") =:= {16, 2}), + ?_assert(rebar_require_vsn:version_tuple("R16B03", "eunit") =:= {16, 3}), + ?_assert(rebar_require_vsn:version_tuple("R16B03-1", "eunit") =:= {16, 3}), + ?_assert(rebar_require_vsn:version_tuple("17", "eunit") =:= {17, 0}), + %% error cases + ?_assertException(throw, rebar_abort, rebar_require_vsn:version_tuple("", "eunit")), + ?_assertException(throw, rebar_abort, rebar_require_vsn:version_tuple("abc", "eunit")) + ]. |