summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.travis.yml2
-rw-r--r--CONTRIBUTING.md4
-rw-r--r--README.md10
-rwxr-xr-xbootstrap4
-rw-r--r--priv/templates/app.erl3
-rw-r--r--rebar.config4
-rw-r--r--rebar.lock4
-rw-r--r--src/rebar.hrl2
-rw-r--r--src/rebar_agent.erl17
-rw-r--r--src/rebar_dist_utils.erl89
-rw-r--r--src/rebar_git_resource.erl2
-rw-r--r--src/rebar_prv_common_test.erl22
-rw-r--r--src/rebar_prv_dialyzer.erl2
-rw-r--r--src/rebar_prv_edoc.erl8
-rw-r--r--src/rebar_prv_eunit.erl27
-rw-r--r--src/rebar_prv_packages.erl32
-rw-r--r--src/rebar_prv_path.erl8
-rw-r--r--src/rebar_prv_report.erl2
-rw-r--r--src/rebar_prv_shell.erl68
-rw-r--r--test/rebar_dist_utils_SUITE.erl74
20 files changed, 299 insertions, 85 deletions
diff --git a/.travis.yml b/.travis.yml
index 630beb2..ab2d28d 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -17,7 +17,7 @@ cache:
before_deploy: "rm -rf !(rebar3)"
deploy:
on:
- branch: master
+ tags: true
condition: $TRAVIS_OTP_RELEASE = R16B03-1
provider: s3
access_key_id: AKIAJAPYAQEFYCYSNL7Q
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index f175cc2..8077813 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -23,7 +23,7 @@ All files without specific headers can safely be assumed to be under Apache
## Submitting a Bug
-Bugs can be submitted to the [Github issue page](https://github.com/rebar/rebar3/issues).
+Bugs can be submitted to the [Github issue page](https://github.com/erlang/rebar3/issues).
Rebar3 is not perfect software and will be buggy. When submitting a bug, be
careful to know the following:
@@ -58,7 +58,7 @@ Before requesting or implementing a new feature, please do the following:
- Take a look at our [list of plugins](http://www.rebar3.org/docs/using-available-plugins)
to know if the feature isn't already supported by the community.
-- Verify in existing [tickets](https://github.com/rebar/rebar3/issues) whether
+- Verify in existing [tickets](https://github.com/erlang/rebar3/issues) whether
the feature might already is in the works, has been moved to a plugin, or
has already been rejected.
diff --git a/README.md b/README.md
index 6e5f102..7560ab0 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
# Rebar3
-[![Build Status](https://travis-ci.org/rebar/rebar3.svg?branch=master)](https://travis-ci.org/rebar/rebar3) [![Windows build status](https://ci.appveyor.com/api/projects/status/yx4oitd9pvd2kab3?svg=true)](https://ci.appveyor.com/project/TristanSloughter/rebar3)
+[![Build Status](https://travis-ci.org/erlang/rebar3.svg?branch=master)](https://travis-ci.org/erlang/rebar3) [![Windows build status](https://ci.appveyor.com/api/projects/status/yx4oitd9pvd2kab3?svg=true)](https://ci.appveyor.com/project/TristanSloughter/rebar3)
1. [What is Rebar3?](#what-is-rebar3)
2. [Why Rebar3?](#why-rebar3)
@@ -64,12 +64,12 @@ $ wget https://s3.amazonaws.com/rebar3/rebar3 && chmod +x rebar3
From Source (assuming you have a full Erlang install):
```bash
-$ git clone https://github.com/rebar/rebar3.git
+$ git clone https://github.com/erlang/rebar3.git
$ cd rebar3
$ ./bootstrap
```
-Stable versions can be obtained from the [releases page](https://github.com/rebar/rebar3/releases).
+Stable versions can be obtained from the [releases page](https://github.com/erlang/rebar3/releases).
The rebar3 escript can also extract itself with a run script under the user's home directory:
@@ -159,13 +159,13 @@ quick feedback, you can try the #rebar channel on
asking about things with well known answers.
For bug reports, roadmaps, and issues, visit the [github issues
-page](https://github.com/rebar/rebar3/issues).
+page](https://github.com/erlang/rebar3/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/)
-- [issues](https://github.com/rebar/rebar3/issues)
+- [issues](https://github.com/erlang/rebar3/issues)
- [Documentation](http://www.rebar3.org/v3.0/docs)
To contribute to rebar3, please refer to [CONTRIBUTING](CONTRIBUTING.md).
diff --git a/bootstrap b/bootstrap
index b20d0d3..e2a393b 100755
--- a/bootstrap
+++ b/bootstrap
@@ -24,7 +24,7 @@ main(_) ->
bootstrap_rebar3(),
%% Build rebar.app from rebar.app.src
- {ok, App} = rebar_app_info:new(rebar, "3.0.0", filename:absname("_build/default/lib/rebar/")),
+ {ok, App} = rebar_app_info:new(rebar, "3.1.0", filename:absname("_build/default/lib/rebar/")),
rebar_otp_app:compile(rebar_state:new(), App),
%% Because we are compiling files that are loaded already we want to silence
@@ -92,7 +92,7 @@ fetch({pkg, Name, Vsn}, App) ->
Dir = filename:join([filename:absname("_build/default/lib/"), App]),
case filelib:is_dir(Dir) of
false ->
- CDN = "https://s3.amazonaws.com/s3.hex.pm/tarballs",
+ CDN = "https://repo.hex.pm/tarballs",
Package = binary_to_list(<<Name/binary, "-", Vsn/binary, ".tar">>),
Url = string:join([CDN, Package], "/"),
case request(Url) of
diff --git a/priv/templates/app.erl b/priv/templates/app.erl
index 83eb9a3..62d2ddf 100644
--- a/priv/templates/app.erl
+++ b/priv/templates/app.erl
@@ -8,8 +8,7 @@
-behaviour(application).
%% Application callbacks
--export([start/2
- ,stop/1]).
+-export([start/2, stop/1]).
%%====================================================================
%% API
diff --git a/rebar.config b/rebar.config
index 575c616..5d3b310 100644
--- a/rebar.config
+++ b/rebar.config
@@ -1,13 +1,13 @@
%% -*- mode: erlang;erlang-indent-level: 4;indent-tabs-mode: nil -*-
%% ex: ts=4 sw=4 ft=erlang et
-{deps, [{erlware_commons, "0.19.0"},
+{deps, [{erlware_commons, "0.20.0"},
{ssl_verify_hostname, "1.0.5"},
{certifi, "0.4.0"},
{providers, "1.6.0"},
{getopt, "0.8.2"},
{bbmustache, "1.0.4"},
- {relx, "3.17.0"},
+ {relx, "3.19.0"},
{cf, "0.2.1"},
{cth_readable, "1.2.2"},
{eunit_formatters, "0.3.1"}]}.
diff --git a/rebar.lock b/rebar.lock
index a9a1cd2..9c6fe4a 100644
--- a/rebar.lock
+++ b/rebar.lock
@@ -2,9 +2,9 @@
{<<"certifi">>,{pkg,<<"certifi">>,<<"0.4.0">>},0},
{<<"cf">>,{pkg,<<"cf">>,<<"0.2.1">>},0},
{<<"cth_readable">>,{pkg,<<"cth_readable">>,<<"1.2.2">>},0},
- {<<"erlware_commons">>,{pkg,<<"erlware_commons">>,<<"0.19.0">>},0},
+ {<<"erlware_commons">>,{pkg,<<"erlware_commons">>,<<"0.20.0">>},0},
{<<"eunit_formatters">>,{pkg,<<"eunit_formatters">>,<<"0.3.1">>},0},
{<<"getopt">>,{pkg,<<"getopt">>,<<"0.8.2">>},0},
{<<"providers">>,{pkg,<<"providers">>,<<"1.6.0">>},0},
- {<<"relx">>,{pkg,<<"relx">>,<<"3.17.0">>},0},
+ {<<"relx">>,{pkg,<<"relx">>,<<"3.19.0">>},0},
{<<"ssl_verify_hostname">>,{pkg,<<"ssl_verify_hostname">>,<<"1.0.5">>},0}].
diff --git a/src/rebar.hrl b/src/rebar.hrl
index f4e7f5e..0b7f0b1 100644
--- a/src/rebar.hrl
+++ b/src/rebar.hrl
@@ -22,7 +22,7 @@
-define(DEFAULT_TEST_DEPS_DIR, "test/lib").
-define(DEFAULT_RELEASE_DIR, "rel").
-define(DEFAULT_CONFIG_FILE, "rebar.config").
--define(DEFAULT_CDN, "https://s3.amazonaws.com/s3.hex.pm/").
+-define(DEFAULT_CDN, "https://repo.hex.pm/").
-define(REMOTE_PACKAGE_DIR, "tarballs").
-define(REMOTE_REGISTRY_FILE, "registry.ets.gz").
-define(LOCK_FILE, "rebar.lock").
diff --git a/src/rebar_agent.erl b/src/rebar_agent.erl
index 2b69812..95818d8 100644
--- a/src/rebar_agent.erl
+++ b/src/rebar_agent.erl
@@ -86,6 +86,8 @@ refresh_paths(RState) ->
|| App <- rebar_state:project_apps(RState)]
%% make sure to never reload self; halt()s the VM
) -- [filename:dirname(code:which(?MODULE))],
+ %% Modules from apps we can't reload without breaking functionality
+ Blacklist = [ec_cmd_log, providers, cf, cth_readable],
%% Similar to rebar_utils:update_code/1, but also forces a reload
%% of used modules. Also forces to reload all of ebin/ instead
%% of just the modules in the .app file, because 'extra_src_dirs'
@@ -102,11 +104,16 @@ refresh_paths(RState) ->
undefined ->
code:add_patha(Path),
ok;
- {ok, _} ->
- ?DEBUG("reloading ~p from ~s", [Modules, Path]),
- code:replace_path(App, Path),
- [begin code:purge(M), code:delete(M), code:load_file(M) end
- || M <- Modules]
+ {ok, Mods} ->
+ case {length(Mods), length(Mods -- Blacklist)} of
+ {X,X} ->
+ ?DEBUG("reloading ~p from ~s", [Modules, Path]),
+ code:replace_path(App, Path),
+ [begin code:purge(M), code:delete(M), code:load_file(M) end
+ || M <- Modules];
+ {_,_} ->
+ ?DEBUG("skipping app ~p, stable copy required", [App])
+ end
end
end, ToRefresh).
diff --git a/src/rebar_dist_utils.erl b/src/rebar_dist_utils.erl
new file mode 100644
index 0000000..f462826
--- /dev/null
+++ b/src/rebar_dist_utils.erl
@@ -0,0 +1,89 @@
+%%% Common functions to boot/stop distributed setups for
+%%% the rebar3 script.
+-module(rebar_dist_utils).
+-export([either/3, short/2, long/2, find_options/1]).
+-include("rebar.hrl").
+
+%%%%%%%%%%%%%%%%%%
+%%% PUBLIC API %%%
+%%%%%%%%%%%%%%%%%%
+-spec either(Name::atom(), SName::atom(), Opts::[{setcookie,term()}]) -> atom().
+either(undefined, undefined, _) ->
+ 'nonode@nohost';
+either(Name, undefined, Opts) ->
+ long(Name, Opts),
+ node();
+either(undefined, SName, Opts) ->
+ short(SName, Opts),
+ node();
+either(_, _, _) ->
+ ?ABORT("Cannot have both short and long node names defined", []).
+
+short(Name, Opts) ->
+ start(Name, shortnames, Opts).
+
+long(Name, Opts) ->
+ start(Name, longnames, Opts).
+
+-spec find_options(rebar_state:state()) -> {Long, Short, Opts} when
+ Long :: atom(),
+ Short :: atom(),
+ Opts :: [{setcookie,term()}].
+find_options(State) ->
+ {Long, Short} = find_name_options(State),
+ case find_cookie_option(State) of
+ nocookie ->
+ {Long, Short, []};
+ Cookie ->
+ {Long, Short, [{setcookie, Cookie}]}
+ end.
+
+%%%%%%%%%%%%%%%
+%%% PRIVATE %%%
+%%%%%%%%%%%%%%%
+start(Name, Type, Opts) ->
+ check_epmd(net_kernel:start([Name, Type])),
+ setup_cookie(Opts).
+
+check_epmd({error,{{shutdown, {_,net_kernel,{'EXIT',nodistribution}}},_}}) ->
+ ?ERROR("Erlang Distribution failed, falling back to nonode@nohost. "
+ "Verify that epmd is running and try again.",[]);
+check_epmd(_) ->
+ ok.
+
+setup_cookie(Opts) ->
+ case {node(), proplists:get_value(setcookie, Opts, nocookie)} of
+ {'nonode@nohost', _} -> nocookie;
+ {_, nocookie} -> nocookie;
+ {Node, Name} -> erlang:set_cookie(Node, Name)
+ end.
+
+find_name_options(State) ->
+ {Opts, _} = rebar_state:command_parsed_args(State),
+ %% First try the CLI
+ case {proplists:get_value(name, Opts), proplists:get_value(sname, Opts)} of
+ {undefined, undefined} ->
+ %% Else try the config file
+ DistOpts = rebar_state:get(State, dist_node, []),
+ %% Pick the first one seen to support profile merges
+ find_first_name(DistOpts);
+ Res ->
+ Res
+ end.
+
+find_first_name([]) -> {undefined, undefined};
+find_first_name([{sname,Val}|_]) -> {undefined, Val};
+find_first_name([{name,Val}|_]) -> {Val, undefined};
+find_first_name([_|Opts]) -> find_first_name(Opts).
+
+find_cookie_option(State) ->
+ {Opts, _} = rebar_state:command_parsed_args(State),
+ %% First try the CLI
+ case proplists:get_value(setcookie, Opts) of
+ undefined ->
+ %% Else try the config file
+ DistOpts = rebar_state:get(State, dist_node, []),
+ proplists:get_value(setcookie, DistOpts, nocookie);
+ Res ->
+ Res
+ end.
diff --git a/src/rebar_git_resource.erl b/src/rebar_git_resource.erl
index 876d047..5a6a5ef 100644
--- a/src/rebar_git_resource.erl
+++ b/src/rebar_git_resource.erl
@@ -201,7 +201,7 @@ parse_tags(Dir) ->
{error, _} ->
{undefined, "0.0.0"};
{ok, Line} ->
- case re:run(Line, "(\\(|\\s)(HEAD,\\s)tag:\\s(v?([^,\\)]+))", [{capture, [3, 4], list}]) of
+ case re:run(Line, "(\\(|\\s)(HEAD[^,]*,\\s)tag:\\s(v?([^,\\)]+))", [{capture, [3, 4], list}]) of
{match,[Tag, Vsn]} ->
{Tag, Vsn};
nomatch ->
diff --git a/src/rebar_prv_common_test.erl b/src/rebar_prv_common_test.erl
index 6b94f79..5712fbf 100644
--- a/src/rebar_prv_common_test.erl
+++ b/src/rebar_prv_common_test.erl
@@ -37,6 +37,7 @@ init(State) ->
-spec do(rebar_state:t()) -> {ok, rebar_state:t()} | {error, string()}.
do(State) ->
+ setup_name(State),
Tests = prepare_tests(State),
case compile(State, Tests) of
%% successfully compiled apps
@@ -105,6 +106,10 @@ format_error({multiple_errors, Errors}) ->
%% Internal functions
%% ===================================================================
+setup_name(State) ->
+ {Long, Short, Opts} = rebar_dist_utils:find_options(State),
+ rebar_dist_utils:either(Long, Short, Opts).
+
prepare_tests(State) ->
%% command line test options
CmdOpts = cmdopts(State),
@@ -189,8 +194,10 @@ ensure_opts([{suite, Suites}|Rest], Acc) ->
ensure_opts(Rest, [NewSuites|Acc]);
ensure_opts([{K, V}|Rest], Acc) ->
ensure_opts(Rest, [{K, V}|Acc]);
-ensure_opts([V|_Rest], _Acc) ->
- ?PRV_ERROR({badconfig, {"Member `~p' of option `~p' must be a 2-tuple", {V, ct_opts}}}).
+%% pass through other options, in case of things like config terms
+%% in `ct_opts`
+ensure_opts([V|Rest], Acc) ->
+ ensure_opts(Rest, [V|Acc]).
add_hooks(Opts, State) ->
case {readable(State), lists:keyfind(ct_hooks, 1, Opts)} of
@@ -637,7 +644,10 @@ ct_opts(_State) ->
{create_priv_dir, undefined, "create_priv_dir", string, help(create_priv_dir)},
{include, undefined, "include", string, help(include)},
{readable, undefined, "readable", boolean, help(readable)},
- {verbose, $v, "verbose", boolean, help(verbose)}
+ {verbose, $v, "verbose", boolean, help(verbose)},
+ {name, undefined, "name", atom, help(name)},
+ {sname, undefined, "sname", atom, help(sname)},
+ {setcookie, undefined, "setcookie", atom, help(setcookie)}
].
help(dir) ->
@@ -692,5 +702,11 @@ help(readable) ->
"Shows test case names and only displays logs to shell on failures";
help(verbose) ->
"Verbose output";
+help(name) ->
+ "Gives a long name to the node";
+help(sname) ->
+ "Gives a short name to the node";
+help(setcookie) ->
+ "Sets the cookie if the node is distributed";
help(_) ->
"".
diff --git a/src/rebar_prv_dialyzer.erl b/src/rebar_prv_dialyzer.erl
index 834eb98..622ee60 100644
--- a/src/rebar_prv_dialyzer.erl
+++ b/src/rebar_prv_dialyzer.erl
@@ -97,7 +97,7 @@ do(State) ->
end.
%% This is used to workaround dialyzer quirk discussed here
-%% https://github.com/rebar/rebar3/pull/489#issuecomment-107953541
+%% https://github.com/erlang/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() ->
diff --git a/src/rebar_prv_edoc.erl b/src/rebar_prv_edoc.erl
index e7048b6..6cefe14 100644
--- a/src/rebar_prv_edoc.erl
+++ b/src/rebar_prv_edoc.erl
@@ -32,13 +32,19 @@ init(State) ->
do(State) ->
code:add_pathsa(rebar_state:code_paths(State, all_deps)),
ProjectApps = rebar_state:project_apps(State),
+ Providers = rebar_state:providers(State),
EDocOpts = rebar_state:get(State, edoc_opts, []),
+ Cwd = rebar_state:dir(State),
+ rebar_hooks:run_all_hooks(Cwd, pre, ?PROVIDER, Providers, State),
lists:foreach(fun(AppInfo) ->
+ rebar_hooks:run_all_hooks(Cwd, pre, ?PROVIDER, Providers, AppInfo, State),
AppName = ec_cnv:to_list(rebar_app_info:name(AppInfo)),
?INFO("Running edoc for ~s", [AppName]),
AppDir = rebar_app_info:dir(AppInfo),
- ok = edoc:application(list_to_atom(AppName), AppDir, EDocOpts)
+ ok = edoc:application(list_to_atom(AppName), AppDir, EDocOpts),
+ rebar_hooks:run_all_hooks(Cwd, post, ?PROVIDER, Providers, AppInfo, State)
end, ProjectApps),
+ rebar_hooks:run_all_hooks(Cwd, post, ?PROVIDER, Providers, State),
rebar_utils:cleanup_code_path(rebar_state:code_paths(State, default)),
{ok, State}.
diff --git a/src/rebar_prv_eunit.erl b/src/rebar_prv_eunit.erl
index 46ea48d..942fd10 100644
--- a/src/rebar_prv_eunit.erl
+++ b/src/rebar_prv_eunit.erl
@@ -51,6 +51,7 @@ do(State) ->
do(State, Tests) ->
?INFO("Performing EUnit tests...", []),
+ setup_name(State),
rebar_utils:update_code(rebar_state:code_paths(State, all_deps), [soft_purge]),
%% Run eunit provider prehooks
@@ -106,6 +107,10 @@ format_error({error, Error}) ->
%% Internal functions
%% ===================================================================
+setup_name(State) ->
+ {Long, Short, Opts} = rebar_dist_utils:find_options(State),
+ rebar_dist_utils:either(Long, Short, Opts).
+
prepare_tests(State) ->
%% parse and translate command line tests
CmdTests = resolve_tests(State),
@@ -479,11 +484,17 @@ eunit_opts(_State) ->
{file, $f, "file", string, help(file)},
{module, $m, "module", string, help(module)},
{suite, $s, "suite", string, help(module)},
- {verbose, $v, "verbose", boolean, help(verbose)}].
-
-help(app) -> "Comma separated list of application test suites to run. Equivalent to `[{application, App}]`.";
-help(cover) -> "Generate cover data. Defaults to false.";
-help(dir) -> "Comma separated list of dirs to load tests from. Equivalent to `[{dir, Dir}]`.";
-help(file) -> "Comma separated list of files to load tests from. Equivalent to `[{file, File}]`.";
-help(module) -> "Comma separated list of modules to load tests from. Equivalent to `[{module, Module}]`.";
-help(verbose) -> "Verbose output. Defaults to false.".
+ {verbose, $v, "verbose", boolean, help(verbose)},
+ {name, undefined, "name", atom, help(name)},
+ {sname, undefined, "sname", atom, help(sname)},
+ {setcookie, undefined, "setcookie", atom, help(setcookie)}].
+
+help(app) -> "Comma separated list of application test suites to run. Equivalent to `[{application, App}]`.";
+help(cover) -> "Generate cover data. Defaults to false.";
+help(dir) -> "Comma separated list of dirs to load tests from. Equivalent to `[{dir, Dir}]`.";
+help(file) -> "Comma separated list of files to load tests from. Equivalent to `[{file, File}]`.";
+help(module) -> "Comma separated list of modules to load tests from. Equivalent to `[{module, Module}]`.";
+help(verbose) -> "Verbose output. Defaults to false.";
+help(name) -> "Gives a long name to the node";
+help(sname) -> "Gives a short name to the node";
+help(setcookie) -> "Sets the cookie if the node is distributed".
diff --git a/src/rebar_prv_packages.erl b/src/rebar_prv_packages.erl
index 998320c..7217ab8 100644
--- a/src/rebar_prv_packages.erl
+++ b/src/rebar_prv_packages.erl
@@ -28,22 +28,19 @@ init(State) ->
-spec do(rebar_state:t()) -> {ok, rebar_state:t()} | {error, string()}.
do(State) ->
rebar_packages:packages(State),
- print_packages(),
+ case rebar_state:command_args(State) of
+ [Name] ->
+ print_packages(get_packages(iolist_to_binary(Name)));
+ _ ->
+ print_packages(sort_packages())
+ end,
{ok, State}.
-spec format_error(any()) -> iolist().
format_error(load_registry_fail) ->
"Failed to load package regsitry. Try running 'rebar3 update' to fix".
-print_packages() ->
- SortedPkgs = ets:foldl(fun({package_index_version, _}, Acc) ->
- Acc;
- ({Pkg, Vsns}, Acc) ->
- orddict:store(Pkg, Vsns, Acc);
- (_, Acc) ->
- Acc
- end, orddict:new(), ?PACKAGE_TABLE),
-
+print_packages(Pkgs) ->
orddict:map(fun(Name, Vsns) ->
SortedVsns = lists:sort(fun(A, B) ->
ec_semver:lte(ec_semver:parse(A)
@@ -51,7 +48,20 @@ print_packages() ->
end, Vsns),
VsnStr = join(SortedVsns, <<", ">>),
?CONSOLE("~s:~n Versions: ~s~n", [Name, VsnStr])
- end, SortedPkgs).
+ end, Pkgs).
+
+sort_packages() ->
+ ets:foldl(fun({package_index_version, _}, Acc) ->
+ Acc;
+ ({Pkg, Vsns}, Acc) ->
+ orddict:store(Pkg, Vsns, Acc);
+ (_, Acc) ->
+ Acc
+ end, orddict:new(), ?PACKAGE_TABLE).
+
+get_packages(Name) ->
+ ets:lookup(?PACKAGE_TABLE, Name).
+
-spec join([binary()], binary()) -> binary().
join([Bin], _Sep) ->
diff --git a/src/rebar_prv_path.erl b/src/rebar_prv_path.erl
index 37c9834..4e88496 100644
--- a/src/rebar_prv_path.erl
+++ b/src/rebar_prv_path.erl
@@ -95,10 +95,14 @@ print_paths_if_exist(Paths, State) ->
project_deps(State) ->
Profiles = rebar_state:current_profiles(State),
- List = lists:foldl(fun(Profile, Acc) -> rebar_state:get(State, {deps, Profile}, []) ++ Acc end, [], Profiles),
- Deps = [normalize(Name) || {Name, _} <- List],
+ DepList = lists:foldl(fun(Profile, Acc) -> rebar_state:get(State, {deps, Profile}, []) ++ Acc end, [], Profiles),
+ LockList = lists:foldl(fun(Profile, Acc) -> rebar_state:get(State, {locks, Profile}, []) ++ Acc end, [], Profiles),
+ Deps = [normalize(name(Dep)) || Dep <- DepList++LockList],
lists:usort(Deps).
+name(App) when is_tuple(App) -> element(1, App);
+name(Name) when is_binary(Name); is_list(Name); is_atom(Name) -> Name.
+
normalize(AppName) when is_list(AppName) -> AppName;
normalize(AppName) when is_atom(AppName) -> atom_to_list(AppName);
normalize(AppName) when is_binary(AppName) -> binary_to_list(AppName).
diff --git a/src/rebar_prv_report.erl b/src/rebar_prv_report.erl
index 587fad7..d6c8b60 100644
--- a/src/rebar_prv_report.erl
+++ b/src/rebar_prv_report.erl
@@ -13,7 +13,7 @@
-define(PROVIDER, report).
-define(DEPS, []).
--define(ISSUES_URL, "https://github.com/rebar/rebar3/issues").
+-define(ISSUES_URL, "https://github.com/erlang/rebar3/issues").
%% ===================================================================
%% Public API
diff --git a/src/rebar_prv_shell.erl b/src/rebar_prv_shell.erl
index 430d1e8..0ede495 100644
--- a/src/rebar_prv_shell.erl
+++ b/src/rebar_prv_shell.erl
@@ -133,11 +133,25 @@ kill_old_user() ->
%% fully die
[P] = [P || P <- element(2,process_info(whereis(user), links)), is_port(P)],
user ! {'EXIT', P, normal}, % pretend the port died, then the port can die!
+ exit(P, kill),
+ wait_for_port_death(1000, P),
OldUser.
+wait_for_port_death(N, _) when N < 0 ->
+ %% This risks displaying a warning!
+ whatever;
+wait_for_port_death(N, P) ->
+ case erlang:port_info(P) of
+ undefined ->
+ ok;
+ _ ->
+ timer:sleep(10),
+ wait_for_port_death(N-10, P)
+ end.
+
setup_new_shell() ->
- %% terminate the current user supervision structure
- ok = supervisor:terminate_child(kernel_sup, user),
+ %% terminate the current user supervision structure, if any
+ _ = supervisor:terminate_child(kernel_sup, user),
%% start a new shell (this also starts a new user under the correct group)
_ = user_drv:start(),
%% wait until user_drv and user have been registered (max 3 seconds)
@@ -178,7 +192,9 @@ rewrite_leaders(OldUser, NewUser) ->
%% disable the simple error_logger (which may have been added multiple
%% times). removes at most the error_logger added by init and the
%% error_logger added by the tty handler
- remove_error_handler(3)
+ remove_error_handler(3),
+ %% reset the tty handler once more for remote shells
+ error_logger:swap_handler(tty)
catch
E:R -> % may fail with custom loggers
?DEBUG("Logger changes failed for ~p:~p (~p)", [E,R,erlang:get_stacktrace()]),
@@ -255,33 +271,8 @@ simulate_proc_lib() ->
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
- {undefined, undefined} ->
- ok;
- {Name, undefined} ->
- check_epmd(net_kernel:start([Name, longnames])),
- setup_cookie(Opts);
- {undefined, SName} ->
- check_epmd(net_kernel:start([SName, shortnames])),
- setup_cookie(Opts);
- {_, _} ->
- ?ABORT("Cannot have both short and long node names defined", [])
- end.
-
-check_epmd({error,{{shutdown, {_,net_kernel,{'EXIT',nodistribution}}},_}}) ->
- ?ERROR("Erlang Distribution failed, falling back to nonode@nohost. "
- "Verify that epmd is running and try again.",[]);
-check_epmd(_) ->
- ok.
-
-setup_cookie(Opts) ->
- case {node(), proplists:get_value(setcookie, Opts, nocookie)} of
- {'nonode@nohost', _} -> nocookie;
- {_, nocookie} -> nocookie;
- {Node, Name} -> erlang:set_cookie(Node, Name)
- end.
-
+ {Long, Short, Opts} = rebar_dist_utils:find_options(State),
+ rebar_dist_utils:either(Long, Short, Opts).
find_apps_to_boot(State) ->
%% Try the shell_apps option
@@ -339,7 +330,8 @@ reread_config(State) ->
ConfigList ->
try
[application:set_env(Application, Key, Val)
- || {Application, Items} <- ConfigList,
+ || Config <- ConfigList,
+ {Application, Items} <- Config,
{Key, Val} <- Items]
catch _:_ ->
?ERROR("The configuration file submitted could not be read "
@@ -402,7 +394,7 @@ add_test_paths(State) ->
ok.
% First try the --config flag, then try the relx sys_config
--spec find_config(rebar_state:t()) -> [tuple()] | no_config.
+-spec find_config(rebar_state:t()) -> [[tuple()]] | no_config.
find_config(State) ->
case first_value([fun find_config_option/1,
fun find_config_rebar/1,
@@ -450,11 +442,17 @@ find_config_relx(State) ->
debug_get_value(sys_config, rebar_state:get(State, relx, []), no_value,
"Found config from relx.").
--spec consult_config(rebar_state:t(), string()) -> [tuple()].
+-spec consult_config(rebar_state:t(), string()) -> [[tuple()]].
consult_config(State, Filename) ->
Fullpath = filename:join(rebar_dir:root_dir(State), Filename),
?DEBUG("Loading configuration from ~p", [Fullpath]),
- case rebar_file_utils:try_consult(Fullpath) of
+ Config = case rebar_file_utils:try_consult(Fullpath) of
[T] -> T;
[] -> []
- end.
+ end,
+ SubConfigs = [consult_config(State, Entry ++ ".config") ||
+ Entry <- Config, is_list(Entry)
+ ],
+
+ [Config | lists:merge(SubConfigs)].
+
diff --git a/test/rebar_dist_utils_SUITE.erl b/test/rebar_dist_utils_SUITE.erl
new file mode 100644
index 0000000..e190b94
--- /dev/null
+++ b/test/rebar_dist_utils_SUITE.erl
@@ -0,0 +1,74 @@
+%%% This suite currently only tests for options parsing since we do
+%%% not know if epmd will be running to actually boot nodes.
+-module(rebar_dist_utils_SUITE).
+-include_lib("common_test/include/ct.hrl").
+-include_lib("eunit/include/eunit.hrl").
+-compile(export_all).
+
+all() -> [from_config, from_cli, overlap, from_config_profile].
+
+init_per_testcase(_, Config0) ->
+ Config = rebar_test_utils:init_rebar_state(Config0),
+ AppDir = ?config(apps, Config),
+ Name = rebar_test_utils:create_random_name("app_"),
+ Vsn = rebar_test_utils:create_random_vsn(),
+ rebar_test_utils:create_app(filename:join([AppDir,"apps",Name]), Name, Vsn, [kernel, stdlib]),
+ Config.
+
+
+end_per_testcase(_, _) ->
+ ok.
+
+from_config(Config) ->
+ ShortConfig = [{dist_node, [{sname, 'a@localhost'}, {setcookie, abc}]}],
+ LongConfig = [{dist_node, [{name, 'a@localhost.x'}, {setcookie, abc}]}],
+ BothConfig = [{dist_node, [{sname, 'a@localhost'}, {name, 'a@localhost.x'}, {setcookie,abc}]}],
+ NoConfig = [],
+ CookieConfig = [{dist_node, [{setcookie, def}]}],
+ NoCookie = [{dist_node, [{sname, 'a@localhost'}]}],
+ {ok, State0} = rebar_test_utils:run_and_check(Config, ShortConfig, ["version"], return),
+ {undefined, 'a@localhost', [{setcookie, abc}]} = rebar_dist_utils:find_options(State0),
+ {ok, State1} = rebar_test_utils:run_and_check(Config, LongConfig, ["version"], return),
+ {'a@localhost.x', undefined, [{setcookie, abc}]} = rebar_dist_utils:find_options(State1),
+ %% only support the first name found, side-effect of wanting profile support
+ {ok, State2} = rebar_test_utils:run_and_check(Config, BothConfig, ["version"], return),
+ {undefined, 'a@localhost', [{setcookie, abc}]} = rebar_dist_utils:find_options(State2),
+ {ok, State3} = rebar_test_utils:run_and_check(Config, NoConfig, ["version"], return),
+ {undefined, undefined, []} = rebar_dist_utils:find_options(State3),
+ {ok, State4} = rebar_test_utils:run_and_check(Config, CookieConfig, ["version"], return),
+ {undefined, undefined, [{setcookie, def}]} = rebar_dist_utils:find_options(State4),
+ {ok, State5} = rebar_test_utils:run_and_check(Config, NoCookie, ["version"], return),
+ {undefined, 'a@localhost', []} = rebar_dist_utils:find_options(State5),
+ ok.
+
+from_cli(Config) ->
+ {ok, State0} = rebar_test_utils:run_and_check(Config, [], ["version"], return),
+ {undefined, undefined, []} = rebar_dist_utils:find_options(State0),
+ State1 = rebar_state:command_parsed_args(State0, {[{sname, 'a@localhost'}, {setcookie,abc}], []}),
+ {undefined, 'a@localhost', [{setcookie, abc}]} = rebar_dist_utils:find_options(State1),
+ State2 = rebar_state:command_parsed_args(State0, {[{name, 'a@localhost.x'}, {setcookie,abc}], []}),
+ {'a@localhost.x', undefined, [{setcookie, abc}]} = rebar_dist_utils:find_options(State2),
+ State3 = rebar_state:command_parsed_args(State0, {[{sname, 'a@localhost'}, {name, 'a@localhost.x'}, {setcookie,abc}], []}),
+ {'a@localhost.x', 'a@localhost', [{setcookie, abc}]} = rebar_dist_utils:find_options(State3),
+ State4 = rebar_state:command_parsed_args(State0, {[{setcookie,def}], []}),
+ {undefined, undefined, [{setcookie, def}]} = rebar_dist_utils:find_options(State4),
+ State5 = rebar_state:command_parsed_args(State0, {[{sname, 'a@localhost'}], []}),
+ {undefined, 'a@localhost', []} = rebar_dist_utils:find_options(State5),
+ ok.
+
+overlap(Config) ->
+ %% Make sure that CLI config takes over rebar config without clash for names, though
+ %% cookies can pass through
+ RebarConfig = [{dist_node, [{sname, 'a@localhost'}, {setcookie, abc}]}],
+ {ok, State0} = rebar_test_utils:run_and_check(Config, RebarConfig, ["version"], return),
+ State1 = rebar_state:command_parsed_args(State0, {[{name, 'b@localhost.x'}], []}),
+ {'b@localhost.x', undefined, [{setcookie, abc}]} = rebar_dist_utils:find_options(State1),
+ ok.
+
+from_config_profile(Config) ->
+ %% running as a profile does not create name clashes
+ RebarConfig = [{dist_node, [{sname, 'a@localhost'}, {setcookie, abc}]},
+ {profiles, [ {fake, [{dist_node, [{name, 'a@localhost.x'}]}]} ]}],
+ {ok, State0} = rebar_test_utils:run_and_check(Config, RebarConfig, ["as","fake","version"], return),
+ {'a@localhost.x', undefined, [{setcookie, abc}]} = rebar_dist_utils:find_options(State0),
+ ok.