summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/rebar.app.src2
-rw-r--r--src/rebar3.erl5
-rw-r--r--src/rebar_agent.erl22
-rw-r--r--src/rebar_app_discover.erl2
-rw-r--r--src/rebar_core.erl12
-rw-r--r--src/rebar_dir.erl6
-rw-r--r--src/rebar_erlc_compiler.erl7
-rw-r--r--src/rebar_file_utils.erl113
-rw-r--r--src/rebar_git_resource.erl29
-rw-r--r--src/rebar_hooks.erl47
-rw-r--r--src/rebar_pkg_resource.erl3
-rw-r--r--src/rebar_plugins.erl2
-rw-r--r--src/rebar_prv_common_test.erl41
-rw-r--r--src/rebar_prv_compile.erl13
-rw-r--r--src/rebar_prv_cover.erl20
-rw-r--r--src/rebar_prv_dialyzer.erl10
-rw-r--r--src/rebar_prv_install_deps.erl221
-rw-r--r--src/rebar_prv_plugins_upgrade.erl5
-rw-r--r--src/rebar_prv_release.erl29
-rw-r--r--src/rebar_prv_relup.erl29
-rw-r--r--src/rebar_prv_shell.erl12
-rw-r--r--src/rebar_prv_tar.erl24
-rw-r--r--src/rebar_prv_update.erl3
-rw-r--r--src/rebar_relx.erl69
-rw-r--r--src/rebar_utils.erl59
25 files changed, 461 insertions, 324 deletions
diff --git a/src/rebar.app.src b/src/rebar.app.src
index 5abb643..e5d56bb 100644
--- a/src/rebar.app.src
+++ b/src/rebar.app.src
@@ -3,7 +3,7 @@
{application, rebar,
[{description, "Rebar: Erlang Build Tool"},
- {vsn, "3.0.0-alpha-6"},
+ {vsn, "3.0.0-beta-1"},
{modules, []},
{registered, []},
{applications, [kernel,
diff --git a/src/rebar3.erl b/src/rebar3.erl
index 5c0559f..a797c46 100644
--- a/src/rebar3.erl
+++ b/src/rebar3.erl
@@ -272,4 +272,7 @@ start_and_load_apps() ->
application:start(asn1),
application:start(public_key),
application:start(ssl),
- inets:start().
+ inets:start(),
+ inets:start(httpc, [{profile, rebar}]),
+ rebar_utils:set_httpc_options().
+
diff --git a/src/rebar_agent.erl b/src/rebar_agent.erl
index 0432fb8..dc45dcf 100644
--- a/src/rebar_agent.erl
+++ b/src/rebar_agent.erl
@@ -20,17 +20,17 @@ do(Namespace, Command) when is_atom(Namespace), is_atom(Command) ->
gen_server:call(?MODULE, {cmd, Namespace, Command}, infinity).
init(State) ->
- {ok, Cwd} = file:get_cwd(),
+ Cwd = rebar_dir:get_cwd(),
{ok, #state{state=State, cwd=Cwd}}.
handle_call({cmd, Command}, _From, State=#state{state=RState, cwd=Cwd}) ->
MidState = maybe_show_warning(State),
{Res, NewRState} = run(default, Command, RState, Cwd),
- {reply, Res, MidState#state{state=NewRState}};
+ {reply, Res, MidState#state{state=NewRState}, hibernate};
handle_call({cmd, Namespace, Command}, _From, State = #state{state=RState, cwd=Cwd}) ->
MidState = maybe_show_warning(State),
{Res, NewRState} = run(Namespace, Command, RState, Cwd),
- {reply, Res, MidState#state{state=NewRState}};
+ {reply, Res, MidState#state{state=NewRState}, hibernate};
handle_call(_Call, _From, State) ->
{noreply, State}.
@@ -48,8 +48,8 @@ terminate(_Reason, _State) ->
run(Namespace, Command, RState, Cwd) ->
try
- case file:get_cwd() of
- {ok, Cwd} ->
+ case rebar_dir:get_cwd() of
+ Cwd ->
Args = [atom_to_list(Namespace), atom_to_list(Command)],
CmdState0 = refresh_state(RState, Cwd),
CmdState1 = rebar_state:set(CmdState0, task, atom_to_list(Command)),
@@ -87,16 +87,22 @@ refresh_paths(RState) ->
%% make sure to never reload self; halt()s the VM
) -- [filename:dirname(code:which(?MODULE))],
%% Similar to rebar_utils:update_code/1, but also forces a reload
- %% of used modules.
+ %% of used modules. Also forces to reload all of ebin/ instead
+ %% of just the modules in the .app file, because 'extra_src_dirs'
+ %% allows to load and compile files that are not to be kept
+ %% in the app file.
lists:foreach(fun(Path) ->
Name = filename:basename(Path, "/ebin"),
+ Files = filelib:wildcard(filename:join([Path, "*.beam"])),
+ Modules = [list_to_atom(filename:basename(F, ".beam"))
+ || F <- Files],
App = list_to_atom(Name),
application:load(App),
case application:get_key(App, modules) of
undefined ->
code:add_patha(Path),
ok;
- {ok, Modules} ->
+ {ok, _} ->
?DEBUG("reloading ~p from ~s", [Modules, Path]),
code:replace_path(Name, Path),
[begin code:purge(M), code:delete(M), code:load_file(M) end
@@ -108,5 +114,5 @@ refresh_state(RState, _Dir) ->
lists:foldl(
fun(F, State) -> F(State) end,
rebar3:init_config(),
- [fun(S) -> rebar_state:current_profiles(S, rebar_state:current_profiles(RState)) end]
+ [fun(S) -> rebar_state:apply_profiles(S, rebar_state:current_profiles(RState)) end]
).
diff --git a/src/rebar_app_discover.erl b/src/rebar_app_discover.erl
index 2eb9d91..9c4a5ff 100644
--- a/src/rebar_app_discover.erl
+++ b/src/rebar_app_discover.erl
@@ -139,7 +139,7 @@ app_dir(AppFile) ->
-spec create_app_info(file:name(), file:name()) -> rebar_app_info:t() | {error, term()}.
create_app_info(AppDir, AppFile) ->
- [{application, AppName, AppDetails}] = rebar_file_utils:try_consult(AppFile),
+ [{application, AppName, AppDetails}] = rebar_config:consult_app_file(AppFile),
AppVsn = proplists:get_value(vsn, AppDetails),
Applications = proplists:get_value(applications, AppDetails, []),
IncludedApplications = proplists:get_value(included_applications, AppDetails, []),
diff --git a/src/rebar_core.erl b/src/rebar_core.erl
index b1647f0..f097429 100644
--- a/src/rebar_core.erl
+++ b/src/rebar_core.erl
@@ -128,9 +128,15 @@ do([ProviderName | Rest], State) ->
{error, Error}
catch
error:undef ->
- %% This should really only happen if a plugin provider doesn't export do/1
- ?DEBUG("Undefined call to provider's do function:~n~p", [erlang:get_stacktrace()]),
- ?PRV_ERROR({bad_provider_namespace, ProviderName});
+ Stack = erlang:get_stacktrace(),
+ case Stack of
+ [{ProviderName, do, [_], _}|_] ->
+ %% This should really only happen if a plugin provider doesn't export do/1
+ ?DEBUG("Undefined call to provider's do/1 function:~n~p", [Stack]),
+ ?PRV_ERROR({bad_provider_namespace, ProviderName});
+ _ -> % re-raise
+ erlang:raise(error, undef, Stack)
+ end;
error:{badrecord,provider} ->
{error, ProviderName}
end.
diff --git a/src/rebar_dir.erl b/src/rebar_dir.erl
index e226633..7af94ea 100644
--- a/src/rebar_dir.erl
+++ b/src/rebar_dir.erl
@@ -100,7 +100,11 @@ local_cache_dir(Dir) ->
get_cwd() ->
{ok, Dir} = file:get_cwd(),
- Dir.
+ %% On windows cwd may return capital letter for drive,
+ %% for example C:/foobar. But as said in http://www.erlang.org/doc/man/filename.html#join-1
+ %% filename:join/1,2 anyway will convert drive-letter to lowercase, so we have to "internalize"
+ %% cwd as soon as it possible.
+ filename:join([Dir]).
template_globals(State) ->
filename:join([global_config_dir(State), "templates", "globals"]).
diff --git a/src/rebar_erlc_compiler.erl b/src/rebar_erlc_compiler.erl
index b9072a3..87cf352 100644
--- a/src/rebar_erlc_compiler.erl
+++ b/src/rebar_erlc_compiler.erl
@@ -404,10 +404,13 @@ target_base(OutDir, Source) ->
-spec compile_mib(file:filename(), file:filename(),
rebar_state:t()) -> 'ok'.
compile_mib(Source, Target, Config) ->
+ Dir = rebar_state:dir(Config),
ok = filelib:ensure_dir(Target),
- ok = filelib:ensure_dir(filename:join("include", "dummy.hrl")),
- Opts = [{outdir, "priv/mibs"}, {i, ["priv/mibs"]}] ++
+ ok = filelib:ensure_dir(filename:join([Dir, "include", "dummy.hrl"])),
+ Opts = [{outdir, filename:join([Dir, "priv", "mibs"])}
+ ,{i, [filename:join([Dir, "priv", "mibs"])]}] ++
rebar_state:get(Config, mib_opts, []),
+
case snmpc:compile(Source, Opts) of
{ok, _} ->
Mib = filename:rootname(Target),
diff --git a/src/rebar_file_utils.erl b/src/rebar_file_utils.erl
index ad30172..b4cdc27 100644
--- a/src/rebar_file_utils.erl
+++ b/src/rebar_file_utils.erl
@@ -36,10 +36,14 @@
write_file_if_contents_differ/2,
system_tmpdir/0,
system_tmpdir/1,
- reset_dir/1]).
+ reset_dir/1,
+ touch/1]).
-include("rebar.hrl").
+
-include_lib("providers/include/providers.hrl").
+-include_lib("kernel/include/file.hrl").
+
%% ===================================================================
%% Public API
@@ -71,9 +75,40 @@ symlink_or_copy(Source, Target) ->
{error, eexist} ->
ok;
{error, _} ->
- cp_r([Source], Target)
+ case os:type() of
+ {win32, _} ->
+ S = unicode:characters_to_list(Source),
+ T = unicode:characters_to_list(Target),
+ case filelib:is_dir(S) of
+ true ->
+ win32_symlink(S, T);
+ false ->
+ cp_r([S], T)
+ end;
+ _ ->
+ case filelib:is_dir(Target) of
+ true ->
+ ok;
+ false ->
+ cp_r([Source], Target)
+ end
+ end
+ end.
+
+win32_symlink(Source, Target) ->
+ Res = rebar_utils:sh(
+ ?FMT("cmd /c mklink /j \"~s\" \"~s\"",
+ [filename:nativename(Target), filename:nativename(Source)]),
+ [{use_stdout, false}, return_on_error]),
+ case win32_ok(Res) of
+ true -> ok;
+ false ->
+ {error, lists:flatten(
+ io_lib:format("Failed to symlink ~s to ~s~n",
+ [Source, Target]))}
end.
+
%% @doc Remove files and directories.
%% Target is a single filename, directoryname or wildcard expression.
-spec rm_rf(string()) -> 'ok'.
@@ -120,21 +155,32 @@ mv(Source, Dest) ->
[{use_stdout, false}, abort_on_error]),
ok;
{win32, _} ->
- {ok, R} = rebar_utils:sh(
- ?FMT("move /y \"~s\" \"~s\" 1> nul",
- [filename:nativename(Source),
- filename:nativename(Dest)]),
+ Cmd = case filelib:is_dir(Source) of
+ true ->
+ ?FMT("robocopy /move /s \"~s\" \"~s\" 1> nul",
+ [filename:nativename(Source),
+ filename:nativename(Dest)]);
+ false ->
+ ?FMT("robocopy /move /s \"~s\" \"~s\" \"~s\" 1> nul",
+ [filename:nativename(filename:dirname(Source)),
+ filename:nativename(Dest),
+ filename:basename(Source)])
+ end,
+ Res = rebar_utils:sh(Cmd,
[{use_stdout, false}, return_on_error]),
- case R of
- [] ->
- ok;
- _ ->
+ case win32_ok(Res) of
+ true -> ok;
+ false ->
{error, lists:flatten(
io_lib:format("Failed to move ~s to ~s~n",
[Source, Dest]))}
end
end.
+win32_ok({ok, _}) -> true;
+win32_ok({error, {Rc, _}}) when Rc<9; Rc=:=16 -> true;
+win32_ok(_) -> false.
+
delete_each([]) ->
ok;
delete_each([File | Rest]) ->
@@ -186,6 +232,17 @@ reset_dir(Path) ->
%% recreate the directory
filelib:ensure_dir(filename:join([Path, "dummy.beam"])).
+
+%% Linux touch but using erlang functions to work in bot *nix os and
+%% windows
+-spec touch(Path) -> ok | {error, Reason} when
+ Path :: file:name(),
+ Reason :: file:posix().
+touch(Path) ->
+ {ok, A} = file:read_file_info(Path),
+ ok = file:write_file_info(Path, A#file_info{mtime = calendar:local_time(),
+ atime = calendar:local_time()}).
+
%% ===================================================================
%% Internal functions
%% ===================================================================
@@ -198,28 +255,36 @@ delete_each_dir_win32([Dir | Rest]) ->
delete_each_dir_win32(Rest).
xcopy_win32(Source,Dest)->
- {ok, R} = rebar_utils:sh(
- ?FMT("xcopy \"~s\" \"~s\" /q /y /e 2> nul",
- [filename:nativename(Source), filename:nativename(Dest)]),
+ %% "xcopy \"~s\" \"~s\" /q /y /e 2> nul", Chanegd to robocopy to
+ %% handle long names. May have issues with older windows.
+ Cmd = case filelib:is_dir(Source) of
+ true ->
+ ?FMT("robocopy \"~s\" \"~s\" /e /is 1> nul",
+ [filename:nativename(Source),
+ filename:nativename(Dest)]);
+ false ->
+ ?FMT("robocopy \"~s\" \"~s\" \"~s\" /e /is 1> nul",
+ [filename:nativename(filename:dirname(Source)),
+ filename:nativename(Dest),
+ filename:basename(Source)])
+ end,
+ Res = rebar_utils:sh(Cmd,
[{use_stdout, false}, return_on_error]),
- case length(R) > 0 of
- %% when xcopy fails, stdout is empty and and error message is printed
- %% to stderr (which is redirected to nul)
- true -> ok;
- false ->
- {error, lists:flatten(
- io_lib:format("Failed to xcopy from ~s to ~s~n",
- [Source, Dest]))}
+ case win32_ok(Res) of
+ true -> ok;
+ false ->
+ {error, lists:flatten(
+ io_lib:format("Failed to copy ~s to ~s~n",
+ [Source, Dest]))}
end.
cp_r_win32({true, SourceDir}, {true, DestDir}) ->
%% from directory to directory
- SourceBase = filename:basename(SourceDir),
- ok = case file:make_dir(filename:join(DestDir, SourceBase)) of
+ ok = case file:make_dir(DestDir) of
{error, eexist} -> ok;
Other -> Other
end,
- ok = xcopy_win32(SourceDir, filename:join(DestDir, SourceBase));
+ ok = xcopy_win32(SourceDir, DestDir);
cp_r_win32({false, Source} = S,{true, DestDir}) ->
%% from file to directory
cp_r_win32(S, {false, filename:join(DestDir, filename:basename(Source))});
diff --git a/src/rebar_git_resource.erl b/src/rebar_git_resource.erl
index 2d83579..e2f3f69 100644
--- a/src/rebar_git_resource.erl
+++ b/src/rebar_git_resource.erl
@@ -68,6 +68,7 @@ compare_url(Dir, Url) ->
CurrentUrl1 = string:strip(string:strip(CurrentUrl, both, $\n), both, $\r),
ParsedUrl = parse_git_url(Url),
ParsedCurrentUrl = parse_git_url(CurrentUrl1),
+ ?DEBUG("Comparing git url ~p with ~p", [ParsedUrl, ParsedCurrentUrl]),
ParsedCurrentUrl =:= ParsedUrl.
parse_git_url("git@" ++ HostPath) ->
@@ -76,6 +77,9 @@ parse_git_url("git@" ++ HostPath) ->
parse_git_url("git://" ++ HostPath) ->
[Host | Path] = string:tokens(HostPath, "/"),
{Host, filename:rootname(filename:join(Path), ".git")};
+parse_git_url("http://" ++ HostPath) ->
+ [Host | Path] = string:tokens(HostPath, "/"),
+ {Host, filename:rootname(filename:join(Path), ".git")};
parse_git_url("https://" ++ HostPath) ->
[Host | Path] = string:tokens(HostPath, "/"),
{Host, filename:rootname(filename:join(Path), ".git")}.
@@ -109,28 +113,23 @@ download(Dir, {git, Url, Rev}, _State) ->
rebar_utils:sh(?FMT("git checkout -q ~s", [Rev]), [{cd, Dir}]).
make_vsn(Dir) ->
- {ok, Cwd} = file:get_cwd(),
- try
- ok = file:set_cwd(Dir),
- {Vsn, RawRef, RawCount} = collect_default_refcount(),
- {plain, build_vsn_string(Vsn, RawRef, RawCount)}
- after
- file:set_cwd(Cwd)
- end.
+ {Vsn, RawRef, RawCount} = collect_default_refcount(Dir),
+ {plain, build_vsn_string(Vsn, RawRef, RawCount)}.
%% Internal functions
-collect_default_refcount() ->
+collect_default_refcount(Dir) ->
%% Get the tag timestamp and minimal ref from the system. The
%% timestamp is really important from an ordering perspective.
AbortMsg1 = "Getting log of git dependency failed in " ++ rebar_dir:get_cwd(),
{ok, String} =
rebar_utils:sh("git log -n 1 --pretty=format:\"%h\n\" ",
[{use_stdout, false},
+ {cd, Dir},
{debug_abort_on_error, AbortMsg1}]),
RawRef = string:strip(String, both, $\n),
- {Tag, TagVsn} = parse_tags(),
+ {Tag, TagVsn} = parse_tags(Dir),
{ok, RawCount} =
case Tag of
undefined ->
@@ -140,7 +139,7 @@ collect_default_refcount() ->
{debug_abort_on_error, AbortMsg2}]),
rebar_utils:line_count(PatchLines);
_ ->
- get_patch_count(Tag)
+ get_patch_count(Dir, Tag)
end,
{TagVsn, RawRef, RawCount}.
@@ -158,8 +157,8 @@ build_vsn_string(Vsn, RawRef, Count) ->
integer_to_list(Count), RefTag]))
end.
-get_patch_count(RawRef) ->
- AbortMsg = "Getting rev-list of git dep failed in " ++ rebar_dir:get_cwd(),
+get_patch_count(Dir, RawRef) ->
+ AbortMsg = "Getting rev-list of git dep failed in " ++ Dir,
Ref = re:replace(RawRef, "\\s", "", [global]),
Cmd = io_lib:format("git rev-list ~s..HEAD",
[Ref]),
@@ -169,10 +168,10 @@ get_patch_count(RawRef) ->
rebar_utils:line_count(PatchLines).
-parse_tags() ->
+parse_tags(Dir) ->
%% Don't abort on error, we want the bad return to be turned into 0.0.0
case rebar_utils:sh("git log --oneline --no-walk --tags --decorate",
- [{use_stdout, false}, return_on_error]) of
+ [{use_stdout, false}, return_on_error, {cd, Dir}]) of
{error, _} ->
{undefined, "0.0.0"};
{ok, Line} ->
diff --git a/src/rebar_hooks.erl b/src/rebar_hooks.erl
index 56c4e91..857336c 100644
--- a/src/rebar_hooks.erl
+++ b/src/rebar_hooks.erl
@@ -14,12 +14,21 @@ run_all_hooks(Dir, Type, Command, Providers, State) ->
run_hooks(Dir, Type, Command, State).
run_provider_hooks(Dir, Type, Command, Providers, State) ->
+ case rebar_state:get(State, provider_hooks, []) of
+ [] ->
+ ok;
+ AllHooks ->
+ TypeHooks = proplists:get_value(Type, AllHooks, []),
+ run_provider_hooks(Dir, Type, Command, Providers, TypeHooks, State)
+ end.
+
+run_provider_hooks(_Dir, _Type, _Command, _Providers, [], _State) ->
+ ok;
+run_provider_hooks(Dir, Type, Command, Providers, TypeHooks, State) ->
PluginDepsPaths = rebar_state:code_paths(State, all_plugin_deps),
code:add_pathsa(PluginDepsPaths),
Providers1 = rebar_state:providers(State),
State1 = rebar_state:providers(rebar_state:dir(State, Dir), Providers++Providers1),
- AllHooks = rebar_state:get(State1, provider_hooks, []),
- TypeHooks = proplists:get_value(Type, AllHooks, []),
HookProviders = proplists:get_all_values(Command, TypeHooks),
case rebar_core:do(HookProviders, State1) of
@@ -58,24 +67,24 @@ format_error({bad_provider, Type, Command, Name}) ->
%% ERL = ERLANG_ROOT_DIR/bin/erl
%% ERLC = ERLANG_ROOT_DIR/bin/erl
%%
+run_hooks(Dir, pre, Command, State) ->
+ run_hooks(Dir, pre_hooks, Command, State);
+run_hooks(Dir, post, Command, State) ->
+ run_hooks(Dir, post_hooks, Command, State);
run_hooks(Dir, Type, Command, State) ->
- Hooks = case Type of
- pre ->
- rebar_state:get(State, pre_hooks, []);
- post ->
- rebar_state:get(State, post_hooks, []);
- _ ->
- []
- end,
-
- Env = create_env(State),
- lists:foreach(fun({_, C, _}=Hook) when C =:= Command ->
- apply_hook(Dir, Env, Hook);
- ({C, _}=Hook) when C =:= Command ->
- apply_hook(Dir, Env, Hook);
- (_) ->
- continue
- end, Hooks).
+ case rebar_state:get(State, Type, []) of
+ [] ->
+ ok;
+ Hooks ->
+ Env = create_env(State),
+ lists:foreach(fun({_, C, _}=Hook) when C =:= Command ->
+ apply_hook(Dir, Env, Hook);
+ ({C, _}=Hook) when C =:= Command ->
+ apply_hook(Dir, Env, Hook);
+ (_) ->
+ continue
+ end, Hooks)
+ end.
apply_hook(Dir, Env, {Arch, Command, Hook}) ->
case rebar_utils:is_arch(Arch) of
diff --git a/src/rebar_pkg_resource.erl b/src/rebar_pkg_resource.erl
index 59ce0dc..450ff1e 100644
--- a/src/rebar_pkg_resource.erl
+++ b/src/rebar_pkg_resource.erl
@@ -95,7 +95,8 @@ make_vsn(_) ->
request(Url, ETag) ->
case httpc:request(get, {Url, [{"if-none-match", ETag} || ETag =/= false]},
[{relaxed, true}],
- [{body_format, binary}]) of
+ [{body_format, binary}],
+ rebar) of
{ok, {{_Version, 200, _Reason}, Headers, Body}} ->
?DEBUG("Successfully downloaded ~s", [Url]),
{"etag", ETag1} = lists:keyfind("etag", 1, Headers),
diff --git a/src/rebar_plugins.erl b/src/rebar_plugins.erl
index 7e12324..3e855de 100644
--- a/src/rebar_plugins.erl
+++ b/src/rebar_plugins.erl
@@ -63,7 +63,7 @@ handle_plugins(Profile, Plugins, State, Upgrade) ->
handle_plugin(Profile, Plugin, State, Upgrade) ->
try
- {ok, Apps, State2} = rebar_prv_install_deps:handle_deps(Profile, State, [Plugin], Upgrade),
+ {Apps, State2} = rebar_prv_install_deps:handle_deps_as_profile(Profile, State, [Plugin], Upgrade),
{no_cycle, Sorted} = rebar_prv_install_deps:find_cycles(Apps),
ToBuild = rebar_prv_install_deps:cull_compile(Sorted, []),
diff --git a/src/rebar_prv_common_test.erl b/src/rebar_prv_common_test.erl
index 710922a..2b024cf 100644
--- a/src/rebar_prv_common_test.erl
+++ b/src/rebar_prv_common_test.erl
@@ -105,14 +105,18 @@ run_test_verbose(Opts) -> handle_results(ct:run_test(Opts)).
run_test_quiet(Opts) ->
Pid = self(),
+ Ref = erlang:make_ref(),
LogDir = proplists:get_value(logdir, Opts),
- erlang:spawn_monitor(fun() ->
+ {_, Monitor} = erlang:spawn_monitor(fun() ->
{ok, F} = file:open(filename:join([LogDir, "ct.latest.log"]),
[write]),
true = group_leader(F, self()),
- Pid ! ct:run_test(Opts)
+ Pid ! {Ref, ct:run_test(Opts)}
end),
- receive Result -> handle_quiet_results(Opts, Result) end.
+ receive
+ {Ref, Result} -> handle_quiet_results(Opts, Result);
+ {'DOWN', Monitor, _, _, Reason} -> handle_results(?PRV_ERROR(Reason))
+ end.
handle_results(Results) when is_list(Results) ->
Result = lists:foldl(fun sum_results/2, {0, 0, {0,0}}, Results),
@@ -132,8 +136,6 @@ sum_results({Passed, Failed, {UserSkipped, AutoSkipped}},
handle_quiet_results(_, {error, _} = Result) ->
handle_results(Result);
-handle_quiet_results(_, {'DOWN', _, _, _, Reason}) ->
- handle_results(?PRV_ERROR(Reason));
handle_quiet_results(CTOpts, Results) when is_list(Results) ->
_ = [format_result(Result) || Result <- Results],
case handle_results(Results) of
@@ -345,23 +347,26 @@ reduce_path([_|Acc], [".."|Rest]) -> reduce_path(Acc, Rest);
reduce_path([], [".."|Rest]) -> reduce_path([], Rest);
reduce_path(Acc, [Component|Rest]) -> reduce_path([Component|Acc], Rest).
-remove_links(Path) ->
- case ec_file:is_dir(Path) of
- false -> ok;
- true -> remove_links1(Path)
- end.
-remove_links1(Path) ->
+remove_links(Path) ->
+ IsDir = ec_file:is_dir(Path),
case ec_file:is_symlink(Path) of
- true ->
- file:delete(Path);
- false ->
- lists:foreach(fun(ChildPath) ->
- remove_links(ChildPath)
- end, sub_dirs(Path))
+ true when IsDir ->
+ delete_dir_link(Path);
+ false when IsDir ->
+ lists:foreach(fun(ChildPath) ->
+ remove_links(ChildPath)
+ end, dir_entries(Path));
+ _ -> file:delete(Path)
end.
-sub_dirs(Path) ->
+delete_dir_link(Path) ->
+ case os:type() of
+ {unix, _} -> file:delete(Path);
+ {win32, _} -> file:del_dir(Path)
+ end.
+
+dir_entries(Path) ->
{ok, SubDirs} = file:list_dir(Path),
[filename:join(Path, SubDir) || SubDir <- SubDirs].
diff --git a/src/rebar_prv_compile.erl b/src/rebar_prv_compile.erl
index 6eb8a4f..25d5193 100644
--- a/src/rebar_prv_compile.erl
+++ b/src/rebar_prv_compile.erl
@@ -126,7 +126,20 @@ copy_app_dirs(State, OldAppDir, AppDir) ->
false ->
ok
end,
+
filelib:ensure_dir(filename:join(AppDir, "dummy")),
+
+ %% link or copy mibs if it exists
+ case filelib:is_dir(filename:join(OldAppDir, "mibs")) of
+ true ->
+ %% If mibs exist it means we must ensure priv exists.
+ %% mibs files are compiled to priv/mibs/
+ filelib:ensure_dir(filename:join([OldAppDir, "priv", "dummy"])),
+ symlink_or_copy(OldAppDir, AppDir, "mibs");
+ false ->
+ ok
+ end,
+
%% link to src_dirs to be adjacent to ebin is needed for R15 use of cover/xref
SrcDirs = rebar_dir:all_src_dirs(State, ["src"], ["test"]),
[symlink_or_copy(OldAppDir, AppDir, Dir) || Dir <- ["priv", "include"] ++ SrcDirs];
diff --git a/src/rebar_prv_cover.erl b/src/rebar_prv_cover.erl
index 6c115b6..8c26521 100644
--- a/src/rebar_prv_cover.erl
+++ b/src/rebar_prv_cover.erl
@@ -337,16 +337,24 @@ write_coverdata(State, Task) ->
?WARN("Cover data export failed: ~p", [Reason])
end.
-verbose(State) ->
+command_line_opts(State) ->
{Opts, _} = rebar_state:command_parsed_args(State),
- case proplists:get_value(verbose, Opts, missing) of
- missing -> rebar_state:get(State, cover_print_enabled, false);
- Else -> Else
+ Opts.
+
+config_opts(State) ->
+ rebar_state:get(State, cover_opts, []).
+
+verbose(State) ->
+ Command = proplists:get_value(verbose, command_line_opts(State), undefined),
+ Config = proplists:get_value(verbose, config_opts(State), undefined),
+ case {Command, Config} of
+ {undefined, undefined} -> false;
+ {undefined, Verbose} -> Verbose;
+ {Verbose, _} -> Verbose
end.
cover_dir(State) ->
- rebar_state:get(State, cover_data_dir, filename:join([rebar_dir:base_dir(State),
- "cover"])).
+ filename:join([rebar_dir:base_dir(State), "cover"]).
cover_opts(_State) ->
[{reset, $r, "reset", boolean, help(reset)},
diff --git a/src/rebar_prv_dialyzer.erl b/src/rebar_prv_dialyzer.erl
index 15f1dac..1cf7b71 100644
--- a/src/rebar_prv_dialyzer.erl
+++ b/src/rebar_prv_dialyzer.erl
@@ -72,6 +72,7 @@ short_desc() ->
-spec do(rebar_state:t()) -> {ok, rebar_state:t()} | {error, string()}.
do(State) ->
+ maybe_fix_env(),
?INFO("Dialyzer starting, this may take a while...", []),
code:add_pathsa(rebar_state:code_paths(State, all_deps)),
Plt = get_plt(State),
@@ -91,6 +92,13 @@ do(State) ->
rebar_utils:cleanup_code_path(rebar_state:code_paths(State, default))
end.
+%% This is used to workaround dialyzer quirk discussed here
+%% https://github.com/rebar/rebar3/pull/489#issuecomment-107953541
+%% Dialyzer gets default plt location wrong way by peeking HOME environment
+%% variable which usually is not defined on Windows.
+maybe_fix_env() ->
+ os:putenv("DIALYZER_PLT", filename:join(rebar_dir:home_dir(), ".dialyzer_plt")).
+
-spec format_error(any()) -> iolist().
format_error({error_processing_apps, Error}) ->
io_lib:format("Error in dialyzing apps: ~s", [Error]);
@@ -380,7 +388,7 @@ run_dialyzer(State, Opts, Output) ->
{check_plt, false} |
Opts],
?DEBUG("Running dialyzer with options: ~p~n", [Opts2]),
- _ = dialyzer:run(Opts2),
+ dialyzer:run(Opts2),
{0, State}
end.
diff --git a/src/rebar_prv_install_deps.erl b/src/rebar_prv_install_deps.erl
index 768d41a..105bbb1 100644
--- a/src/rebar_prv_install_deps.erl
+++ b/src/rebar_prv_install_deps.erl
@@ -35,10 +35,7 @@
-include("rebar.hrl").
-include_lib("providers/include/providers.hrl").
--export([handle_deps/3,
- handle_deps/4,
- handle_deps/5,
-
+-export([handle_deps_as_profile/4,
find_cycles/1,
cull_compile/2]).
@@ -76,8 +73,8 @@ do(State) ->
Profiles = rebar_state:current_profiles(State),
ProjectApps = rebar_state:project_apps(State),
- {Apps, State1} =
- lists:foldl(fun deps_per_profile/2, {[], State}, lists:reverse(Profiles)),
+ Upgrade = rebar_state:get(State, upgrade, false),
+ {Apps, State1} = deps_per_profile(Profiles, Upgrade, State),
State2 = rebar_state:update_all_deps(State1, Apps),
CodePaths = [rebar_app_info:ebin_dir(A) || A <- Apps],
@@ -119,63 +116,77 @@ format_error({cycles, Cycles}) ->
format_error(Reason) ->
io_lib:format("~p", [Reason]).
--spec handle_deps(atom(), rebar_state:t(), list()) ->
- {ok, [rebar_app_info:t()], rebar_state:t()} | {error, string()}.
-handle_deps(Profile, State, Deps) ->
- handle_deps(Profile, State, Deps, false, []).
-
--spec handle_deps(atom(), rebar_state:t(), list(), list() | boolean()) ->
- {ok, [rebar_app_info:t()], rebar_state:t()} | {error, string()}.
-handle_deps(Profile, State, Deps, Upgrade) when is_boolean(Upgrade) ->
- handle_deps(Profile, State, Deps, Upgrade, []);
-handle_deps(Profile, State, Deps, Locks) when is_list(Locks) ->
- Upgrade = rebar_state:get(State, upgrade, false),
- handle_deps(Profile, State, Deps, Upgrade, Locks).
-
--spec handle_deps(atom(), rebar_state:t(), list(), boolean() | {true, binary(), integer()}, list())
- -> {ok, [rebar_app_info:t()], rebar_state:t()} | {error, string()}.
-handle_deps(_Profile, State, [], _, _) ->
- {ok, [], State};
-handle_deps(Profile, State0, Deps, Upgrade, Locks) ->
- %% Split source deps from pkg deps, needed to keep backwards compatibility
- DepsDir = profile_dep_dir(State0, Profile),
-
- {SrcDeps, PkgDeps} = parse_deps(DepsDir, Deps, State0, Locks, 0),
-
- %% Fetch transitive src deps
- {State1, SrcApps, PkgDeps1, Seen} = update_src_deps(Profile, 0, SrcDeps, PkgDeps, []
- ,State0, Upgrade, sets:new(), Locks),
-
- {Solved, State4} =
- case PkgDeps1 of
- [] ->
- {[], State1};
- _ ->
- %% Read in package index and dep graph
- {Packages, Graph} = rebar_state:packages(State1),
- Registry = rebar_packages:registry(State1),
- State2 = rebar_state:packages(rebar_state:registry(State1, Registry)
- ,{Packages, Graph}),
-
- update_pkg_deps(Profile, Packages, PkgDeps1
- ,Graph, Upgrade, Seen, State2, Locks)
- end,
-
- AllDeps = lists:ukeymerge(2
- ,lists:ukeysort(2, SrcApps)
- ,lists:ukeysort(2, Solved)),
-
- {ok, AllDeps, State4}.
+%% Allows other providers to install deps in a given profile
+%% manually, outside of what is provided by rebar3's deps tuple.
+handle_deps_as_profile(Profile, State, Deps, Upgrade) ->
+ Locks = [],
+ Level = 0,
+ DepsDir = profile_dep_dir(State, Profile),
+
+ {SrcDeps, PkgDeps} = parse_deps(DepsDir, Deps, State, Locks, Level),
+ AllSrcProfileDeps = [{Profile, SrcDeps, Locks, Level}],
+ AllPkgProfileDeps = [{Profile, Locks, PkgDeps}],
+ {AllApps, PkgDeps1, Seen, State1} = handle_profile_level(AllSrcProfileDeps, AllPkgProfileDeps, Locks, sets:new(), Upgrade, State),
+
+ handle_profile_pkg_level(PkgDeps1, AllApps, Seen, Upgrade, State1).
+
%% ===================================================================
%% Internal functions
%% ===================================================================
-deps_per_profile(Profile, {Apps, State}) ->
+%% finds all the deps in `{deps, ...}` for each profile provided.
+deps_per_profile(Profiles, Upgrade, State) ->
+ Level = 0,
+ {AllProfileDeps, PkgDeps} = lists:foldl(fun(Profile, {SrcAcc, PkgAcc}) ->
+ {Src, Pkg} = parse_profile_deps(State, Profile, Level),
+ {[Src | SrcAcc], [Pkg | PkgAcc]}
+ end, {[], []}, Profiles),
+ {AllApps, PkgDeps1, Seen, State1} = handle_profile_level(AllProfileDeps, PkgDeps, [], sets:new(), Upgrade, State),
+
+ handle_profile_pkg_level(PkgDeps1, AllApps, Seen, Upgrade, State1).
+
+parse_profile_deps(State, Profile, Level) ->
+ DepsDir = profile_dep_dir(State, Profile),
Locks = rebar_state:get(State, {locks, Profile}, []),
- ProfileDeps = rebar_state:get(State, {deps, Profile}, []),
- {ok, NewApps, NewState} = handle_deps(Profile, State, ProfileDeps, Locks),
- {NewApps++Apps, NewState}.
+ Deps = rebar_state:get(State, {deps, Profile}, []),
+ {SrcDeps, PkgDeps} = parse_deps(DepsDir, Deps, State, Locks, Level),
+ {{Profile, SrcDeps, Locks, Level}, {Profile, Locks, PkgDeps}}.
+
+%% Level-order traversal of all dependencies, across profiles.
+%% If profiles x,y,z are present, then the traversal will go:
+%% x0, y0, z0, x1, y1, z1, ..., xN, yN, zN.
+handle_profile_level([], PkgDeps, SrcApps, Seen, _Upgrade, State) ->
+ {SrcApps, PkgDeps, Seen, State};
+handle_profile_level([{Profile, SrcDeps, Locks, Level} | Rest], PkgDeps, SrcApps, Seen, Upgrade, State) ->
+ {SrcDeps1, PkgDeps1, SrcApps1, State1, Seen1, Locks1} =
+ update_src_deps(Profile, Level, SrcDeps, [], SrcApps
+ ,State, Upgrade, Seen, Locks),
+ SrcDeps2 = case SrcDeps1 of
+ [] -> Rest;
+ _ -> Rest ++ [{Profile, SrcDeps1, Locks1, Level+1}]
+ end,
+ handle_profile_level(SrcDeps2, [{Profile, Locks1, PkgDeps1} | PkgDeps], SrcApps1++SrcApps, sets:union(Seen, Seen1), Upgrade, State1).
+
+handle_profile_pkg_level(PkgDeps, AllApps, Seen, Upgrade, State) ->
+ %% Read in package index and dep graph
+ {Packages, Graph} = rebar_state:packages(State),
+ Registry = rebar_packages:registry(State),
+ State1 = rebar_state:packages(rebar_state:registry(State, Registry)
+ ,{Packages, Graph}),
+
+ lists:foldl(fun({_Profile, _, []}, {AllAcc, StateAcc}) ->
+ {AllAcc, StateAcc};
+ ({Profile1, Locks, PkgDeps2}, {AllAcc, StateAcc}) ->
+ {Solved, StateAcc2} = update_pkg_deps(Profile1, Packages, PkgDeps2
+ ,Graph, Upgrade, Seen, StateAcc, Locks),
+
+ AllDeps = lists:ukeymerge(2
+ ,lists:ukeysort(2, AllAcc)
+ ,lists:ukeysort(2, Solved)),
+
+ {AllDeps, StateAcc2}
+ end, {AllApps, State1}, PkgDeps).
find_cycles(Apps) ->
case rebar_digraph:compile_order(Apps) of
@@ -279,19 +290,15 @@ package_to_app(DepsDir, Packages, {Name, Vsn, Level}, IsLock, State) ->
-spec update_src_deps(atom(), non_neg_integer(), list(), list(), list(), rebar_state:t(), boolean(), sets:set(binary()), list()) -> {rebar_state:t(), list(), list(), sets:set(binary())}.
update_src_deps(Profile, Level, SrcDeps, PkgDeps, SrcApps, State, Upgrade, Seen, Locks) ->
- case lists:foldl(
- fun(AppInfo, {SrcDepsAcc, PkgDepsAcc, SrcAppsAcc, StateAcc, SeenAcc, LocksAcc}) ->
- update_src_dep(AppInfo, Profile, Level,
- SrcDepsAcc, PkgDepsAcc, SrcAppsAcc, StateAcc,
- Upgrade, SeenAcc, Locks, LocksAcc)
- end,
- {[], PkgDeps, SrcApps, State, Seen, Locks},
- rebar_utils:sort_deps(SrcDeps)) of
- {[], NewPkgDeps, NewSrcApps, State1, Seen1, _NewLocks} ->
- {State1, NewSrcApps, NewPkgDeps, Seen1};
- {NewSrcDeps, NewPkgDeps, NewSrcApps, State1, Seen1, NewLocks} ->
- update_src_deps(Profile, Level+1, NewSrcDeps, NewPkgDeps, NewSrcApps, State1, Upgrade, Seen1, NewLocks)
- end.
+ lists:foldl(
+ fun(AppInfo, {SrcDepsAcc, PkgDepsAcc, SrcAppsAcc, StateAcc, SeenAcc, LocksAcc}) ->
+ update_src_dep(AppInfo, Profile, Level,
+ SrcDepsAcc, PkgDepsAcc, SrcAppsAcc, StateAcc,
+ Upgrade, SeenAcc, Locks, LocksAcc)
+ end,
+ {[], PkgDeps, SrcApps, State, Seen, Locks},
+ rebar_utils:sort_deps(SrcDeps)).
+
update_src_dep(AppInfo, Profile, Level, SrcDeps, PkgDeps, SrcApps, State, Upgrade, Seen, BaseLocks, Locks) ->
%% If not seen, add to list of locks to write out
@@ -314,7 +321,7 @@ profile_dep_dir(State, Profile) ->
_ -> rebar_dir:deps_dir(State)
end.
-update_seen_src_dep(AppInfo, Profile, Level, SrcDeps, PkgDeps, SrcApps, State, Upgrade, Seen, BaseLocks, Locks) ->
+update_seen_src_dep(AppInfo, _Profile, _Level, SrcDeps, PkgDeps, SrcApps, State, Upgrade, Seen, BaseLocks, Locks) ->
Name = rebar_app_info:name(AppInfo),
%% If seen from lock file or user requested an upgrade
%% don't print warning about skipping
@@ -323,44 +330,32 @@ update_seen_src_dep(AppInfo, Profile, Level, SrcDeps, PkgDeps, SrcApps, State, U
false when not Upgrade -> warn_skip_deps(AppInfo, State);
true -> ok
end,
- %% scan for app children here if upgrading
- case Upgrade of
- false ->
- {SrcDeps, PkgDeps, SrcApps, State, Seen, Locks};
- true ->
- {NewSrcDeps, NewPkgDeps, NewSrcApps, NewState, NewLocks}
- = handle_dep(AppInfo, Profile, SrcDeps, PkgDeps, SrcApps,
- Level, State, Locks),
- {NewSrcDeps, NewPkgDeps, NewSrcApps, NewState, Seen, NewLocks}
- end.
+ {SrcDeps, PkgDeps, SrcApps, State, Seen, Locks}.
update_unseen_src_dep(AppInfo, Profile, Level, SrcDeps, PkgDeps, SrcApps, State, Upgrade, Seen, Locks) ->
{NewSeen, State1} = maybe_lock(Profile, AppInfo, Seen, State, Level),
{NewSrcDeps, NewPkgDeps, NewSrcApps, State2, NewLocks}
= case Upgrade of
- true ->
- handle_upgrade(AppInfo, Profile, SrcDeps, PkgDeps, SrcApps,
- Level, State1, Locks);
- _ ->
- {_, AppInfo1} = maybe_fetch(AppInfo, Profile, false, Seen, State1),
- handle_dep(AppInfo1, Profile, SrcDeps, PkgDeps, SrcApps,
- Level, State1, Locks)
- end,
+ true ->
+ handle_upgrade(AppInfo, Profile, SrcDeps, PkgDeps, SrcApps,
+ Level, State1, Seen, Locks);
+ _ ->
+ {_, AppInfo1} = maybe_fetch(AppInfo, Profile, false, Seen, State1),
+ handle_dep(AppInfo1, Profile, SrcDeps, PkgDeps, SrcApps,
+ Level, State1, Locks)
+ end,
{NewSrcDeps, NewPkgDeps, NewSrcApps, State2, NewSeen, NewLocks}.
-handle_upgrade(AppInfo, Profile, SrcDeps, PkgDeps, SrcApps, Level, State, Locks) ->
+handle_upgrade(AppInfo, Profile, SrcDeps, PkgDeps, SrcApps, Level, State, Seen, Locks) ->
Name = rebar_app_info:name(AppInfo),
case lists:keyfind(Name, 1, Locks) of
false ->
- case maybe_fetch(AppInfo, Profile, true, sets:new(), State) of
- {true, AppInfo1} ->
- handle_dep(AppInfo1, Profile, SrcDeps, PkgDeps, SrcApps,
- Level, State, Locks);
- {false, AppInfo1} ->
- {[AppInfo1|SrcDeps], PkgDeps, SrcApps, State, Locks}
- end;
+ {_, AppInfo1} = maybe_fetch(AppInfo, Profile, true, Seen, State),
+ handle_dep(AppInfo1, Profile, SrcDeps, PkgDeps, SrcApps,
+ Level, State, Locks);
_StillLocked ->
- {[AppInfo|SrcDeps], PkgDeps, SrcApps, State, Locks}
+ handle_dep(AppInfo, Profile, SrcDeps, PkgDeps, SrcApps,
+ Level, State, Locks)
end.
handle_dep(AppInfo, Profile, SrcDeps, PkgDeps, SrcApps, Level, State, Locks) ->
@@ -414,41 +409,27 @@ maybe_fetch(AppInfo, Profile, Upgrade, Seen, State) ->
false ->
case rebar_app_discover:find_app(AppDir, all) of
false ->
- case already_in_default(AppInfo, State) of
- false ->
- case fetch_app(AppInfo, AppDir, State) of
- true ->
- maybe_symlink_default(State, Profile, AppDir, AppInfo),
- {true, update_app_info(AppDir, AppInfo)};
- Other ->
- {Other, AppInfo}
- end;
- {true, FoundApp} ->
- %% Preserve the state we created with overrides
- AppState = rebar_app_info:state(AppInfo),
- FoundApp1 = rebar_app_info:state(FoundApp, AppState),
- symlink_dep(rebar_app_info:dir(FoundApp1), AppDir),
- {true, FoundApp1}
+ case fetch_app(AppInfo, AppDir, State) of
+ true ->
+ maybe_symlink_default(State, Profile, AppDir, AppInfo),
+ {true, update_app_info(AppDir, AppInfo)};
+ Other ->
+ {Other, AppInfo}
end;
{true, AppInfo1} ->
%% Preserve the state we created with overrides
AppState = rebar_app_info:state(AppInfo),
AppInfo2 = rebar_app_info:state(AppInfo1, AppState),
- maybe_symlink_default(State, Profile, AppDir, AppInfo2),
case sets:is_element(rebar_app_info:name(AppInfo), Seen) of
true ->
{false, AppInfo2};
false ->
+ maybe_symlink_default(State, Profile, AppDir, AppInfo2),
{maybe_upgrade(AppInfo, AppDir, Upgrade, State), AppInfo2}
end
end
end.
-already_in_default(AppInfo, State) ->
- Name = ec_cnv:to_list(rebar_app_info:name(AppInfo)),
- DefaultAppDir = filename:join([rebar_state:get(State, base_dir, []), "default", "lib", Name]),
- rebar_app_discover:find_app(DefaultAppDir, all).
-
needs_symlinking(State, Profile) ->
case {rebar_state:current_profiles(State), Profile} of
{[default], default} ->
@@ -504,6 +485,7 @@ parse_deps(DepsDir, Deps, State, Locks, Level) ->
end, {[], []}, Deps).
parse_dep({Name, Vsn}, {SrcDepsAcc, PkgDepsAcc}, DepsDir, IsLock, State) when is_list(Vsn) ->
+ %% Versioned Package dependency
CheckoutsDir = ec_cnv:to_list(rebar_dir:checkouts_dir(State, Name)),
case rebar_app_info:discover(CheckoutsDir) of
{ok, _App} ->
@@ -514,6 +496,7 @@ parse_dep({Name, Vsn}, {SrcDepsAcc, PkgDepsAcc}, DepsDir, IsLock, State) when is
,ec_cnv:to_binary(Vsn)) | PkgDepsAcc]}
end;
parse_dep(Name, {SrcDepsAcc, PkgDepsAcc}, DepsDir, IsLock, State) when is_atom(Name) ->
+ %% Unversioned package dependency
{PkgName, PkgVsn} = get_package(ec_cnv:to_binary(Name), State),
CheckoutsDir = ec_cnv:to_list(rebar_dir:checkouts_dir(State, Name)),
case rebar_app_info:discover(CheckoutsDir) of
diff --git a/src/rebar_prv_plugins_upgrade.erl b/src/rebar_prv_plugins_upgrade.erl
index 5ccd054..02c185f 100644
--- a/src/rebar_prv_plugins_upgrade.erl
+++ b/src/rebar_prv_plugins_upgrade.erl
@@ -62,10 +62,7 @@ upgrade(Plugin, State) ->
?PRV_ERROR({not_found, Plugin});
{ok, P, Profile} ->
State1 = rebar_state:set(State, deps_dir, ?DEFAULT_PLUGINS_DIR),
- {ok, Apps, _State2} = rebar_prv_install_deps:handle_deps(Profile
- ,State1
- ,[P]
- ,true),
+ {Apps, _State2} = rebar_prv_install_deps:handle_deps_as_profile(Profile, State1, [P], true),
{no_cycle, Sorted} = rebar_prv_install_deps:find_cycles(Apps),
ToBuild = rebar_prv_install_deps:cull_compile(Sorted, []),
diff --git a/src/rebar_prv_release.erl b/src/rebar_prv_release.erl
index dc58047..2cf9b23 100644
--- a/src/rebar_prv_release.erl
+++ b/src/rebar_prv_release.erl
@@ -32,34 +32,7 @@ init(State) ->
-spec do(rebar_state:t()) -> {ok, rebar_state:t()} | {error, string()}.
do(State) ->
- Options = rebar_state:command_args(State),
- DepsDir = rebar_dir:deps_dir(State),
- ProjectAppDirs = lists:delete(".", ?DEFAULT_PROJECT_APP_DIRS),
- LibDirs = rebar_utils:filtermap(fun ec_file:exists/1,
- [?DEFAULT_CHECKOUTS_DIR, DepsDir | ProjectAppDirs]),
- OutputDir = filename:join(rebar_dir:base_dir(State), ?DEFAULT_RELEASE_DIR),
- AllOptions = string:join(["release" | Options], " "),
- Cwd = rebar_state:dir(State),
- Providers = rebar_state:providers(State),
- rebar_hooks:run_all_hooks(Cwd, pre, ?PROVIDER, Providers, State),
- try
- case rebar_state:get(State, relx, []) of
- [] ->
- relx:main([{lib_dirs, LibDirs}
- ,{output_dir, OutputDir}
- ,{caller, api}], AllOptions);
- Config ->
- relx:main([{lib_dirs, LibDirs}
- ,{config, lists:reverse(Config)}
- ,{output_dir, OutputDir}
- ,{caller, api}], AllOptions)
- end,
- rebar_hooks:run_all_hooks(Cwd, post, ?PROVIDER, Providers, State),
- {ok, State}
- catch
- throw:T ->
- {error, {rlx_prv_release, T}}
- end.
+ rebar_relx:do(rlx_prv_release, "release", ?PROVIDER, State).
-spec format_error(any()) -> iolist().
format_error(Reason) ->
diff --git a/src/rebar_prv_relup.erl b/src/rebar_prv_relup.erl
index aed12a6..a4cd8ae 100644
--- a/src/rebar_prv_relup.erl
+++ b/src/rebar_prv_relup.erl
@@ -33,34 +33,7 @@ init(State) ->
-spec do(rebar_state:t()) -> {ok, rebar_state:t()} | {error, string()}.
do(State) ->
- Options = rebar_state:command_args(State),
- DepsDir = rebar_dir:deps_dir(State),
- ProjectAppDirs = lists:delete(".", ?DEFAULT_PROJECT_APP_DIRS),
- LibDirs = rebar_utils:filtermap(fun ec_file:exists/1,
- [?DEFAULT_CHECKOUTS_DIR, DepsDir | ProjectAppDirs]),
- OutputDir = filename:join(rebar_dir:base_dir(State), ?DEFAULT_RELEASE_DIR),
- AllOptions = string:join(["relup" | Options], " "),
- Cwd = rebar_state:dir(State),
- Providers = rebar_state:providers(State),
- rebar_hooks:run_all_hooks(Cwd, pre, ?PROVIDER, Providers, State),
- try
- case rebar_state:get(State, relx, []) of
- [] ->
- relx:main([{lib_dirs, LibDirs}
- ,{output_dir, OutputDir}
- ,{caller, api}], AllOptions);
- Config ->
- relx:main([{lib_dirs, LibDirs}
- ,{config, lists:reverse(Config)}
- ,{output_dir, OutputDir}
- ,{caller, api}], AllOptions)
- end,
- rebar_hooks:run_all_hooks(Cwd, post, ?PROVIDER, Providers, State),
- {ok, State}
- catch
- throw:T ->
- {error, {rlx_prv_release, T}}
- end.
+ rebar_relx:do(rlx_prv_release, "relup", ?PROVIDER, State).
-spec format_error(any()) -> iolist().
format_error(Reason) ->
diff --git a/src/rebar_prv_shell.erl b/src/rebar_prv_shell.erl
index 84ad723..3c6369a 100644
--- a/src/rebar_prv_shell.erl
+++ b/src/rebar_prv_shell.erl
@@ -90,9 +90,10 @@ shell(State) ->
%% their application masters never gets the new group leader (held in
%% their internal state)
maybe_boot_apps(State),
- rebar_agent:start_link(State),
- %% this call never returns (until user quits shell)
- timer:sleep(infinity).
+ simulate_proc_lib(),
+ true = register(rebar_agent, self()),
+ {ok, GenState} = rebar_agent:init(State),
+ gen_server:enter_loop(rebar_agent, [], GenState, {local, rebar_agent}, hibernate).
info() ->
"Start a shell with project and deps preloaded similar to~n'erl -pa ebin -pa deps/*/ebin'.~n".
@@ -145,6 +146,11 @@ maybe_boot_apps(State) ->
boot_apps(Apps)
end.
+simulate_proc_lib() ->
+ FakeParent = spawn_link(fun() -> timer:sleep(infinity) end),
+ put('$ancestors', [FakeParent]),
+ put('$initial_call', {rebar_agent, init, 1}).
+
setup_name(State) ->
{Opts, _} = rebar_state:command_parsed_args(State),
case {proplists:get_value(name, Opts), proplists:get_value(sname, Opts)} of
diff --git a/src/rebar_prv_tar.erl b/src/rebar_prv_tar.erl
index 17d7b0b..b3a12c0 100644
--- a/src/rebar_prv_tar.erl
+++ b/src/rebar_prv_tar.erl
@@ -32,29 +32,7 @@ init(State) ->
-spec do(rebar_state:t()) -> {ok, rebar_state:t()} | {error, string()}.
do(State) ->
- Options = rebar_state:command_args(State),
- DepsDir = rebar_dir:deps_dir(State),
- ProjectAppDirs = lists:delete(".", ?DEFAULT_PROJECT_APP_DIRS),
- LibDirs = rebar_utils:filtermap(fun ec_file:exists/1,
- [?DEFAULT_CHECKOUTS_DIR, DepsDir | ProjectAppDirs]),
- OutputDir = filename:join(rebar_dir:base_dir(State), ?DEFAULT_RELEASE_DIR),
- AllOptions = string:join(["tar" | Options], " "),
- Cwd = rebar_state:dir(State),
- Providers = rebar_state:providers(State),
- rebar_hooks:run_all_hooks(Cwd, pre, ?PROVIDER, Providers, State),
- case rebar_state:get(State, relx, []) of
- [] ->
- relx:main([{lib_dirs, LibDirs}
- ,{output_dir, OutputDir}
- ,{caller, api}], AllOptions);
- Config ->
- relx:main([{lib_dirs, LibDirs}
- ,{config, lists:reverse(Config)}
- ,{output_dir, OutputDir}
- ,{caller, api}], AllOptions)
- end,
- rebar_hooks:run_all_hooks(Cwd, post, ?PROVIDER, Providers, State),
- {ok, State}.
+ rebar_relx:do(rlx_prv_release, "tar", ?PROVIDER, State).
-spec format_error(any()) -> iolist().
format_error(Reason) ->
diff --git a/src/rebar_prv_update.erl b/src/rebar_prv_update.erl
index 6838bab..64fe65e 100644
--- a/src/rebar_prv_update.erl
+++ b/src/rebar_prv_update.erl
@@ -43,7 +43,8 @@ do(State) ->
Url = rebar_state:get(State, rebar_packages_cdn, "https://s3.amazonaws.com/s3.hex.pm/registry.ets.gz"),
{ok, _RequestId} = httpc:request(get, {Url, []},
- [], [{stream, TmpFile}, {sync, true}]),
+ [], [{stream, TmpFile}, {sync, true}],
+ rebar),
{ok, Data} = file:read_file(TmpFile),
Unzipped = zlib:gunzip(Data),
ok = file:write_file(HexFile, Unzipped),
diff --git a/src/rebar_relx.erl b/src/rebar_relx.erl
new file mode 100644
index 0000000..a3adedd
--- /dev/null
+++ b/src/rebar_relx.erl
@@ -0,0 +1,69 @@
+%% -*- erlang-indent-level: 4;indent-tabs-mode: nil -*-
+%% ex: ts=4 sw=4 et
+
+-module(rebar_relx).
+
+-export([do/4,
+ format_error/1]).
+
+-include("rebar.hrl").
+
+%% ===================================================================
+%% Public API
+%% ===================================================================
+
+-spec do(atom(), string(), atom(), rebar_state:t()) -> {ok, rebar_state:t()} | {error, string()}.
+do(Module, Command, Provider, State) ->
+ Options = rebar_state:command_args(State),
+ DepsDir = rebar_dir:deps_dir(State),
+ ProjectAppDirs = lists:delete(".", ?DEFAULT_PROJECT_APP_DIRS),
+ LibDirs = rebar_utils:filtermap(fun ec_file:exists/1,
+ [?DEFAULT_CHECKOUTS_DIR, DepsDir | ProjectAppDirs]),
+ OutputDir = filename:join(rebar_dir:base_dir(State), ?DEFAULT_RELEASE_DIR),
+ AllOptions = string:join([Command | Options], " "),
+ Cwd = rebar_state:dir(State),
+ Providers = rebar_state:providers(State),
+ rebar_hooks:run_all_hooks(Cwd, pre, Provider, Providers, State),
+ try
+ case rebar_state:get(State, relx, []) of
+ [] ->
+ relx:main([{lib_dirs, LibDirs}
+ ,{output_dir, OutputDir}
+ ,{caller, api}], AllOptions);
+ Config ->
+ Config1 = update_config(Config),
+ relx:main([{lib_dirs, LibDirs}
+ ,{config, Config1}
+ ,{output_dir, OutputDir}
+ ,{caller, api}], AllOptions)
+ end,
+ rebar_hooks:run_all_hooks(Cwd, post, Provider, Providers, State),
+ {ok, State}
+ catch
+ throw:T ->
+ {error, {Module, T}}
+ end.
+
+-spec format_error(any()) -> iolist().
+format_error(Reason) ->
+ io_lib:format("~p", [Reason]).
+
+%% To handle profiles rebar3 expects the provider to use the first entry
+%% in a configuration key-value list as the value of a key if dups exist.
+%% This does not work with relx. Some config options must not lose their
+%% order (release which has an extends option is one). So here we pull out
+%% options that are special so we can reverse the rest so what we expect
+%% from a rebar3 profile is what we get on the relx side.
+-define(SPECIAL_KEYS, [release, vm_args, sys_config, overlay_vars, lib_dirs]).
+
+update_config(Config) ->
+ {Special, Other} =
+ lists:foldl(fun(Tuple, {SpecialAcc, OtherAcc}) when is_tuple(Tuple) ->
+ case lists:member(element(1, Tuple), ?SPECIAL_KEYS) of
+ true ->
+ {[Tuple | SpecialAcc], OtherAcc};
+ false ->
+ {SpecialAcc, [Tuple | OtherAcc]}
+ end
+ end, {[], []}, Config),
+ lists:reverse(Special) ++ Other.
diff --git a/src/rebar_utils.erl b/src/rebar_utils.erl
index cc59ed0..ebdf0fe 100644
--- a/src/rebar_utils.erl
+++ b/src/rebar_utils.erl
@@ -56,7 +56,8 @@
wordsize/0,
tup_umerge/2,
tup_sort/1,
- line_count/1]).
+ line_count/1,
+ set_httpc_options/0]).
%% for internal use only
-export([otp_release/0]).
@@ -127,11 +128,13 @@ sh_send(Command0, String, Options0) ->
PortSettings = proplists:get_all_values(port_settings, Options) ++
[exit_status, {line, 16384}, use_stdio, stderr_to_stdout, hide],
Port = open_port({spawn, Command}, PortSettings),
-
- %% allow us to send some data to the shell command's STDIN
- %% Erlang doesn't let us get any reply after sending an EOF, though...
- Port ! {self(), {command, String}},
- port_close(Port).
+ try
+ %% allow us to send some data to the shell command's STDIN
+ %% Erlang doesn't let us get any reply after sending an EOF, though...
+ Port ! {self(), {command, String}}
+ after
+ port_close(Port)
+ end.
%%
%% Options = [Option] -- defaults to [use_stdout, abort_on_error]
@@ -154,15 +157,19 @@ sh(Command0, Options0) ->
Command = lists:flatten(patch_on_windows(Command0, proplists:get_value(env, Options, []))),
PortSettings = proplists:get_all_values(port_settings, Options) ++
- [exit_status, {line, 16384}, use_stdio, stderr_to_stdout, hide],
+ [exit_status, {line, 16384}, use_stdio, stderr_to_stdout, hide, eof],
?DEBUG("Port Cmd: ~s\nPort Opts: ~p\n", [Command, PortSettings]),
Port = open_port({spawn, Command}, PortSettings),
- case sh_loop(Port, OutputHandler, []) of
- {ok, _Output} = Ok ->
- Ok;
- {error, {_Rc, _Output}=Err} ->
- ErrorHandler(Command, Err)
+ try
+ case sh_loop(Port, OutputHandler, []) of
+ {ok, _Output} = Ok ->
+ Ok;
+ {error, {_Rc, _Output}=Err} ->
+ ErrorHandler(Command, Err)
+ end
+ after
+ port_close(Port)
end.
find_files(Dir, Regex) ->
@@ -435,10 +442,14 @@ sh_loop(Port, Fun, Acc) ->
sh_loop(Port, Fun, Fun(Line ++ "\n", Acc));
{Port, {data, {noeol, Line}}} ->
sh_loop(Port, Fun, Fun(Line, Acc));
- {Port, {exit_status, 0}} ->
- {ok, lists:flatten(lists:reverse(Acc))};
- {Port, {exit_status, Rc}} ->
- {error, {Rc, lists:flatten(lists:reverse(Acc))}}
+ {Port, eof} ->
+ Data = lists:flatten(lists:reverse(Acc)),
+ receive
+ {Port, {exit_status, 0}} ->
+ {ok, Data};
+ {Port, {exit_status, Rc}} ->
+ {error, {Rc, Data}}
+ end
end.
beam_to_mod(Dir, Filename) ->
@@ -657,3 +668,19 @@ maybe_ends_in_comma(H) ->
"," ++ Flag -> lists:reverse(Flag);
_ -> false
end.
+
+get_http_vars(Scheme) ->
+ GlobalConfigFile = rebar_dir:global_config(),
+ Config = rebar_config:consult_file(GlobalConfigFile),
+ proplists:get_value(Scheme, Config, []).
+
+set_httpc_options() ->
+ set_httpc_options(https_proxy, get_http_vars(https_proxy)),
+ set_httpc_options(proxy, get_http_vars(http_proxy)).
+
+set_httpc_options(_, []) ->
+ ok;
+
+set_httpc_options(Scheme, Proxy) ->
+ {ok, {_, _, Host, Port, _, _}} = http_uri:parse(Proxy),
+ httpc:set_options([{Scheme, {{Host, Port}, []}}], rebar).