Introduce REBAR_DEPS_PREFER_LIBS env variable to alter search behaviour

When REBAR_DEPS_PREFER_LIBS is set, dependencies with defined sources
are allowed to be searched for in system lib directory.

Under specific circumstances (i.e. in build environments without networking)
it is impossible to fetch deps locally. So, user needs a way to ask rebar to
search in system lib directory as well.

Signed-off-by: Matwey V. Kornilov <matwey.kornilov@gmail.com>
diff --git a/THANKS b/THANKS
index 888cc1d..ab7935c 100644
--- a/THANKS
+++ b/THANKS
@@ -149,3 +149,4 @@
 John Daily
 Yury Gargay
 Frank Hunleth
+Matwey Kornilov
diff --git a/inttest/tdeps_prefer/a.erl b/inttest/tdeps_prefer/a.erl
new file mode 100644
index 0000000..bf413a6
--- /dev/null
+++ b/inttest/tdeps_prefer/a.erl
@@ -0,0 +1,4 @@
+-module({{module}}).
+
+-include_lib("b/include/b.hrl").
+-include_lib("c/include/c.hrl").
diff --git a/inttest/tdeps_prefer/a.rebar.config b/inttest/tdeps_prefer/a.rebar.config
new file mode 100644
index 0000000..41fe9bc
--- /dev/null
+++ b/inttest/tdeps_prefer/a.rebar.config
@@ -0,0 +1,4 @@
+{deps, [
+	{c, "1", {git, "../repo/c"}},
+	{b, "1", {git, "../repo/b"}}
+]}.
diff --git a/inttest/tdeps_prefer/b.hrl b/inttest/tdeps_prefer/b.hrl
new file mode 100644
index 0000000..9f02fab
--- /dev/null
+++ b/inttest/tdeps_prefer/b.hrl
@@ -0,0 +1 @@
+-define(HELLO, hello).
diff --git a/inttest/tdeps_prefer/c.hrl b/inttest/tdeps_prefer/c.hrl
new file mode 100644
index 0000000..152a99f
--- /dev/null
+++ b/inttest/tdeps_prefer/c.hrl
@@ -0,0 +1 @@
+-define(WORLD, world).
diff --git a/inttest/tdeps_prefer/root.rebar.config b/inttest/tdeps_prefer/root.rebar.config
new file mode 100644
index 0000000..d1c3793
--- /dev/null
+++ b/inttest/tdeps_prefer/root.rebar.config
@@ -0,0 +1 @@
+{sub_dirs, ["apps/a"]}.
diff --git a/inttest/tdeps_prefer/tdeps_prefer_rt.erl b/inttest/tdeps_prefer/tdeps_prefer_rt.erl
new file mode 100644
index 0000000..94c9b8f
--- /dev/null
+++ b/inttest/tdeps_prefer/tdeps_prefer_rt.erl
@@ -0,0 +1,68 @@
+%% -*- erlang-indent-level: 4;indent-tabs-mode: nil -*-
+%% ex: ts=4 sw=4 et
+-module(tdeps_prefer_rt).
+
+-compile(export_all).
+
+setup([Target]) ->
+    retest_utils:load_module(filename:join(Target, "inttest_utils.erl")),
+    ok.
+
+%% Test REBAR_DEPS_FORCE_LIB
+%% A -> [B, C]
+%% where B should be found globally and C should be found locally
+files() ->
+    [
+    %% A application
+    {create, "apps/a/ebin/a.app", app(a, [a])},
+    {copy, "a.rebar.config", "apps/a/rebar.config"},
+    {template, "a.erl", "apps/a/src/a.erl", dict:from_list([{module, a}])},
+
+    %% B application
+    {create, "libs/b-1/ebin/b.app", app(b, [])},
+    {copy, "b.hrl", "libs/b-1/include/b.hrl"},
+
+    %% C application
+    {create, "repo/c/ebin/c.app", app(c, [])},
+    {copy, "c.hrl", "repo/c/include/c.hrl"},
+
+    {copy, "root.rebar.config", "rebar.config"}
+    ] ++ inttest_utils:rebar_setup().
+
+apply_cmds([], _Params) ->
+    ok;
+apply_cmds([Cmd | Rest], Params) ->
+    io:format("Running: ~s (~p)\n", [Cmd, Params]),
+    {ok, _} = retest_sh:run(Cmd, Params),
+    apply_cmds(Rest, Params).
+
+run(Dir) ->
+    %% Initialize the c apps as git repos so that dependencies pull
+    %% properly
+    GitCmds = ["git init",
+               "git add -A",
+               "git config user.email 'tdeps@example.com'",
+               "git config user.name 'tdeps'",
+               "git commit -a -m \"Initial Commit\""],
+    ErlLibs = filename:join(Dir, "libs"),
+    ok = apply_cmds(GitCmds, [{dir, "repo/c"}]),
+    Env = [
+        {"REBAR_DEPS_PREFER_LIBS", "1"},
+        {"ERL_LIBS", ErlLibs}
+    ],
+
+    {ok, _} = retest_sh:run("./rebar -v get-deps", [{env, Env}]),
+    {ok, _} = retest_sh:run("./rebar -v compile", [{env, Env}]),
+    ok.
+
+%%
+%% 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/src/rebar.erl b/src/rebar.erl
index 2fceb19..888f80d 100644
--- a/src/rebar.erl
+++ b/src/rebar.erl
@@ -284,7 +284,11 @@
                       {"freebsd", compile, "c_src/freebsd_tweaks.sh"},
                       {eunit, "touch file2.out"},
                       {compile, "touch postcompile.out"}]}
-       ]).
+       ]),
+    ?CONSOLE(
+       "Environment variables:~n"
+       "  REBAR_DEPS_PREFER_LIBS to look for dependecies in system libs prior fetching.~n"
+       "~n", []).
 
 %%
 %% Parse command line arguments using getopt and also filtering out any
diff --git a/src/rebar_deps.erl b/src/rebar_deps.erl
index a6e5b27..995ce97 100644
--- a/src/rebar_deps.erl
+++ b/src/rebar_deps.erl
@@ -58,16 +58,19 @@
     %% used globally since it will be set on the first time through here
     Config1 = set_shared_deps_dir(Config, get_shared_deps_dir(Config, [])),
 
+    %% Check whether user forced deps resolution via system wide libs
+    Config2 = set_deps_prefer_libs(Config1, get_deps_prefer_libs(Config1, undefined)),
+
     %% Get the list of deps for the current working directory and identify those
     %% deps that are available/present.
-    Deps = rebar_config:get_local(Config1, deps, []),
-    {Config2, {AvailableDeps, MissingDeps}} = find_deps(Config1, find, Deps),
+    Deps = rebar_config:get_local(Config2, deps, []),
+    {Config3, {AvailableDeps, MissingDeps}} = find_deps(Config2, find, Deps),
 
     ?DEBUG("Available deps: ~p\n", [AvailableDeps]),
     ?DEBUG("Missing deps  : ~p\n", [MissingDeps]),
 
     %% Add available deps to code path
-    Config3 = update_deps_code_path(Config2, AvailableDeps),
+    Config4 = update_deps_code_path(Config3, AvailableDeps),
 
     %% Filtering out 'raw' dependencies so that no commands other than
     %% deps-related can be executed on their directories.
@@ -83,8 +86,8 @@
                           fun(D, Acc) ->
                                   rebar_config:set_skip_dir(Acc, D#dep.dir)
                           end,
-                          Config3,
-                          collect_deps(rebar_utils:get_cwd(), Config3)),
+                          Config4,
+                          collect_deps(rebar_utils:get_cwd(), Config4)),
             %% Return the empty list, as we don't want anything processed before
             %% us.
             {ok, NewConfig, []};
@@ -97,12 +100,12 @@
             %% 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
+                case rebar_config:get_global(Config4, skip_deps, false) of
                     "true" ->
                         lists:foldl(
                           fun(#dep{dir = Dir}, C) ->
                                   rebar_config:set_skip_dir(C, Dir)
-                          end, Config3, AvailableDeps);
+                          end, Config4, AvailableDeps);
                     Apps when is_list(Apps) ->
                         SkipApps = [list_to_atom(App) ||
                                        App <- string:tokens(Apps, ",")],
@@ -112,9 +115,9 @@
                                       true -> rebar_config:set_skip_dir(C, Dir);
                                       false -> C
                                   end
-                          end, Config3, AvailableDeps);
+                          end, Config4, AvailableDeps);
                     _ ->
-                        Config3
+                        Config4
                 end,
 
             %% Return all the available dep directories for process
@@ -254,7 +257,9 @@
        "  ~p~n"
        "  ~p~n"
        "Valid command line options:~n"
-       "  deps_dir=\"deps\" (override default or rebar.config deps_dir)~n",
+       "  deps_dir=\"deps\" (override default or rebar.config deps_dir)~n"
+       "Environment variables:~n"
+       "  REBAR_DEPS_PREFER_LIBS to look for dependecies in system libs prior fetching.~n",
        [
         Description,
         {deps_dir, "deps"},
@@ -302,6 +307,18 @@
 get_shared_deps_dir(Config, Default) ->
     rebar_config:get_xconf(Config, deps_dir, Default).
 
+set_deps_prefer_libs(Config, undefined) ->
+    DepsPreferLibs = case os:getenv("REBAR_DEPS_PREFER_LIBS") of
+        false -> false;
+        _ -> true
+    end,
+    rebar_config:set_xconf(Config, deps_prefer_libs, DepsPreferLibs);
+set_deps_prefer_libs(Config, _DepsPreferLibs) ->
+    Config.
+
+get_deps_prefer_libs(Config, Default) ->
+    rebar_config:get_xconf(Config, deps_prefer_libs, Default).
+
 get_deps_dir(Config) ->
     get_deps_dir(Config, "").
 
@@ -378,9 +395,15 @@
     %% e.g. {git, "https://github.com/mochi/mochiweb.git", "HEAD"}
     %% Deps with a source must be found (or fetched) locally.
     %% Those without a source may be satisfied from lib dir (get_lib_dir).
-    find_dep(Config, Dep, Dep#dep.source).
+    DepsPreferLibs = get_deps_prefer_libs(Config, false),
+    Mode = case {Dep#dep.source, DepsPreferLibs} of
+        {undefined, _DepsPreferLibs} -> maybe_in_lib;
+        {_DepSource, true} -> maybe_in_lib;
+        {_DepSource, false} -> local_only
+    end,
+    find_dep(Config, Dep, Mode).
 
-find_dep(Config, Dep, undefined) ->
+find_dep(Config, Dep, maybe_in_lib) ->
     %% 'source' is undefined.  If Dep is not satisfied locally,
     %% go ahead and find it amongst the lib_dir's.
     case find_dep_in_dir(Config, Dep, get_deps_dir(Config, Dep#dep.app)) of
@@ -389,7 +412,7 @@
         {Config1, {missing, _}} ->
             find_dep_in_dir(Config1, Dep, get_lib_dir(Dep#dep.app))
     end;
-find_dep(Config, Dep, _Source) ->
+find_dep(Config, Dep, local_only) ->
     %% _Source is defined.  Regardless of what it is, we must find it
     %% locally satisfied or fetch it from the original source
     %% into the project's deps