summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.travis.yml3
-rw-r--r--README.md86
-rw-r--r--THANKS2
-rw-r--r--dialyzer_reference2
-rw-r--r--inttest/t_custom_config/t_custom_config_rt.erl2
-rw-r--r--priv/shell-completion/zsh/_rebar79
-rw-r--r--rebar.config.sample15
-rw-r--r--src/rebar.erl7
-rw-r--r--src/rebar_base_compiler.erl20
-rw-r--r--src/rebar_ct.erl13
-rw-r--r--src/rebar_deps.erl88
-rw-r--r--src/rebar_require_vsn.erl29
-rw-r--r--src/rebar_utils.erl7
-rw-r--r--src/rebar_xref.erl19
14 files changed, 277 insertions, 95 deletions
diff --git a/.travis.yml b/.travis.yml
index fc9c771..f5e3d99 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,7 +1,4 @@
language: erlang
-notifications:
- webhooks: http://basho-engbot.herokuapp.com/travis?key=a0e66154af272adba328195454cfdc10ff5f33f5
- email: eng@basho.com
otp_release:
- R15B01
- R15B
diff --git a/README.md b/README.md
index 68236e1..3be5091 100644
--- a/README.md
+++ b/README.md
@@ -1,29 +1,28 @@
rebar
=====
-rebar is an Erlang build tool that makes it easy to compile and
-test Erlang applications, port drivers and releases.
+rebar is an Erlang build tool that makes it easy to compile and test Erlang
+applications, port drivers and releases.
-[![Build Status](https://secure.travis-ci.org/basho/rebar.png?branch=master)](http://travis-ci.org/basho/rebar)
+[![Build Status](https://secure.travis-ci.org/rebar/rebar.png?branch=master)](http://travis-ci.org/rebar/rebar)
-rebar is a self-contained Erlang script, so it's easy to distribute or even
-embed directly in a project. Where possible, rebar uses standard Erlang/OTP
-conventions for project structures, thus minimizing the amount of build
-configuration work. rebar also provides dependency management, enabling
-application writers to easily re-use common libraries from a variety of
+rebar is a self-contained Erlang script, so it's easy to distribute or even
+embed directly in a project. Where possible, rebar uses standard Erlang/OTP
+conventions for project structures, thus minimizing the amount of build
+configuration work. rebar also provides dependency management, enabling
+application writers to easily re-use common libraries from a variety of
locations (git, hg, etc).
Building
--------
-Information on building and installing [Erlang/OTP](http://www.erlang.org)
-can be found [here](https://github.com/erlang/otp/wiki/Installation)
-([more info](https://github.com/erlang/otp/blob/master/INSTALL.md)).
+Information on building and installing [Erlang/OTP](http://www.erlang.org) can
+be found [here](https://github.com/erlang/otp/wiki/Installation) ([more
+info](https://github.com/erlang/otp/blob/master/INSTALL.md)).
### Dependencies
-To build rebar you will need a working installation of Erlang R13B03 (or
-later).
+To build rebar you will need a working installation of Erlang R13B03 (or later).
Should you want to clone the rebar repository, you will also require git.
@@ -31,12 +30,12 @@ Should you want to clone the rebar repository, you will also require git.
You can download a pre-built binary version of rebar from:
-https://github.com/basho/rebar/wiki/rebar
+https://github.com/rebar/rebar/wiki/rebar
#### Building rebar
```sh
-$ git clone git://github.com/basho/rebar.git
+$ git clone git://github.com/rebar/rebar.git
$ cd rebar
$ ./bootstrap
Recompile: src/getopt
@@ -72,9 +71,10 @@ Do not mix spaces and tabs.
Do not introduce lines longer than 80 characters.
-[erlang-mode (emacs)](http://www.erlang.org/doc/man/erlang.el.html) indentation is preferred.
-vi-only users are encouraged to
-give [Vim emulation](http://emacswiki.org/emacs/Evil) ([more info](https://gitorious.org/evil/pages/Home)) a try.
+[erlang-mode (emacs)](http://www.erlang.org/doc/man/erlang.el.html) indentation
+is preferred. vi-only users are encouraged to give [Vim
+emulation](http://emacswiki.org/emacs/Evil) ([more
+info](https://gitorious.org/evil/pages/Home)) a try.
Writing Commit Messages
-----------------------
@@ -111,43 +111,39 @@ Longer description (wrap at 72 characters)
Run checks
----------
-Before you submit a patch, run ``make check`` to execute
-the test suite and check for
-[xref](http://www.erlang.org/doc/man/xref.html) and
-[Dialyzer](http://www.erlang.org/doc/man/dialyzer.html)
-warnings. You may have to run ``make clean`` first.
+Before you submit a patch, run ``make check`` to execute the test suite and
+check for [xref](http://www.erlang.org/doc/man/xref.html) and
+[Dialyzer](http://www.erlang.org/doc/man/dialyzer.html) warnings. You may have
+to run ``make clean`` first.
[Dialyzer](http://www.erlang.org/doc/man/dialyzer.html) warnings are compared
-against a set of safe-to-ignore warnings found in
-[dialyzer_reference](https://raw.github.com/basho/rebar/master/dialyzer_reference).
-[xref](http://www.erlang.org/doc/man/xref.html) is run with
-[custom queries](https://raw.github.com/basho/rebar/master/rebar.config)
-to suppress safe-to-ignore warnings.
-
-It is **strongly recommended** to check the code with
-[Tidier](http://tidier.softlab.ntua.gr:20000/tidier/getstarted).
-Select all transformation
-options and enable **automatic** transformation. If Tidier suggests a transformation,
-apply the changes **manually** to the source code. Do not use the code from
-the
-tarball (*out.tgz*) as it will have white-space changes applied by Erlang's pretty-printer.
+against a set of safe-to-ignore warnings found in
+[dialyzer_reference](https://raw.github.com/rebar/rebar/master/dialyzer_reference).
+[xref](http://www.erlang.org/doc/man/xref.html) is run with [custom
+queries](https://raw.github.com/rebar/rebar/master/rebar.config) to suppress
+safe-to-ignore warnings.
Community and Resources
-----------------------
-In case of problems that cannot be solved through documentation or examples, you may
-want to try to contact members of the community for help. The community is also where
-you want to go for questions about how to extend rebar, fill in bug reports, and so on.
+In case of problems that cannot be solved through documentation or examples, you
+may want to try to contact members of the community for help. The community is
+also where you want to go for questions about how to extend rebar, fill in bug
+reports, and so on.
-The main place to go for questions is the [rebar mailing list](http://lists.basho.com/pipermail/rebar_lists.basho.com/). If you need quick feedback,
-you can try the #rebar channel on [irc.freenode.net](http://freenode.net). Be sure to check the [wiki](https://github.com/basho/rebar/wiki) first,
-just to be sure you're not asking about things with well known answers.
+The main place to go for questions is the [rebar mailing
+list](http://lists.basho.com/pipermail/rebar_lists.basho.com/). If you need
+quick feedback, you can try the #rebar channel on
+[irc.freenode.net](http://freenode.net). Be sure to check the
+[wiki](https://github.com/rebar/rebar/wiki) first, just to be sure you're not
+asking about things with well known answers.
-For bug reports, roadmaps, and issues, visit the [github issues page](https://github.com/basho/rebar/issues).
+For bug reports, roadmaps, and issues, visit the [github issues
+page](https://github.com/rebar/rebar/issues).
General rebar community resources and links:
- [Rebar Mailing List](http://lists.basho.com/pipermail/rebar_lists.basho.com/)
- #rebar on [irc.freenode.net](http://freenode.net/)
-- [wiki](https://github.com/basho/rebar/wiki)
-- [issues](https://github.com/basho/rebar/issues)
+- [wiki](https://github.com/rebar/rebar/wiki)
+- [issues](https://github.com/rebar/rebar/issues)
diff --git a/THANKS b/THANKS
index f8b4c9b..16b1f24 100644
--- a/THANKS
+++ b/THANKS
@@ -107,3 +107,5 @@ Dmitriy Kargapolov
Ryan Zezeski
Daniel White
Martin Schut
+Serge Aleynikov
+Magnus Henoch
diff --git a/dialyzer_reference b/dialyzer_reference
index ff3dc50..a50bb88 100644
--- a/dialyzer_reference
+++ b/dialyzer_reference
@@ -1,3 +1,3 @@
rebar_eunit.erl:351: Call to missing or unexported function eunit_test:function_wrapper/2
-rebar_utils.erl:163: Call to missing or unexported function escript:foldl/3
+rebar_utils.erl:162: Call to missing or unexported function escript:foldl/3
diff --git a/inttest/t_custom_config/t_custom_config_rt.erl b/inttest/t_custom_config/t_custom_config_rt.erl
index 0609abb..864ce5e 100644
--- a/inttest/t_custom_config/t_custom_config_rt.erl
+++ b/inttest/t_custom_config/t_custom_config_rt.erl
@@ -20,7 +20,7 @@ run(Dir) ->
{ok, Missing} =
retest:sh_expect(Ref,
"DEBUG: Missing deps : \\[\\{dep,bad_name,"
- "boo,\"\\.\",undefined\\}\\]",
+ "boo,\"\\.\",undefined,false\\}\\]",
[{capture, all, list}]),
retest_log:log(debug, "[CAPTURED]: ~s~n", [Captured]),
retest_log:log(debug, "[Missing]: ~s~n", [Missing]),
diff --git a/priv/shell-completion/zsh/_rebar b/priv/shell-completion/zsh/_rebar
new file mode 100644
index 0000000..7ac5a51
--- /dev/null
+++ b/priv/shell-completion/zsh/_rebar
@@ -0,0 +1,79 @@
+#compdef rebar
+
+local curcontext=$curcontext state ret=1
+typeset -ga _rebar_global_opts
+
+_rebar_global_opts=(
+ '(--help -h)'{--help,-h}'[Show the program options]'
+ '(--commands -c)'{--commands,-c}'[Show available commands]'
+ '(--version -V)'{--version,-V}'[Show version information]'
+ '(-vvv -vv -v)'--verbose+'[Verbosity level. Default: 0]:verbosity level:(0 1 2 3)'
+ '(-vvv)-v[Slightly more verbose output]'
+ '(-vvv)-vv[More verbose output]'
+ '(-v -vv)-vvv[Most verbose output]'
+ '(--force -f)'{--force,-f}'[Force]'
+ '-D+[Define compiler macro]'
+ '(--jobs -j)'{--jobs+,-j+}'[Number of concurrent workers a command may use. Default: 3]:workers:(1 2 3 4 5 6 7 8 9)'
+ '(--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]'
+)
+
+_rebar () {
+ _arguments -C $_rebar_global_opts \
+ '*::command and variable:->cmd_and_var' \
+ && return
+
+ case $state in
+ cmd_and_var)
+ _values -S = 'variables' \
+ 'clean[Clean]' \
+ 'compile[Compile sources]' \
+ 'create[Create skel based on template and vars]' \
+ 'create-app[Create simple app skel]' \
+ 'create-node[Create simple node skel]' \
+ 'list-template[List avaiavle templates]' \
+ 'doc[Generate Erlang program documentation]' \
+ 'check-deps[Display to be fetched dependencies]' \
+ 'get-deps[Fetch dependencies]' \
+ 'update-deps[Update fetched dependencies]' \
+ 'delete-deps[Delete fetched dependencies]' \
+ 'list-deps[List dependencies]' \
+ 'generate[Build release with reltool]' \
+ 'overlay[Run reltool overlays only]' \
+ 'generate-appups[Generate appup files]' \
+ 'generate-upgrade[Build an upgrade package]' \
+ 'eunit[Run eunit tests]' \
+ 'ct[Run common_test suites]' \
+ 'qc[Test QuickCheck properties]' \
+ 'xref[Run cross reference analysis]' \
+ 'help[Show the program options]' \
+ 'version[Show version information]' \
+ 'apps[Application names to process]:' \
+ 'case[Common Test case]:' \
+ 'dump_spec[Dump reltool spec]:' \
+ 'jobs[Number of workers]::workers:(0 1 2 3 4 5 6 7 8 9)' \
+ 'suites[Common Test suites]::suite name:_path_files -W "(src test)" -g "*.erl(:r)"' \
+ 'verbose[Verbosity level]::verbosity level:(0 1 2 3)' \
+ 'appid[Application id]:' \
+ 'previous_release[Previous release path]:' \
+ 'nodeid[Node id]:' \
+ 'root_dir[Reltool config root directory]::directory:_files -/' \
+ 'skip_deps[Skip deps]::flag:(true false)' \
+ 'skip_apps[Application names to not process]::flag:(true false)' \
+ 'template[Template name]:' \
+ 'template_dir[Template directory]::directory:_files -/' \
+ && ret=0
+ ;;
+ esac
+}
+
+_rebar
+
+# Local variables:
+# mode: shell-script
+# sh-basic-offset: 2
+# sh-indent-comment: t
+# indent-tabs-mode: nil
+# End:
+# ex: sw=2 ts=2 et filetype=sh
diff --git a/rebar.config.sample b/rebar.config.sample
index 4ed815a..fac55af 100644
--- a/rebar.config.sample
+++ b/rebar.config.sample
@@ -138,7 +138,20 @@
{deps, [application_name,
{application_name, "1.0.*"},
{application_name, "1.0.*",
- {git, "git://github.com/basho/rebar.git", {branch, "master"}}}]}.
+ {git, "git://github.com/basho/rebar.git", {branch, "master"}}},
+
+%% Dependencies can be marked as 'raw'. Rebar does not require such dependencies
+%% to have a standard Erlang/OTP layout which assumes the presence of either
+%% "src/dependency_name.app.src" or "ebin/dependency_name.app" files.
+%%
+%% 'raw' dependencies can still contain 'rebar.config' and even can have the
+%% proper OTP directory layout, but they won't be compiled.
+%%
+%% Only a subset of rebar commands will be executed on the 'raw' subdirectories:
+%% get-deps, update-deps, check-deps, list-deps and delete-deps.
+ {application_name, "",
+ {git, "git://github.com/basho/rebar.git", {branch, "master"}},
+ [raw]}]}.
%% == Subdirectories ==
diff --git a/src/rebar.erl b/src/rebar.erl
index cd0bed5..82e3fac 100644
--- a/src/rebar.erl
+++ b/src/rebar.erl
@@ -27,6 +27,7 @@
-module(rebar).
-export([main/1,
+ run/2,
help/0,
parse_args/1,
version/0,
@@ -52,6 +53,7 @@
%% Public API
%% ====================================================================
+%% escript Entry point
main(Args) ->
case catch(run(Args)) of
ok ->
@@ -65,6 +67,11 @@ main(Args) ->
rebar_utils:delayed_halt(1)
end.
+%% Erlang-API entry point
+run(BaseConfig, Commands) ->
+ application:load(rebar),
+ run_aux(BaseConfig, Commands).
+
%% ====================================================================
%% Internal functions
%% ====================================================================
diff --git a/src/rebar_base_compiler.erl b/src/rebar_base_compiler.erl
index 0721725..260cdaf 100644
--- a/src/rebar_base_compiler.erl
+++ b/src/rebar_base_compiler.erl
@@ -235,15 +235,17 @@ maybe_report(_) ->
report(Messages) ->
lists:foreach(fun(Msg) -> io:format("~s", [Msg]) end, Messages).
-format_errors(Config, Source, Extra, Errors) ->
- AbsSource = case rebar_utils:processing_base_dir(Config) of
- true ->
- Source;
- false ->
- filename:absname(Source)
- end,
- [[format_error(AbsSource, Extra, Desc) || Desc <- Descs]
- || {_, Descs} <- Errors].
+format_errors(Config, _MainSource, Extra, Errors) ->
+ [begin
+ AbsSource = case rebar_utils:processing_base_dir(Config) of
+ true ->
+ Source;
+ false ->
+ filename:absname(Source)
+ end,
+ [format_error(AbsSource, Extra, Desc) || Desc <- Descs]
+ end
+ || {Source, Descs} <- Errors].
format_error(AbsSource, Extra, {{Line, Column}, Mod, Desc}) ->
ErrorDesc = Mod:format_error(Desc),
diff --git a/src/rebar_ct.erl b/src/rebar_ct.erl
index 6fd5bc7..e33c6c9 100644
--- a/src/rebar_ct.erl
+++ b/src/rebar_ct.erl
@@ -65,7 +65,12 @@ run_test_if_present(TestDir, LogDir, Config, File) ->
++ " SUITES - skipping\n", [TestDir]),
ok;
_ ->
- run_test(TestDir, LogDir, Config, File)
+ try
+ run_test(TestDir, LogDir, Config, File)
+ catch
+ throw:skip ->
+ ok
+ end
end
end.
@@ -270,8 +275,10 @@ find_suite_path(Suite, TestDir) ->
Path = filename:join(TestDir, Suite ++ "_SUITE.erl"),
case filelib:is_regular(Path) of
false ->
- ?ERROR("Suite ~s not found\n", [Suite]),
- ?FAIL;
+ ?WARN("Suite ~s not found\n", [Suite]),
+ %% Note - this throw is caught in run_test_if_present/3;
+ %% this solution was easier than refactoring the entire module.
+ throw(skip);
true ->
Path
end.
diff --git a/src/rebar_deps.erl b/src/rebar_deps.erl
index cac4188..074e929 100644
--- a/src/rebar_deps.erl
+++ b/src/rebar_deps.erl
@@ -42,7 +42,8 @@
-record(dep, { dir,
app,
vsn_regex,
- source }).
+ source,
+ is_raw }). %% is_raw = true means non-Erlang/OTP dependency
%% ===================================================================
%% Public API
@@ -68,18 +69,34 @@ preprocess(Config, _) ->
%% If skip_deps=true, mark each dep dir as a skip_dir w/ the core so that
%% the current command doesn't run on the dep dir. However, pre/postprocess
%% WILL run (and we want it to) for transitivity purposes.
+ %%
+ %% Also, if skip_deps=comma,separated,app,list, then only the given
+ %% dependencies are skipped.
NewConfig = case rebar_config:get_global(Config3, skip_deps, false) of
- "true" ->
- lists:foldl(
- fun(#dep{dir = Dir}, C) ->
- rebar_config:set_skip_dir(C, Dir)
- end, Config3, AvailableDeps);
- _ ->
- Config3
- end,
+ "true" ->
+ lists:foldl(
+ fun(#dep{dir = Dir}, C) ->
+ rebar_config:set_skip_dir(C, Dir)
+ end, Config3, AvailableDeps);
+ Apps when is_list(Apps) ->
+ SkipApps = [list_to_atom(App) || App <- string:tokens(Apps, ",")],
+ lists:foldl(
+ fun(#dep{dir = Dir, app = App}, C) ->
+ case lists:member(App, SkipApps) of
+ true -> rebar_config:set_skip_dir(C, Dir);
+ false -> C
+ end
+ end, Config3, AvailableDeps);
+ _ ->
+ Config3
+ end,
+
+ %% Filtering out 'raw' dependencies so that no commands other than
+ %% deps-related can be executed on their directories.
+ NonRawAvailableDeps = [D || D <- AvailableDeps, not D#dep.is_raw],
%% Return all the available dep directories for process
- {ok, NewConfig, dep_dirs(AvailableDeps)}.
+ {ok, NewConfig, dep_dirs(NonRawAvailableDeps)}.
postprocess(Config, _) ->
case rebar_config:get_xconf(Config, ?MODULE, undefined) of
@@ -90,8 +107,9 @@ postprocess(Config, _) ->
{ok, NewConfig, Dirs}
end.
-compile(Config, AppFile) ->
- 'check-deps'(Config, AppFile).
+compile(Config, _) ->
+ {Config1, _AvailDeps} = do_check_deps(Config),
+ {ok, Config1}.
%% set REBAR_DEPS_DIR and ERL_LIBS environment variables
setup_env(Config) ->
@@ -111,13 +129,14 @@ setup_env(Config) ->
end,
[{"REBAR_DEPS_DIR", DepsDir}, ERL_LIBS].
-'check-deps'(Config, _) ->
+%% common function used by 'check-deps' and 'compile'
+do_check_deps(Config) ->
%% Get the list of immediate (i.e. non-transitive) deps that are missing
Deps = rebar_config:get_local(Config, deps, []),
case find_deps(Config, find, Deps) of
- {Config1, {_, []}} ->
+ {Config1, {AvailDeps, []}} ->
%% No missing deps
- {ok, Config1};
+ {Config1, AvailDeps};
{_Config1, {_, MissingDeps}} ->
lists:foreach(fun (#dep{app=App, vsn_regex=Vsn, source=Src}) ->
?CONSOLE("Dependency not available: "
@@ -126,6 +145,10 @@ setup_env(Config) ->
?FAIL
end.
+'check-deps'(Config, _) ->
+ {Config1, AvailDeps} = do_check_deps(Config),
+ {ok, save_dep_dirs(Config1, AvailDeps)}.
+
'get-deps'(Config, _) ->
%% Determine what deps are available and missing
Deps = rebar_config:get_local(Config, deps, []),
@@ -171,7 +194,7 @@ setup_env(Config) ->
case find_deps(Config, find, Deps) of
{Config1, {AvailDeps, []}} ->
lists:foreach(fun(Dep) -> print_source(Dep) end, AvailDeps),
- {ok, Config1};
+ {ok, save_dep_dirs(Config1, AvailDeps)};
{_, MissingDeps} ->
?ABORT("Missing dependencies: ~p\n", [MissingDeps])
end.
@@ -221,7 +244,7 @@ update_deps_code_path(Config, []) ->
update_deps_code_path(Config, [Dep | Rest]) ->
Config2 =
case is_app_available(Config, Dep#dep.app,
- Dep#dep.vsn_regex, Dep#dep.dir) of
+ Dep#dep.vsn_regex, Dep#dep.dir, Dep#dep.is_raw) of
{Config1, {true, _}} ->
Dir = filename:join(Dep#dep.dir, "ebin"),
ok = filelib:ensure_dir(filename:join(Dir, "dummy")),
@@ -247,9 +270,14 @@ find_deps(Config, Mode, [App | Rest], Acc) when is_atom(App) ->
find_deps(Config, Mode, [{App, VsnRegex} | Rest], Acc) when is_atom(App) ->
find_deps(Config, Mode, [{App, VsnRegex, undefined} | Rest], Acc);
find_deps(Config, Mode, [{App, VsnRegex, Source} | Rest], Acc) ->
+ find_deps(Config, Mode, [{App, VsnRegex, Source, []} | Rest], Acc);
+find_deps(Config, Mode, [{App, VsnRegex, Source, Opts} | Rest], Acc) when is_list(Opts) ->
Dep = #dep { app = App,
vsn_regex = VsnRegex,
- source = Source },
+ source = Source,
+ %% dependency is considered raw (i.e. non-Erlang/OTP) when
+ %% 'raw' option is present
+ is_raw = proplists:get_value(raw, Opts, false) },
{Config1, {Availability, FoundDir}} = find_dep(Config, Dep),
find_deps(Config1, Mode, Rest,
acc_deps(Mode, Availability, Dep, FoundDir, Acc));
@@ -284,7 +312,8 @@ find_dep_in_dir(Config, _Dep, {false, Dir}) ->
find_dep_in_dir(Config, Dep, {true, Dir}) ->
App = Dep#dep.app,
VsnRegex = Dep#dep.vsn_regex,
- case is_app_available(Config, App, VsnRegex, Dir) of
+ IsRaw = Dep#dep.is_raw,
+ case is_app_available(Config, App, VsnRegex, Dir, IsRaw) of
{Config1, {true, _AppFile}} -> {Config1, {avail, Dir}};
{Config1, {false, _}} -> {Config1, {missing, Dir}}
end.
@@ -309,7 +338,11 @@ require_source_engine(Source) ->
true = source_engine_avail(Source),
ok.
-is_app_available(Config, App, VsnRegex, Path) ->
+%% IsRaw = false means regular Erlang/OTP dependency
+%%
+%% IsRaw = true means non-Erlang/OTP dependency, e.g. the one that does not
+%% have a proper .app file
+is_app_available(Config, App, VsnRegex, Path, _IsRaw = false) ->
?DEBUG("is_app_available, looking for App ~p with Path ~p~n", [App, Path]),
case rebar_app_utils:is_app_dir(Path) of
{true, AppFile} ->
@@ -340,6 +373,19 @@ is_app_available(Config, App, VsnRegex, Path) ->
?WARN("Expected ~s to be an app dir (containing ebin/*.app), "
"but no .app found.\n", [Path]),
{Config, {false, {missing_app_file, Path}}}
+ end;
+is_app_available(Config, App, _VsnRegex, Path, _IsRaw = true) ->
+ ?DEBUG("is_app_available, looking for Raw Depencency ~p with Path ~p~n", [App, Path]),
+ case filelib:is_dir(Path) of
+ true ->
+ %% TODO: look for version string in <Path>/VERSION file? Not clear
+ %% how to detect git/svn/hg/{cmd, ...} settings that can be passed
+ %% to rebar_utils:vcs_vsn/2 to obtain version dynamically
+ {Config, {true, Path}};
+ false ->
+ ?WARN("Expected ~s to be a raw dependency directory, "
+ "but no directory found.\n", [Path]),
+ {Config, {false, {missing_raw_dependency_directory, Path}}}
end.
use_source(Config, Dep) ->
@@ -353,7 +399,7 @@ use_source(Config, Dep, Count) ->
true ->
%% Already downloaded -- verify the versioning matches the regex
case is_app_available(Config, Dep#dep.app,
- Dep#dep.vsn_regex, Dep#dep.dir) of
+ Dep#dep.vsn_regex, Dep#dep.dir, Dep#dep.is_raw) of
{Config1, {true, _}} ->
Dir = filename:join(Dep#dep.dir, "ebin"),
ok = filelib:ensure_dir(filename:join(Dir, "dummy")),
diff --git a/src/rebar_require_vsn.erl b/src/rebar_require_vsn.erl
index 327f75c..83cb79d 100644
--- a/src/rebar_require_vsn.erl
+++ b/src/rebar_require_vsn.erl
@@ -67,4 +67,33 @@ check_versions(Config) ->
nomatch ->
?ABORT("OTP release ~s does not match required regex ~s\n",
[erlang:system_info(otp_release), OtpRegex])
+ end,
+
+ case rebar_config:get(Config, require_min_otp_vsn, undefined) of
+ undefined -> ?DEBUG("Min OTP version unconfigured~n", []);
+ MinOtpVsn ->
+ {MinMaj, MinMin} = version_tuple(MinOtpVsn, "configured"),
+ {OtpMaj, OtpMin} = version_tuple(erlang:system_info(otp_release),
+ "OTP Release"),
+ case {OtpMaj, OtpMin} >= {MinMaj, MinMin} of
+ true ->
+ ?DEBUG("~s satisfies the requirement for vsn ~s~n",
+ [erlang:system_info(otp_release),
+ MinOtpVsn]);
+ false ->
+ ?ABORT("OTP release ~s or later is required, you have: ~s~n",
+ [MinOtpVsn,
+ erlang:system_info(otp_release)])
+ end
+ end.
+
+version_tuple(OtpRelease, Type) ->
+ 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]} ->
+ {list_to_integer(Maj), 0};
+ nomatch ->
+ ?ABORT("Cannot parse ~s version string: ~s~n",
+ [Type, OtpRelease])
end.
diff --git a/src/rebar_utils.erl b/src/rebar_utils.erl
index 1049c1d..bb58460 100644
--- a/src/rebar_utils.erl
+++ b/src/rebar_utils.erl
@@ -75,8 +75,7 @@ is_arch(ArchRegex) ->
get_arch() ->
Words = wordsize(),
erlang:system_info(otp_release) ++ "-"
- ++ erlang:system_info(system_architecture) ++ "-" ++ Words
- ++ "-" ++ os_family().
+ ++ erlang:system_info(system_architecture) ++ "-" ++ Words.
wordsize() ->
try erlang:system_info({wordsize, external}) of
@@ -318,10 +317,6 @@ processing_base_dir(Config, Dir) ->
%% Internal functions
%% ====================================================================
-os_family() ->
- {OsFamily, _} = os:type(),
- atom_to_list(OsFamily).
-
get_deprecated_3(Get, Config, OldOpt, NewOpt, Default, When) ->
case Get(Config, NewOpt, Default) of
Default ->
diff --git a/src/rebar_xref.erl b/src/rebar_xref.erl
index 84b59f6..a55d71d 100644
--- a/src/rebar_xref.erl
+++ b/src/rebar_xref.erl
@@ -28,7 +28,8 @@
%% -------------------------------------------------------------------
%% This module borrows heavily from http://github.com/etnt/exrefcheck project as
-%% written by Torbjorn Tornkvist <tobbe@kreditor.se>, Daniel Luna and others.
+%% written by Torbjorn Tornkvist <tobbe@kreditor.se>, Daniel Luna
+%% <daniel@lunas.se> and others.
%% -------------------------------------------------------------------
-module(rebar_xref).
@@ -43,7 +44,7 @@
xref(Config, _) ->
%% Spin up xref
{ok, _} = xref:start(xref),
- ok = xref:set_library_path(xref, code_path()),
+ ok = xref:set_library_path(xref, code_path(Config)),
xref:set_default(xref, [{warnings,
rebar_config:get(Config, xref_warnings, false)},
@@ -131,9 +132,17 @@ check_query({Query, Value}) ->
true
end.
-code_path() ->
- [P || P <- code:get_path(),
- filelib:is_dir(P)] ++ [filename:join(rebar_utils:get_cwd(), "ebin")].
+code_path(Config) ->
+ %% Slight hack to ensure that sub_dirs get properly included
+ %% in code path for xref -- otherwise one gets a lot of undefined
+ %% functions, even though those functions are present as part
+ %% of compilation. H/t to @dluna. Long term we should tie more
+ %% properly into the overall compile code path if possible.
+ BaseDir = rebar_config:get_xconf(Config, base_dir),
+ [P || P <- code:get_path() ++
+ [filename:join(BaseDir, filename:join(SubDir, "ebin"))
+ || SubDir <- rebar_config:get(Config, sub_dirs, [])],
+ filelib:is_dir(P)].
%%
%% Ignore behaviour functions, and explicitly marked functions