summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore17
-rw-r--r--RELEASE-NOTES.md89
-rw-r--r--THANKS2
-rw-r--r--ebin/rebar.app16
-rw-r--r--inttest/code_path_no_recurse/code_path_no_recurse_rt.erl19
-rw-r--r--inttest/code_path_no_recurse/deps/bazdep/src/bazdep.app.src12
-rw-r--r--inttest/code_path_no_recurse/deps/bazdep/src/bazdep.erl6
-rw-r--r--inttest/code_path_no_recurse/deps/bazdep/test/bazdep_tests.erl5
-rw-r--r--inttest/code_path_no_recurse/deps/foodep/rebar.config1
-rw-r--r--inttest/code_path_no_recurse/deps/foodep/src/foodep.app.src12
-rw-r--r--inttest/code_path_no_recurse/deps/foodep/src/foodep.erl6
-rw-r--r--inttest/code_path_no_recurse/deps/foodep/test/foodep_tests.erl5
-rw-r--r--inttest/code_path_no_recurse/deps/unuseddep/src/unuseddep.app.src12
-rw-r--r--inttest/code_path_no_recurse/deps/unuseddep/src/unuseddep.erl6
-rw-r--r--inttest/code_path_no_recurse/rebar.config1
-rw-r--r--inttest/code_path_no_recurse/src/codepath.app.src12
-rw-r--r--inttest/code_path_no_recurse/src/codepath.erl6
-rw-r--r--inttest/code_path_no_recurse/test/codepath_tests.erl12
-rw-r--r--inttest/erlc/asn1/SIMPLE-ASN.asn17
-rw-r--r--inttest/erlc/erlc_rt.erl98
-rw-r--r--inttest/erlc/extra-include/foo_extra.hrl1
-rw-r--r--inttest/erlc/extra-src/foo_sup.erl13
-rw-r--r--inttest/erlc/include/foo_core.hrl1
-rw-r--r--inttest/erlc/mibs/SIMPLE-MIB.mib26
-rw-r--r--inttest/erlc/rebar-no_debug_info.config11
-rw-r--r--inttest/erlc/rebar.config10
-rw-r--r--inttest/erlc/src/behaviour/foo_worker.erl14
-rw-r--r--inttest/erlc/src/first_xrl.xrl13
-rw-r--r--inttest/erlc/src/first_yrl.yrl9
-rw-r--r--inttest/erlc/src/foo.erl35
-rw-r--r--inttest/erlc/src/foo_app.erl10
-rw-r--r--inttest/erlc/src/foo_test_worker.erl34
-rw-r--r--inttest/eunit/eunit_rt.erl48
-rw-r--r--inttest/eunit/eunit_src/bar.erl6
-rw-r--r--inttest/eunit/rebar-eunit_compile_opts.config1
-rw-r--r--inttest/eunit/src/foo.erl10
-rw-r--r--inttest/tdeps1/tdeps1_rt.erl3
-rw-r--r--inttest/tdeps2/tdeps2_rt.erl3
-rw-r--r--inttest/tdeps_update/tdeps_update_rt.erl3
-rw-r--r--priv/shell-completion/bash/rebar5
-rw-r--r--priv/shell-completion/zsh/_rebar3
-rw-r--r--rebar.config.sample3
-rw-r--r--src/rebar.erl38
-rw-r--r--src/rebar_config.erl4
-rw-r--r--src/rebar_core.erl198
-rw-r--r--src/rebar_erlc_compiler.erl21
-rw-r--r--src/rebar_file_utils.erl6
-rw-r--r--src/rebar_metacmds.erl56
-rw-r--r--src/rebar_qc.erl5
-rw-r--r--src/rebar_require_vsn.erl5
-rw-r--r--src/rebar_templater.erl3
-rw-r--r--src/rebar_utils.erl8
-rw-r--r--test/rebar_file_utils_tests.erl4
-rw-r--r--test/rebar_require_vsn_tests.erl23
54 files changed, 825 insertions, 152 deletions
diff --git a/.gitignore b/.gitignore
index 165948e..15668a7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -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..093e771 100644
--- a/RELEASE-NOTES.md
+++ b/RELEASE-NOTES.md
@@ -1,33 +1,64 @@
+# Rebar 2.3.1
+
+## PR's Merged
+
+* rebar/242: [Extra commits for #129](https://github.com/rebar/rebar/pull/242)
+* rebar/244: [Document skip_apps=, apps=, and require_*_vsn](https://github.com/rebar/rebar/pull/244)
+* rebar/251: [Make sure that eunit/qc_compile_opts works](https://github.com/rebar/rebar/pull/251)
+* rebar/255: [rebar.app: remove superfluous quoting](https://github.com/rebar/rebar/pull/255)
+* rebar/274: [Use lowercase for Windows drive name to resolve issue #250](https://github.com/rebar/rebar/pull/274)
+
+# Rebar 2.3.0
+
+## PR's Merged
+
+* rebar/98: [Repetition of environment variable definitions in child processes (ports)](https://github.com/rebar/rebar/pull/98)
+* rebar/115: [Incorrect REMSH args when sname is used.](https://github.com/rebar/rebar/pull/115)
+* rebar/129: [Speed up the compilation process v5](https://github.com/rebar/rebar/pull/129)
+* rebar/139: [Allow specification of module dependencies for appups](https://github.com/rebar/rebar/pull/139)
+* rebar/175: [CWD plugins regression](https://github.com/rebar/rebar/pull/175)
+* rebar/188: [Xref extra path](https://github.com/rebar/rebar/pull/188)
+* rebar/208: [Fix typo in rebar_erlydtl_compiler](https://github.com/rebar/rebar/pull/208)
+* rebar/219: [Added R16B01 and R16B02 to travis config.](https://github.com/rebar/rebar/pull/219)
+* rebar/221: [Adapt erlydtl compiler plugin to latest version of erlydtl](https://github.com/rebar/rebar/pull/221)
+* rebar/223: [Add random_suite_order option to eunit command](https://github.com/rebar/rebar/pull/223)
+* rebar/224: [allow suites or tests as options for eunit and ct](https://github.com/rebar/rebar/pull/224)
+* rebar/230: [eunit: fix dialyzer warnings introduced in 03da5e0b](https://github.com/rebar/rebar/pull/230)
+* rebar/232: [Document support for abbreviated commands](https://github.com/rebar/rebar/pull/232)
+* rebar/233: [docs: fix #228](https://github.com/rebar/rebar/pull/233)
+* rebar/234: [Fix #220 (Reported-by: Joseph Norton)](https://github.com/rebar/rebar/pull/234)
+* rebar/237: [Add partial support for Erlang/OTP 17](https://github.com/rebar/rebar/pull/237)
+* rebar/252: [file_utils: properly report errors (fix #95)](https://github.com/rebar/rebar/pull/252)
+* rebar/254: [Fix 'rebar generate' regression (#253)](https://github.com/rebar/rebar/pull/254)
+* rebar/265: [Fix 'rebar help clean' function_clause error](https://github.com/rebar/rebar/pull/265)
+* rebar/268: [Fix #267 (code path regression)](https://github.com/rebar/rebar/pull/268)
+* rebar/269: [Update THANKS](https://github.com/rebar/rebar/pull/269)
+
# Rebar 2.2.0
## PR's Merged
-* rebar/137: [Filter documented behaviour callbacks](https://github.com/basho/rebar/pull/137)
-* rebar/142: [Fix rebar_file_utils module on Windows with MSYS](https://github.com/basho/rebar/pull/142)
-* rebar/152: [Allow users to configure skip_deps for specific commands](https://github.com/basho/rebar/pull/152)
-* rebar/154: [Stop applications nicely before killing extra processes](https://github.com/basho/rebar/pull/154)
-* rebar/155: [Fix rebar_utils:expand_env_variable/3](https://github.com/basho/rebar/pull/155)
-* rebar/157: [add native Windows compiler support](https://github.com/basho/rebar/pull/157)
-* rebar/172: [Allow reltool target_dir to be constructed on the fly](https://github.com/basho/rebar/pull/172)
-* rebar/173: [rebar should expand VCS version in the top directory, if possible](https://github.com/basho/rebar/pull/173)
-* rebar/174: [Fixed handle_call response in simplesrv.erl](https://github.com/basho/rebar/pull/174)
-* rebar/177: [Cache vsn information during the run to avoid extra unnecessary shell calls](https://github.com/basho/rebar/pull/177)
-* rebar/179: [Add ebin to the path before compiling erlydtl templates](https://github.com/basho/rebar/pull/179)
-* rebar/183: [Fix compiling DTL templates with latest erlydtl](https://github.com/basho/rebar/pull/183)
-* rebar/184: [Fix for destruction of config app vars on reset](https://github.com/basho/rebar/pull/184)
-* rebar/185: [simple enhance and simple bugfix](https://github.com/basho/rebar/pull/185)
-* rebar/187: [fix for cp_r_win32 where copying a directory to a non-existant directory would crash](https://github.com/basho/rebar/pull/187)
-* rebar/189: [Fix typos in generated cmd script in bootstrap](https://github.com/basho/rebar/pull/189)
-* rebar/190: [Windows xcopy dir to non-existant dir (re-request)](https://github.com/basho/rebar/pull/190)
-* rebar/191: [Fix typos in rebar_templater](https://github.com/basho/rebar/pull/191)
-* rebar/196: [Escape '|' in the Windows runner usage string](https://github.com/basho/rebar/pull/196)
-* rebar/198: [New feature to rebar_xref to allow execution of custom queries.](https://github.com/basho/rebar/pull/198)
-* rebar/199: [Added new feature to rebar xref to allow execution of custom queries.](https://github.com/basho/rebar/pull/199)
-* rebar/200: [Enable runner to pass more than one argument to start](https://github.com/basho/rebar/pull/200)
-* rebar/201: [include simplemodule.app.src in simplemod template](https://github.com/basho/rebar/pull/201)
-* rebar/205: [Ports in languages other than C](https://github.com/basho/rebar/issues/205)
-* rebar/210: [use file:script if a .config.script file present](https://github.com/basho/rebar/pull/210)
-* rebar/212: [ Modified simplenode.runner to start from alternative directory](https://github.com/basho/rebar/pull/212)
-* rebar/214: [Foreground running doesn't allow console attaching](https://github.com/basho/rebar/issues/214)
-* rebar/215: [Add support for http proxy_friendly_github_urls](https://github.com/basho/rebar/pull/215)
-* rebar/388: [Less than useful rebar error message when error in .hrl files](https://github.com/basho/rebar/issues/388)
+* rebar/152: [Fix erl_opts use](https://github.com/rebar/rebar/pull/152)
+* rebar/154: [Fix update-deps with certain forms of the {tag, ...} type](https://github.com/rebar/rebar/pull/154)
+* rebar/155: [Fixes for #137 and #142](https://github.com/rebar/rebar/pull/155)
+* rebar/157: [Don't over-aggressively clean the code path in the presence of lib_dir directives](https://github.com/rebar/rebar/pull/157)
+* rebar/172: [Add missing dep examples and fix existing ones](https://github.com/rebar/rebar/pull/172)
+* rebar/173: [Fix false reporting of (plain) vsn strings](https://github.com/rebar/rebar/pull/173)
+* rebar/174: [rebar_core: fix Dialyzer warning introduced in aa46d85 (#157)](https://github.com/rebar/rebar/pull/174)
+* rebar/177: [Delete unused inttest/retest binary](https://github.com/rebar/rebar/pull/177)
+* rebar/179: [Make list of commands (for unabbreviation) easier to maintain](https://github.com/rebar/rebar/pull/179)
+* rebar/183: [generate-upgrade can now take target_dir argument](https://github.com/rebar/rebar/pull/183)
+* rebar/184: [Fix log levels](https://github.com/rebar/rebar/pull/184)
+* rebar/185: [Switch retest dep to upstream (dizzyd/retest.git)](https://github.com/rebar/rebar/pull/185)
+* rebar/189: [inttest/rgen1: increase retest timeout (30s -> 60s)](https://github.com/rebar/rebar/pull/189)
+* rebar/190: [inttest/rgen_1: double the timeout a second time](https://github.com/rebar/rebar/pull/190)
+* rebar/191: [Fix #187 (rename getopt and mustache)](https://github.com/rebar/rebar/pull/191)
+* rebar/196: [Print a more appropriate message on 'rebar info'](https://github.com/rebar/rebar/pull/196)
+* rebar/198: [Clean up rebar.config.script](https://github.com/rebar/rebar/pull/198)
+* rebar/199: [rebar_dia_compiler: fix Dialyzer warnings](https://github.com/rebar/rebar/pull/199)
+* rebar/200: [bootstrap: avoid trying to run 'debug' command](https://github.com/rebar/rebar/pull/200)
+* rebar/201: [Added a library template.](https://github.com/rebar/rebar/pull/201)
+* rebar/210: [Fix #205 (erlydtl:compile/3 returns warnings)](https://github.com/rebar/rebar/pull/210)
+* rebar/212: [Fix basho/rebar#388](https://github.com/rebar/rebar/pull/212)
+* rebar/214: [Document compile_only=true](https://github.com/rebar/rebar/pull/214)
+* rebar/215: [Remove experimental flags](https://github.com/rebar/rebar/pull/215)
diff --git a/THANKS b/THANKS
index 0b503d3..66d7b25 100644
--- a/THANKS
+++ b/THANKS
@@ -121,3 +121,5 @@ Sylvain Benner
Oliver Ferrigni
Dave Thomas
Evgeniy Khramtsov
+YeJun Su
+Yuki Ito
diff --git a/ebin/rebar.app b/ebin/rebar.app
index 8e239e9..29ad8cf 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.1"},
{modules, [ rebar,
rebar_abnfc_compiler,
rebar_app_utils,
@@ -38,6 +38,7 @@
rebar_upgrade,
rebar_utils,
rebar_xref,
+ rebar_metacmds,
rebar_getopt,
rebar_mustache ]},
{registered, []},
@@ -80,7 +81,8 @@
rebar_escripter,
rebar_edoc,
rebar_shell,
- rebar_xref
+ rebar_xref,
+ rebar_metacmds
]},
{rel_dir, [
@@ -88,6 +90,14 @@
rebar_reltool,
rebar_upgrade
]}
- ]}
+ ]},
+ {recursive_cmds, [
+ 'check-deps',
+ compile,
+ 'delete-deps',
+ 'get-deps',
+ 'list-deps',
+ 'update-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/inttest/eunit/eunit_rt.erl b/inttest/eunit/eunit_rt.erl
new file mode 100644
index 0000000..47f3331
--- /dev/null
+++ b/inttest/eunit/eunit_rt.erl
@@ -0,0 +1,48 @@
+-module(eunit_rt).
+-export([files/0, run/1]).
+
+-include_lib("eunit/include/eunit.hrl").
+
+files() ->
+ [{create, "ebin/foo.app", app(foo)},
+ {copy, "../../rebar", "rebar"},
+ {copy, "src", "src"},
+ {copy, "eunit_src", "eunit_src"},
+ {copy,
+ "rebar-eunit_compile_opts.config",
+ "rebar-eunit_compile_opts.config"}].
+
+run(_Dir) ->
+ ifdef_test(),
+ eunit_compile_opts_test(),
+ ok.
+
+ifdef_test() ->
+ {ok, Output} = retest:sh("./rebar -v eunit"),
+ ?assert(check_output(Output, "foo_test")),
+ ?assertMatch({ok, _}, retest:sh("./rebar clean")).
+
+eunit_compile_opts_test() ->
+ {ok, Output} =
+ retest:sh("./rebar -v -C rebar-eunit_compile_opts.config eunit"),
+ ?assert(check_output(Output, "bar_test")),
+ ?assertMatch(
+ {ok, _},
+ retest:sh("./rebar -C rebar-eunit_compile_opts.config clean")).
+
+check_output(Output, Target) ->
+ lists:any(fun(Line) ->
+ string:str(Line, Target) > 0
+ end, Output).
+
+%%
+%% Generate the contents of a simple .app file
+%%
+app(Name) ->
+ App = {application, Name,
+ [{description, atom_to_list(Name)},
+ {vsn, "1"},
+ {modules, []},
+ {registered, []},
+ {applications, [kernel, stdlib]}]},
+ io_lib:format("~p.\n", [App]).
diff --git a/inttest/eunit/eunit_src/bar.erl b/inttest/eunit/eunit_src/bar.erl
new file mode 100644
index 0000000..6a80dac
--- /dev/null
+++ b/inttest/eunit/eunit_src/bar.erl
@@ -0,0 +1,6 @@
+-module(bar).
+
+-include_lib("eunit/include/eunit.hrl").
+
+bar_test() ->
+ ?assert(true).
diff --git a/inttest/eunit/rebar-eunit_compile_opts.config b/inttest/eunit/rebar-eunit_compile_opts.config
new file mode 100644
index 0000000..13b2d94
--- /dev/null
+++ b/inttest/eunit/rebar-eunit_compile_opts.config
@@ -0,0 +1 @@
+{eunit_compile_opts, [{src_dirs, ["eunit_src"]}]}.
diff --git a/inttest/eunit/src/foo.erl b/inttest/eunit/src/foo.erl
new file mode 100644
index 0000000..a4c91ba
--- /dev/null
+++ b/inttest/eunit/src/foo.erl
@@ -0,0 +1,10 @@
+-module(foo).
+
+-ifdef(TEST).
+
+-include_lib("eunit/include/eunit.hrl").
+
+foo_test() ->
+ ?assert(true).
+
+-endif.
diff --git a/inttest/tdeps1/tdeps1_rt.erl b/inttest/tdeps1/tdeps1_rt.erl
index 3de1a2b..a72cc83 100644
--- a/inttest/tdeps1/tdeps1_rt.erl
+++ b/inttest/tdeps1/tdeps1_rt.erl
@@ -41,7 +41,8 @@ run(_Dir) ->
apply_cmds(GitCmds, [{dir, "repo/b"}]),
apply_cmds(GitCmds, [{dir, "repo/c"}]),
- {ok, _} = retest_sh:run("./rebar get-deps compile", []),
+ {ok, _} = retest_sh:run("./rebar get-deps", []),
+ {ok, _} = retest_sh:run("./rebar compile", []),
true = filelib:is_regular("ebin/a.beam"),
ok.
diff --git a/inttest/tdeps2/tdeps2_rt.erl b/inttest/tdeps2/tdeps2_rt.erl
index 987567e..22f0abe 100644
--- a/inttest/tdeps2/tdeps2_rt.erl
+++ b/inttest/tdeps2/tdeps2_rt.erl
@@ -49,7 +49,8 @@ run(_Dir) ->
ok = apply_cmds(GitCmds, [{dir, "repo/b"}]),
ok = apply_cmds(GitCmds, [{dir, "repo/c"}]),
- {ok, _} = retest_sh:run("./rebar -v get-deps compile", []),
+ {ok, _} = retest_sh:run("./rebar -v get-deps", []),
+ {ok, _} = retest_sh:run("./rebar -v compile", []),
ok.
%%
diff --git a/inttest/tdeps_update/tdeps_update_rt.erl b/inttest/tdeps_update/tdeps_update_rt.erl
index 81bb7ef..e182ae2 100644
--- a/inttest/tdeps_update/tdeps_update_rt.erl
+++ b/inttest/tdeps_update/tdeps_update_rt.erl
@@ -122,7 +122,8 @@ run(_Dir) ->
ok = apply_cmds(GitCmds++ECmds, [{dir, "repo/e"}]),
ok = apply_cmds(GitCmds++FCmds, [{dir, "repo/f"}]),
- {ok, _} = retest_sh:run("./rebar -v get-deps compile", []),
+ {ok, _} = retest_sh:run("./rebar -v get-deps", []),
+ {ok, _} = retest_sh:run("./rebar -v compile", []),
os:cmd("cp a2.rebar.config apps/a1/rebar.config"),
{ok, _} = retest_sh:run("./rebar -v update-deps", []),
{ok, _} = retest_sh:run("./rebar -v compile", []),
diff --git a/priv/shell-completion/bash/rebar b/priv/shell-completion/bash/rebar
index 7dc3b5e..375566c 100644
--- a/priv/shell-completion/bash/rebar
+++ b/priv/shell-completion/bash/rebar
@@ -6,7 +6,7 @@ _rebar()
COMPREPLY=()
cur="${COMP_WORDS[COMP_CWORD]}"
prev="${COMP_WORDS[COMP_CWORD-1]}"
- sopts="-h -c -v -V -f -D -j -C -p -k"
+ sopts="-h -c -v -V -f -D -j -C -p -k -r"
lopts="--help \
--commands \
--verbose \
@@ -15,6 +15,7 @@ _rebar()
--config \
--profile \
--keep-going \
+ --recursive \
--version"
cmdsnvars="check-deps \
clean \
@@ -35,7 +36,9 @@ _rebar()
help \
list-deps \
list-templates \
+ prepare-deps \
qc \
+ refresh-deps \
update-deps \
version \
xref \
diff --git a/priv/shell-completion/zsh/_rebar b/priv/shell-completion/zsh/_rebar
index 384fead..0218f9e 100644
--- a/priv/shell-completion/zsh/_rebar
+++ b/priv/shell-completion/zsh/_rebar
@@ -17,6 +17,7 @@ _rebar_global_opts=(
'(--config -C)'{--config,-C}'[Rebar config file to use]:files:_files'
'(--profile -p)'{--profile,-p}'[Profile this run of rebar]'
'(--keep-going -k)'{--keep-going,-k}'[Keep running after a command fails]'
+ '(--recursive -r)'{--recursive,-r}'[Apply commands to subdirs and dependencies]'
)
_rebar () {
@@ -36,6 +37,8 @@ _rebar () {
'list-template[List avaiavle templates]' \
'doc[Generate Erlang program documentation]' \
'check-deps[Display to be fetched dependencies]' \
+ 'prepare-deps[Fetch and build dependencies]' \
+ 'refresh-deps[Update and build dependencies]' \
'get-deps[Fetch dependencies]' \
'update-deps[Update fetched dependencies]' \
'delete-deps[Delete fetched dependencies]' \
diff --git a/rebar.config.sample b/rebar.config.sample
index 30d28d0..515ed00 100644
--- a/rebar.config.sample
+++ b/rebar.config.sample
@@ -5,6 +5,9 @@
%% == Core ==
+%% Extend list of always recursive commands
+{recursive_cmds, []}.
+
%% Check required ERTS or OTP release version
{require_erts_vsn, ".*"}.
{require_otp_vsn, ".*"}.
diff --git a/src/rebar.erl b/src/rebar.erl
index 36a7b36..d5d6c77 100644
--- a/src/rebar.erl
+++ b/src/rebar.erl
@@ -206,8 +206,19 @@ help() ->
" ~p~n"
" ~p~n"
" ~p~n"
- " ~p~n",
+ " ~p~n"
+ " ~p~n"
+ " ~p~n"
+ " ~p~n"
+ " ~p~n"
+ "Core command line options:~n"
+ " apps=app1,app2 (specify apps to process)~n"
+ " skip_apps=app1,app2 (specify apps to skip)~n",
[
+ {recursive_cmds, []},
+ {require_erts_vsn, ".*"},
+ {require_otp_vsn, ".*"},
+ {require_min_otp_vsn, ".*"},
{lib_dirs, []},
{sub_dirs, ["dir1", "dir2"]},
{plugins, [plugin1, plugin2]},
@@ -254,19 +265,23 @@ save_options(Config, {Options, NonOptArgs}) ->
Config3 = rebar_config:set_xconf(Config2, keep_going,
proplists:get_bool(keep_going, Options)),
+ %% Setup flag to enable recursive application of commands
+ Config4 = rebar_config:set_xconf(Config3, recursive,
+ proplists:get_bool(recursive, Options)),
+
%% Set global variables based on getopt options
- Config4 = set_global_flag(Config3, Options, force),
- Config5 = case proplists:get_value(jobs, Options, ?DEFAULT_JOBS) of
+ Config5 = set_global_flag(Config4, Options, force),
+ Config6 = case proplists:get_value(jobs, Options, ?DEFAULT_JOBS) of
?DEFAULT_JOBS ->
- Config4;
+ Config5;
Jobs ->
- rebar_config:set_global(Config4, jobs, Jobs)
+ rebar_config:set_global(Config5, jobs, Jobs)
end,
%% Filter all the flags (i.e. strings of form key=value) from the
%% command line arguments. What's left will be the commands to run.
- {Config6, RawCmds} = filter_flags(Config5, NonOptArgs, []),
- {Config6, unabbreviate_command_names(RawCmds)}.
+ {Config7, RawCmds} = filter_flags(Config6, NonOptArgs, []),
+ {Config7, unabbreviate_command_names(RawCmds)}.
%%
%% set log level based on getopt option
@@ -358,6 +373,9 @@ list-templates List available templates
doc Generate Erlang program documentation
+prepare-deps Run 'rebar -r get-deps compile'
+refresh-deps Run 'rebar -r update-deps compile'
+
check-deps Display to be fetched dependencies
get-deps Fetch dependencies
update-deps Update fetched dependencies
@@ -420,7 +438,9 @@ option_spec_list() ->
{config, $C, "config", string, "Rebar config file to use"},
{profile, $p, "profile", undefined, "Profile this run of rebar"},
{keep_going, $k, "keep-going", undefined,
- "Keep running after a command fails"}
+ "Keep running after a command fails"},
+ {recursive, $r, "recursive", boolean,
+ "Apply commands to subdirs and dependencies"}
].
%%
@@ -469,7 +489,9 @@ command_names() ->
"help",
"list-deps",
"list-templates",
+ "prepare-deps",
"qc",
+ "refresh-deps",
"update-deps",
"overlay",
"shell",
diff --git a/src/rebar_config.erl b/src/rebar_config.erl
index 9b58d4f..10c6483 100644
--- a/src/rebar_config.erl
+++ b/src/rebar_config.erl
@@ -31,6 +31,7 @@
get_all/2,
set/3,
set_global/3, get_global/3,
+ is_recursive/1,
save_env/3, get_env/2, reset_envs/1,
set_skip_dir/2, is_skip_dir/2, reset_skip_dirs/1,
clean_config/2,
@@ -109,6 +110,9 @@ get_global(Config, Key, Default) ->
Value
end.
+is_recursive(Config) ->
+ get_xconf(Config, recursive, false).
+
consult_file(File) ->
case filename:extension(File) of
".script" ->
diff --git a/src/rebar_core.erl b/src/rebar_core.erl
index 4efc978..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,71 +117,110 @@ 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 ->
+ WouldCd = would_cd_into_dir(Dir, Command, ParentConfig),
ok = file:set_cwd(Dir),
Config = maybe_load_local_config(Dir, ParentConfig),
%% Save the current code path and then update it with
- %% lib_dirs. Children inherit parents code path, but we
- %% also want to ensure that we restore everything to pristine
+ %% lib_dirs. Children inherit parents code path, but we also
+ %% want to ensure that we restore everything to pristine
%% condition after processing this child
CurrentCodePath = update_code_path(Config),
- %% Get the list of processing modules and check each one against
- %% CWD to see if it's a fit -- if it is, use that set of modules
- %% to process this dir.
+ %% Get the list of processing modules and check each one
+ %% against CWD to see if it's a fit -- if it is, use that
+ %% 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.
-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
+would_cd_into_dir(Dir, Command, Config) ->
+ case would_cd_into_dir1(Dir, Command, Config) of
+ true ->
+ would_cd;
+ false ->
+ would_not_cd
+ end.
+
+would_cd_into_dir1(Dir, Command, Config) ->
+ rebar_utils:processing_base_dir(Config, Dir) orelse
+ rebar_config:is_recursive(Config) orelse
+ is_recursive_command(Command, Config) orelse
+ is_generate_in_rel_dir(Command, Dir).
+
+%% 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).
+
+%% 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
@@ -192,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),
@@ -201,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
@@ -262,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
@@ -292,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.
%%
@@ -340,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..b797137 100644
--- a/src/rebar_erlc_compiler.erl
+++ b/src/rebar_erlc_compiler.erl
@@ -134,12 +134,13 @@ test_compile(Config, Cmd, OutDir) ->
%% Obtain all the test modules for inclusion in the compile stage.
TestErls = rebar_utils:find_files("test", ".*\\.erl\$"),
+ ErlOpts = rebar_utils:erl_opts(Config),
+ {Config1, ErlOpts1} = test_compile_config_and_opts(Config, ErlOpts, Cmd),
+
%% Copy source files to eunit dir for cover in case they are not directly
%% in src but in a subdirectory of src. Cover only looks in cwd and ../src
%% for source files. Also copy files from src_dirs.
- ErlOpts = rebar_utils:erl_opts(Config),
-
- SrcDirs = rebar_utils:src_dirs(proplists:append_values(src_dirs, ErlOpts)),
+ SrcDirs = rebar_utils:src_dirs(proplists:append_values(src_dirs, ErlOpts1)),
SrcErls = lists:foldl(
fun(Dir, Acc) ->
Files = rebar_utils:find_files(Dir, ".*\\.erl\$"),
@@ -172,8 +173,7 @@ test_compile(Config, Cmd, OutDir) ->
%% Compile erlang code to OutDir, using a tweaked config
%% with appropriate defines for eunit, and include all the test modules
%% as well.
- ok = doterl_compile(test_compile_config(Config, ErlOpts, Cmd),
- OutDir, TestErls, ErlOpts),
+ ok = doterl_compile(Config1, OutDir, TestErls, ErlOpts1),
{ok, SrcErls}.
@@ -217,21 +217,22 @@ info_help(Description) ->
{yrl_first_files, []}
]).
-test_compile_config(Config, ErlOpts, Cmd) ->
+test_compile_config_and_opts(Config, ErlOpts, Cmd) ->
{Config1, TriqOpts} = triq_opts(Config),
{Config2, PropErOpts} = proper_opts(Config1),
{Config3, EqcOpts} = eqc_opts(Config2),
OptsAtom = list_to_atom(Cmd ++ "_compile_opts"),
- EunitOpts = rebar_config:get_list(Config3, OptsAtom, []),
+ TestOpts = rebar_config:get_list(Config3, OptsAtom, []),
Opts0 = [{d, 'TEST'}] ++
- ErlOpts ++ EunitOpts ++ TriqOpts ++ PropErOpts ++ EqcOpts,
+ ErlOpts ++ TestOpts ++ TriqOpts ++ PropErOpts ++ EqcOpts,
Opts = [O || O <- Opts0, O =/= no_debug_info],
Config4 = rebar_config:set(Config3, erl_opts, Opts),
FirstFilesAtom = list_to_atom(Cmd ++ "_first_files"),
FirstErls = rebar_config:get_list(Config4, FirstFilesAtom, []),
- rebar_config:set(Config4, erl_first_files, FirstErls).
+ Config5 = rebar_config:set(Config4, erl_first_files, FirstErls),
+ {Config5, Opts}.
triq_opts(Config) ->
{NewConfig, IsAvail} = is_lib_avail(Config, is_triq_avail, triq,
@@ -538,7 +539,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_metacmds.erl b/src/rebar_metacmds.erl
new file mode 100644
index 0000000..6e223bd
--- /dev/null
+++ b/src/rebar_metacmds.erl
@@ -0,0 +1,56 @@
+%% -*- erlang-indent-level: 4;indent-tabs-mode: nil -*-
+%% ex: ts=4 sw=4 et
+%% -------------------------------------------------------------------
+%%
+%% rebar: Erlang Build Tools
+%%
+%% Copyright (c) 2013-2014 Tuncer Ayaz
+%%
+%% Permission is hereby granted, free of charge, to any person obtaining a copy
+%% of this software and associated documentation files (the "Software"), to deal
+%% in the Software without restriction, including without limitation the rights
+%% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+%% copies of the Software, and to permit persons to whom the Software is
+%% furnished to do so, subject to the following conditions:
+%%
+%% The above copyright notice and this permission notice shall be included in
+%% all copies or substantial portions of the Software.
+%%
+%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+%% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+%% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+%% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+%% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+%% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+%% THE SOFTWARE.
+%% -------------------------------------------------------------------
+-module(rebar_metacmds).
+
+-export(['prepare-deps'/2,
+ 'refresh-deps'/2]).
+
+%% for internal use only
+-export([info/2]).
+
+-include("rebar.hrl").
+
+%% ===================================================================
+%% Public API
+%% ===================================================================
+'prepare-deps'(Config, _AppFile) ->
+ rebar:run(enable_recursion(Config), ["get-deps", "compile"]).
+
+'refresh-deps'(Config, _AppFile) ->
+ rebar:run(enable_recursion(Config), ["update-deps", "compile"]).
+
+%% ===================================================================
+%% Internal functions
+%% ===================================================================
+
+info(help, 'prepare-deps') ->
+ ?CONSOLE("Meta command to run 'rebar -r get-deps compile'.~n", []);
+info(help, 'refresh-deps') ->
+ ?CONSOLE("Meta command to run 'rebar -r update-deps compile'.~n", []).
+
+enable_recursion(Config) ->
+ rebar_config:set_xconf(Config, recursive, true).
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_templater.erl b/src/rebar_templater.erl
index 43bb8da..fef4627 100644
--- a/src/rebar_templater.erl
+++ b/src/rebar_templater.erl
@@ -245,7 +245,8 @@ find_disk_templates(Config) ->
HomeFiles = rebar_utils:find_files(filename:join([os:getenv("HOME"),
".rebar", "templates"]),
?TEMPLATE_RE),
- LocalFiles = rebar_utils:find_files(".", ?TEMPLATE_RE),
+ Recursive = rebar_config:is_recursive(Config),
+ LocalFiles = rebar_utils:find_files(".", ?TEMPLATE_RE, Recursive),
[{file, F} || F <- OtherTemplates ++ HomeFiles ++ LocalFiles].
find_other_templates(Config) ->
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"))
+ ].