summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.travis.yml27
-rw-r--r--README.md2
-rwxr-xr-xbootstrap6
-rw-r--r--rebar.config5
-rw-r--r--rebar.lock4
-rw-r--r--src/rebar.hrl2
-rw-r--r--src/rebar3.erl17
-rw-r--r--src/rebar_app_utils.erl7
-rw-r--r--src/rebar_config.erl18
-rw-r--r--src/rebar_dir.erl1
-rw-r--r--src/rebar_git_resource.erl13
-rw-r--r--src/rebar_hooks.erl28
-rw-r--r--src/rebar_prv_cover.erl24
-rw-r--r--src/rebar_prv_edoc.erl8
-rw-r--r--src/rebar_prv_path.erl8
-rw-r--r--src/rebar_prv_shell.erl8
-rw-r--r--src/rebar_prv_update.erl12
-rw-r--r--src/rebar_prv_upgrade.erl24
-rw-r--r--src/rebar_prv_xref.erl22
-rw-r--r--test/rebar_cover_SUITE.erl8
-rw-r--r--test/rebar_ct_SUITE.erl2
-rw-r--r--test/rebar_dir_SUITE.erl36
-rw-r--r--test/rebar_upgrade_SUITE.erl52
23 files changed, 237 insertions, 97 deletions
diff --git a/.travis.yml b/.travis.yml
index ab2d28d..a45cb05 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,27 +1,24 @@
sudo: false
language: erlang
-install: "true"
+install: 'true'
otp_release:
- - 18.0
- - 17.5
- - R16B03-1
- - R15B03
+- 18.0
+- 17.5
+- R16B03-1
+- R15B03
before_script: "./bootstrap"
script: "./rebar3 ct"
branches:
only:
- - master
+ - master
cache:
directories:
- - $HOME/.cache/rebar3/hex/default
-before_deploy: "rm -rf !(rebar3)"
+ - "$HOME/.cache/rebar3/hex/default"
deploy:
+ provider: releases
+ api_key:
+ secure: MjloYuaQF3cd3Oab57zqwPDLPqt5MDgBIrRLpXOQwNovr2tnkKd4aJK3QJ3pTxvZievjgl+qIYI1IZyjuRV37nkjAfMw14iig959wi0k8XTJoMdylVxE5X7hk4SiWhX/ycnJx3C28PPw1OitGTF76HAJDMgEelNdoNt+hvjvDEo=
+ file: rebar3
on:
+ repo: erlang/rebar3
tags: true
- condition: $TRAVIS_OTP_RELEASE = R16B03-1
- provider: s3
- access_key_id: AKIAJAPYAQEFYCYSNL7Q
- secret_access_key:
- secure: "BUv2KQABv0Q4e8DAVNBRTc/lXHWt27yCN46Fdgo1IrcSSIiP+hq2yXzQcXLbPwkEu6pxUZQtL3mvKbt6l7uw3wFrcRfFAi1PGTITAW8MTmxtwcZIBcHSk3XOzDbkK+fYYcaddszmt7hDzzEFPtmYXiNgnaMIVeynhQLgcCcIRRQ="
- bucket: "rebar3"
- skip_cleanup: true
diff --git a/README.md b/README.md
index 7560ab0..f44c7bd 100644
--- a/README.md
+++ b/README.md
@@ -53,7 +53,7 @@ best experience you can get.
## Getting Started
-A [getting started guide is maintained on the offcial documentation website](http://www.rebar3.org/docs/getting-started),
+A [getting started guide is maintained on the official documentation website](http://www.rebar3.org/docs/getting-started),
but installing rebar3 can be done by any of the ways described below
Nightly compiled version:
diff --git a/bootstrap b/bootstrap
index 35759b0..f52779e 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.1.0", filename:absname("_build/default/lib/rebar/")),
+ {ok, App} = rebar_app_info:new(rebar, "3.1.1", 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
@@ -350,7 +350,7 @@ format_error(AbsSource, Extra, {Mod, Desc}) ->
io_lib:format("~s: ~s~s~n", [AbsSource, Extra, ErrorDesc]).
additional_defines() ->
- [{d, D} || {Re, D} <- [{"^[0-9]+", namespaced_types}, {"^R1[4|5]", deprecated_crypto}], is_otp_release(Re)].
+ [{d, D} || {Re, D} <- [{"^[0-9]+", namespaced_types}, {"^R1[4|5]", deprecated_crypto}, {"^((1[8|9])|2)", rand_module}], is_otp_release(Re)].
is_otp_release(ArchRegex) ->
case re:run(otp_release(), ArchRegex, [{capture, none}]) of
diff --git a/rebar.config b/rebar.config
index fcd62b8..ea5af27 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.20.0"},
+{deps, [{erlware_commons, "0.21.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.18.0"},
+ {relx, "3.19.0"},
{cf, "0.2.1"},
{cth_readable, "1.2.2"},
{eunit_formatters, "0.3.1"}]}.
@@ -51,6 +51,7 @@
%% Overrides
{overrides, [{override, erlware_commons, [{erl_opts, [{platform_define, "^[0-9]+", namespaced_types},
{platform_define, "^R1[4|5]", deprecated_crypto},
+ {platform_define, "^((1[8|9])|2)", rand_module},
no_debug_info,
warnings_as_errors]},
{deps, []}, {plugins, []}]},
diff --git a/rebar.lock b/rebar.lock
index 9451024..40463ac 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.20.0">>},0},
+ {<<"erlware_commons">>,{pkg,<<"erlware_commons">>,<<"0.21.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.18.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 c96b191..4d69c7b 100644
--- a/src/rebar.hrl
+++ b/src/rebar.hrl
@@ -23,7 +23,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/rebar3.erl b/src/rebar3.erl
index 4564b8a..82b4472 100644
--- a/src/rebar3.erl
+++ b/src/rebar3.erl
@@ -129,13 +129,20 @@ run_aux(State, RawArgs) ->
%% Initializing project_plugins which can override default providers
State6 = rebar_plugins:project_plugins_install(State5),
State7 = rebar_plugins:top_level_install(State6),
- State8 = rebar_state:default(State7, rebar_state:opts(State7)),
+ State8 = case os:getenv("REBAR_CACHE_DIR") of
+ false ->
+ State7;
+ ConfigFile ->
+ rebar_state:set(State7, global_rebar_dir, ConfigFile)
+ end,
+
+ State9 = rebar_state:default(State8, rebar_state:opts(State8)),
{Task, Args} = parse_args(RawArgs),
- State9 = rebar_state:code_paths(State8, default, code:get_path()),
+ State10 = rebar_state:code_paths(State9, default, code:get_path()),
- rebar_core:init_command(rebar_state:command_args(State9, Args), Task).
+ rebar_core:init_command(rebar_state:command_args(State10, Args), Task).
init_config() ->
%% Initialize logging system
@@ -270,11 +277,11 @@ handle_error({error, {Module, Reason}}) ->
?DEBUG("Uncaught error: ~p ~p", [Module, Reason]),
?INFO("When submitting a bug report, please include the output of `rebar3 report \"your command\"`", []);
_ ->
- ?ERROR(Module:format_error(Reason), [])
+ ?ERROR("~s", [Module:format_error(Reason)])
end,
erlang:halt(1);
handle_error({error, Error}) when is_list(Error) ->
- ?ERROR(Error, []),
+ ?ERROR("~s", [Error]),
erlang:halt(1);
handle_error(Error) ->
%% Nothing should percolate up from rebar_core;
diff --git a/src/rebar_app_utils.erl b/src/rebar_app_utils.erl
index d3ef841..957526e 100644
--- a/src/rebar_app_utils.erl
+++ b/src/rebar_app_utils.erl
@@ -134,7 +134,12 @@ parse_dep(Parent, {Name, Source}, DepsDir, IsLock, State) when is_tuple(Source)
dep_to_app(Parent, DepsDir, Name, [], Source, IsLock, State);
parse_dep(Parent, {Name, _Vsn, Source}, DepsDir, IsLock, State) when is_tuple(Source) ->
dep_to_app(Parent, DepsDir, Name, [], Source, IsLock, State);
-parse_dep(Parent, {Name, _Vsn, Source, Opts}, DepsDir, IsLock, State) when is_tuple(Source) ->
+parse_dep(Parent, {Name, _Vsn, Source, Opts}, DepsDir, IsLock, State) when is_tuple(Source),
+ is_list(Opts) ->
+ ?WARN("Dependency option list ~p in ~p is not supported and will be ignored", [Opts, Name]),
+ dep_to_app(Parent, DepsDir, Name, [], Source, IsLock, State);
+parse_dep(Parent, {Name, Source, Opts}, DepsDir, IsLock, State) when is_tuple(Source),
+ is_list(Opts) ->
?WARN("Dependency option list ~p in ~p is not supported and will be ignored", [Opts, Name]),
dep_to_app(Parent, DepsDir, Name, [], Source, IsLock, State);
parse_dep(Parent, {Name, {pkg, PkgName, Vsn}, Level}, DepsDir, IsLock, State) when is_integer(Level) ->
diff --git a/src/rebar_config.erl b/src/rebar_config.erl
index 8d7bcf4..836980e 100644
--- a/src/rebar_config.erl
+++ b/src/rebar_config.erl
@@ -180,6 +180,24 @@ check_newly_added({Name, _, Source}, LockedDeps) ->
check_newly_added(Dep, LockedDeps) ->
check_newly_added_(Dep, LockedDeps).
+%% get [raw] deps out of the way
+check_newly_added_({Name, Source, Opts}, LockedDeps) when is_tuple(Source),
+ is_list(Opts) ->
+ case check_newly_added_(Name, LockedDeps) of
+ {true, Name1} ->
+ {true, {Name1, Source}};
+ false ->
+ false
+ end;
+check_newly_added_({Name,_Vsn,Source,Opts}, LockedDeps) when is_tuple(Source),
+ is_list(Opts) ->
+ case check_newly_added_(Name, LockedDeps) of
+ {true, Name1} ->
+ {true, {Name1, Source}};
+ false ->
+ false
+ end;
+%% and on to regular deps
check_newly_added_({Name, Vsn, Source}, LockedDeps) ->
case check_newly_added_(Name, LockedDeps) of
{true, Name1} ->
diff --git a/src/rebar_dir.erl b/src/rebar_dir.erl
index 3729704..1ec58d4 100644
--- a/src/rebar_dir.erl
+++ b/src/rebar_dir.erl
@@ -92,6 +92,7 @@ global_config() ->
Home = home_dir(),
filename:join([Home, ".config", "rebar3", "rebar.config"]).
+-spec global_cache_dir(rebar_dict()) -> file:filename_all().
global_cache_dir(Opts) ->
Home = home_dir(),
rebar_opts:get(Opts, global_rebar_dir, filename:join([Home, ".cache", "rebar3"])).
diff --git a/src/rebar_git_resource.erl b/src/rebar_git_resource.erl
index 5a6a5ef..f0f5f03 100644
--- a/src/rebar_git_resource.erl
+++ b/src/rebar_git_resource.erl
@@ -17,10 +17,17 @@
lock(AppDir, {git, Url, _}) ->
lock(AppDir, {git, Url});
lock(AppDir, {git, Url}) ->
- AbortMsg = io_lib:format("Locking of git dependency failed in ~s", [AppDir]),
+ AbortMsg = lists:flatten(io_lib:format("Locking of git dependency failed in ~s", [AppDir])),
+ Dir = rebar_utils:escape_double_quotes(AppDir),
{ok, VsnString} =
- rebar_utils:sh("git --git-dir=\"" ++ rebar_utils:escape_double_quotes(AppDir) ++ "/.git\" rev-parse --verify HEAD",
- [{use_stdout, false}, {debug_abort_on_error, AbortMsg}]),
+ case os:type() of
+ {win32, _} ->
+ rebar_utils:sh("git rev-parse --git-dir=\"" ++ Dir ++ "/.git\" --work-tree=\"" ++ Dir ++ "\" --verify HEAD",
+ [{use_stdout, false}, {debug_abort_on_error, AbortMsg}]);
+ _ ->
+ rebar_utils:sh("git --git-dir=\"" ++ Dir ++ "/.git\" rev-parse --verify HEAD",
+ [{use_stdout, false}, {debug_abort_on_error, AbortMsg}])
+ end,
Ref = string:strip(VsnString, both, $\n),
{git, Url, {ref, Ref}}.
diff --git a/src/rebar_hooks.erl b/src/rebar_hooks.erl
index 3af17ca..d6a0e2b 100644
--- a/src/rebar_hooks.erl
+++ b/src/rebar_hooks.erl
@@ -38,18 +38,22 @@ run_provider_hooks(Dir, Type, Command, Providers, Opts, State) ->
run_provider_hooks_(_Dir, _Type, _Command, _Providers, [], State) ->
State;
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),
- HookProviders = proplists:get_all_values(Command, TypeHooks),
- case rebar_core:do(HookProviders, State1) of
- {error, ProviderName} ->
- ?DEBUG(format_error({bad_provider, Type, Command, ProviderName}), []),
- throw(?PRV_ERROR({bad_provider, Type, Command, ProviderName}));
- {ok, State2} ->
- rebar_utils:remove_from_code_path(PluginDepsPaths),
- State2
+ case proplists:get_all_values(Command, TypeHooks) of
+ [] ->
+ State;
+ HookProviders ->
+ PluginDepsPaths = lists:usort(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),
+ case rebar_core:do(HookProviders, State1) of
+ {error, ProviderName} ->
+ ?DEBUG(format_error({bad_provider, Type, Command, ProviderName}), []),
+ throw(?PRV_ERROR({bad_provider, Type, Command, ProviderName}));
+ {ok, State2} ->
+ rebar_utils:remove_from_code_path(PluginDepsPaths),
+ State2
+ end
end.
format_error({bad_provider, Type, Command, {Name, Namespace}}) ->
diff --git a/src/rebar_prv_cover.erl b/src/rebar_prv_cover.erl
index c915141..464967b 100644
--- a/src/rebar_prv_cover.erl
+++ b/src/rebar_prv_cover.erl
@@ -296,9 +296,9 @@ strip_coverdir(File) ->
cover_compile(State, apps) ->
Apps = filter_checkouts(rebar_state:project_apps(State)),
AppDirs = app_dirs(Apps),
- ExtraDirs = extra_src_dirs(State, Apps),
- cover_compile(State, lists:filter(fun(D) -> ec_file:is_dir(D) end, AppDirs ++ ExtraDirs));
+ cover_compile(State, lists:filter(fun(D) -> ec_file:is_dir(D) end, AppDirs));
cover_compile(State, Dirs) ->
+ rebar_utils:update_code(rebar_state:code_paths(State, all_deps), [soft_purge]),
%% start the cover server if necessary
{ok, CoverPid} = start_cover(),
%% redirect cover output
@@ -316,27 +316,15 @@ cover_compile(State, Dirs) ->
%% print any warnings about modules that failed to cover compile
lists:foreach(fun print_cover_warnings/1, lists:flatten(Results))
end
- end, Dirs).
+ end, Dirs),
+ rebar_utils:cleanup_code_path(rebar_state:code_paths(State, default)),
+ ok.
app_dirs(Apps) ->
lists:foldl(fun app_ebin_dirs/2, [], Apps).
app_ebin_dirs(App, Acc) ->
- AppDir = rebar_app_info:ebin_dir(App),
- ExtraDirs = rebar_dir:extra_src_dirs(rebar_app_info:opts(App), []),
- OutDir = rebar_app_info:out_dir(App),
- [AppDir] ++ [filename:join([OutDir, D]) || D <- ExtraDirs] ++ Acc.
-
-extra_src_dirs(State, Apps) ->
- BaseDir = rebar_state:dir(State),
- F = fun(App) -> rebar_app_info:dir(App) == BaseDir end,
- %% check that this app hasn't already been dealt with
- Extras = case lists:any(F, Apps) of
- false -> rebar_dir:extra_src_dirs(rebar_state:opts(State), []);
- true -> []
- end,
- OutDir = rebar_dir:base_dir(State),
- [filename:join([OutDir, "extras", D]) || D <- Extras].
+ [rebar_app_info:ebin_dir(App)|Acc].
filter_checkouts(Apps) -> filter_checkouts(Apps, []).
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_path.erl b/src/rebar_prv_path.erl
index 4e88496..4259eec 100644
--- a/src/rebar_prv_path.erl
+++ b/src/rebar_prv_path.erl
@@ -77,15 +77,15 @@ paths([{rel, true}|Rest], Apps, State, Acc) ->
base_dir(State) -> io_lib:format("~s", [rebar_dir:base_dir(State)]).
bin_dir(State) -> io_lib:format("~s/bin", [rebar_dir:base_dir(State)]).
-lib_dir(State) -> io_lib:format("~s/lib", [rebar_dir:base_dir(State)]).
+lib_dir(State) -> io_lib:format("~s", [rebar_dir:deps_dir(State)]).
rel_dir(State) -> io_lib:format("~s/rel", [rebar_dir:base_dir(State)]).
ebin_dirs(Apps, State) ->
- lists:map(fun(App) -> io_lib:format("~s/lib/~s/ebin", [rebar_dir:base_dir(State), App]) end, Apps).
+ lists:map(fun(App) -> io_lib:format("~s/~s/ebin", [rebar_dir:deps_dir(State), App]) end, Apps).
priv_dirs(Apps, State) ->
- lists:map(fun(App) -> io_lib:format("~s/lib/~s/priv", [rebar_dir:base_dir(State), App]) end, Apps).
+ lists:map(fun(App) -> io_lib:format("~s/~s/priv", [rebar_dir:deps_dir(State), App]) end, Apps).
src_dirs(Apps, State) ->
- lists:map(fun(App) -> io_lib:format("~s/lib/~s/src", [rebar_dir:base_dir(State), App]) end, Apps).
+ lists:map(fun(App) -> io_lib:format("~s/~s/src", [rebar_dir:deps_dir(State), App]) end, Apps).
print_paths_if_exist(Paths, State) ->
{RawOpts, _} = rebar_state:command_parsed_args(State),
diff --git a/src/rebar_prv_shell.erl b/src/rebar_prv_shell.erl
index ab496c6..a5457ad 100644
--- a/src/rebar_prv_shell.erl
+++ b/src/rebar_prv_shell.erl
@@ -108,6 +108,10 @@ shell(State) ->
simulate_proc_lib(),
true = register(rebar_agent, self()),
{ok, GenState} = rebar_agent:init(State),
+ %% Hack to fool the init process into thinking we have stopped and the normal
+ %% node start process can go on. Without it, init:get_status() always return
+ %% '{starting, started}' instead of '{started, started}'
+ init ! {'EXIT', self(), normal},
gen_server:enter_loop(rebar_agent, [], GenState, {local, rebar_agent}, hibernate).
info() ->
@@ -192,7 +196,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()]),
diff --git a/src/rebar_prv_update.erl b/src/rebar_prv_update.erl
index 5e1e253..54b135e 100644
--- a/src/rebar_prv_update.erl
+++ b/src/rebar_prv_update.erl
@@ -114,14 +114,14 @@ hex_to_index(State) ->
ets:foldl(fun({Pkg, [[]]}, _) when is_binary(Pkg) ->
true;
- ({Pkg, [Vsns=[Vsn | _Rest]]}, _) when is_binary(Pkg) ->
+ ({Pkg, [Vsns=[_Vsn | _Rest]]}, _) when is_binary(Pkg) ->
%% Verify the package is of the right build tool by checking if the first
%% version exists in the table from the foldl above
- case ets:member(?PACKAGE_TABLE, {Pkg, Vsn}) of
- true ->
- ets:insert(?PACKAGE_TABLE, {Pkg, Vsns});
- false ->
- true
+ case [V || V <- Vsns, ets:member(?PACKAGE_TABLE, {Pkg, V})] of
+ [] ->
+ true;
+ Vsns1 ->
+ ets:insert(?PACKAGE_TABLE, {Pkg, Vsns1})
end;
(_, _) ->
true
diff --git a/src/rebar_prv_upgrade.erl b/src/rebar_prv_upgrade.erl
index c5c43e4..18c307b 100644
--- a/src/rebar_prv_upgrade.erl
+++ b/src/rebar_prv_upgrade.erl
@@ -45,7 +45,29 @@ init(State) ->
do(State) ->
{Args, _} = rebar_state:command_parsed_args(State),
Locks = rebar_state:get(State, {locks, default}, []),
- Deps = rebar_state:get(State, deps, []),
+ %% We have 3 sources of dependencies to upgrade from:
+ %% 1. the top-level rebar.config (in `deps', dep name is an atom)
+ %% 2. the app-level rebar.config in umbrella apps (in `{deps, default}',
+ %% where the dep name is an atom)
+ %% 3. the formatted sources for all after app-parsing (in `{deps, default}',
+ %% where the reprocessed app name is a binary)
+ %%
+ %% The gotcha with these is that the selection of dependencies with a
+ %% binary name (those that are stable and usable internally) is done with
+ %% in the profile deps only, but while accounting for locks.
+ %% Because our job here is to unlock those that have changed, we must
+ %% instead use the atom-based names, both in `deps' and `{deps, default}',
+ %% as those are the dependencies that may have changed but have been
+ %% disregarded by locks.
+ %%
+ %% As such, the working set of dependencies is the addition of
+ %% `deps' and `{deps, default}' entries with an atom name, as those
+ %% disregard locks and parsed values post-selection altogether.
+ %% Packages without versions can of course be a single atom.
+ TopDeps = rebar_state:get(State, deps, []),
+ ProfileDeps = rebar_state:get(State, {deps, default}, []),
+ Deps = [Dep || Dep <- TopDeps ++ ProfileDeps, % TopDeps > ProfileDeps
+ is_atom(Dep) orelse is_atom(element(1, Dep))],
Names = parse_names(ec_cnv:to_binary(proplists:get_value(package, Args, <<"">>)), Locks),
DepsDict = deps_dict(rebar_state:all_deps(State)),
case prepare_locks(Names, Deps, Locks, [], DepsDict) of
diff --git a/src/rebar_prv_xref.erl b/src/rebar_prv_xref.erl
index f600273..45badd3 100644
--- a/src/rebar_prv_xref.erl
+++ b/src/rebar_prv_xref.erl
@@ -38,10 +38,10 @@ init(State) ->
do(State) ->
code:add_pathsa(rebar_state:code_paths(State, all_deps)),
XrefChecks = prepare(State),
-
+ XrefIgnores = rebar_state:get(State, xref_ignores, []),
%% Run xref checks
?INFO("Running cross reference analysis...", []),
- XrefResults = xref_checks(XrefChecks),
+ XrefResults = xref_checks(XrefChecks, XrefIgnores),
%% Run custom queries
QueryChecks = rebar_state:get(State, xref_queries, []),
@@ -110,16 +110,18 @@ prepare(State) ->
sets:from_list(ConfXrefChecks))),
XrefChecks.
-xref_checks(XrefChecks) ->
- lists:foldl(fun run_xref_check/2, [], XrefChecks).
+xref_checks(XrefChecks, XrefIgnores) ->
+ run_xref_checks(XrefChecks, XrefIgnores, []).
-run_xref_check(XrefCheck, Acc) ->
+run_xref_checks([], _XrefIgnores, Acc) ->
+ Acc;
+run_xref_checks([XrefCheck | T], XrefIgnores, Acc) ->
{ok, Results} = xref:analyze(xref, XrefCheck),
- case filter_xref_results(XrefCheck, Results) of
+ case filter_xref_results(XrefCheck, XrefIgnores, Results) of
[] ->
- Acc;
+ run_xref_checks(T, XrefIgnores, Acc);
FilterResult ->
- [{XrefCheck, FilterResult} | Acc]
+ run_xref_checks(T, XrefIgnores, [{XrefCheck, FilterResult} | Acc])
end.
check_query({Query, Value}, Acc) ->
@@ -170,7 +172,7 @@ get_behaviour_callbacks(_XrefCheck, _Attributes) ->
parse_xref_result({_, MFAt}) -> MFAt;
parse_xref_result(MFAt) -> MFAt.
-filter_xref_results(XrefCheck, XrefResults) ->
+filter_xref_results(XrefCheck, XrefIgnores, XrefResults) ->
SearchModules = lists:usort(
lists:map(
fun({Mt,_Ft,_At}) -> Mt;
@@ -178,7 +180,7 @@ filter_xref_results(XrefCheck, XrefResults) ->
(_) -> undefined
end, XrefResults)),
- Ignores = lists:flatmap(fun(Module) ->
+ Ignores = XrefIgnores ++ lists:flatmap(fun(Module) ->
get_xref_ignorelist(Module, XrefCheck)
end, SearchModules),
diff --git a/test/rebar_cover_SUITE.erl b/test/rebar_cover_SUITE.erl
index a838d7d..841e29f 100644
--- a/test/rebar_cover_SUITE.erl
+++ b/test/rebar_cover_SUITE.erl
@@ -90,7 +90,7 @@ basic_extra_src_dirs(Config) ->
{file, _} = cover:is_compiled(Mod),
ExtraMod = list_to_atom(lists:flatten(io_lib:format("~ts_extra", [Name]))),
- {file, _} = cover:is_compiled(ExtraMod).
+ false = cover:is_compiled(ExtraMod).
release_extra_src_dirs(Config) ->
AppDir = ?config(apps, Config),
@@ -129,9 +129,9 @@ release_extra_src_dirs(Config) ->
{file, _} = cover:is_compiled(Mod2),
ExtraMod1 = list_to_atom(lists:flatten(io_lib:format("~ts_extra", [Name1]))),
- {file, _} = cover:is_compiled(ExtraMod1),
+ false = cover:is_compiled(ExtraMod1),
ExtraMod2 = list_to_atom(lists:flatten(io_lib:format("~ts_extra", [Name2]))),
- {file, _} = cover:is_compiled(ExtraMod2).
+ false = cover:is_compiled(ExtraMod2).
root_extra_src_dirs(Config) ->
AppDir = ?config(apps, Config),
@@ -160,7 +160,7 @@ root_extra_src_dirs(Config) ->
Mod2 = list_to_atom(Name2),
{file, _} = cover:is_compiled(Mod2),
- {file, _} = cover:is_compiled(extra).
+ false = cover:is_compiled(extra).
index_written(Config) ->
AppDir = ?config(apps, Config),
diff --git a/test/rebar_ct_SUITE.erl b/test/rebar_ct_SUITE.erl
index 1da7571..e409c29 100644
--- a/test/rebar_ct_SUITE.erl
+++ b/test/rebar_ct_SUITE.erl
@@ -726,7 +726,7 @@ suite_at_app_root(Config) ->
data_dir_correct(Config) ->
DataDir = ?config(data_dir, Config),
Parts = filename:split(DataDir),
- ["rebar_ct_SUITE_data","test","rebar","lib","test","_build"|_] = lists:reverse(Parts).
+ ["rebar_ct_SUITE_data","test","rebar","lib",_,"_build"|_] = lists:reverse(Parts).
cmd_label(Config) ->
State = ?config(result, Config),
diff --git a/test/rebar_dir_SUITE.erl b/test/rebar_dir_SUITE.erl
index 1221db7..9734830 100644
--- a/test/rebar_dir_SUITE.erl
+++ b/test/rebar_dir_SUITE.erl
@@ -6,6 +6,7 @@
-export([src_dirs/1, extra_src_dirs/1, all_src_dirs/1]).
-export([profile_src_dirs/1, profile_extra_src_dirs/1, profile_all_src_dirs/1]).
-export([retarget_path/1, alt_base_dir_abs/1, alt_base_dir_rel/1]).
+-export([global_cache_dir/1, default_global_cache_dir/1, overwrite_default_global_cache_dir/1]).
-include_lib("common_test/include/ct.hrl").
-include_lib("eunit/include/eunit.hrl").
@@ -15,8 +16,20 @@
all() -> [default_src_dirs, default_extra_src_dirs, default_all_src_dirs,
src_dirs, extra_src_dirs, all_src_dirs,
profile_src_dirs, profile_extra_src_dirs, profile_all_src_dirs,
- retarget_path, alt_base_dir_abs, alt_base_dir_rel].
-
+ retarget_path, alt_base_dir_abs, alt_base_dir_rel, global_cache_dir,
+ default_global_cache_dir, overwrite_default_global_cache_dir].
+
+init_per_testcase(default_global_cache_dir, Config) ->
+ [{apps, AppsDir}, {checkouts, CheckoutsDir}, {state, _State} | Config] = rebar_test_utils:init_rebar_state(Config),
+ NewState = rebar_state:new([{base_dir, filename:join([AppsDir, "_build"])}
+ ,{root_dir, AppsDir}]),
+ [{apps, AppsDir}, {checkouts, CheckoutsDir}, {state, NewState} | Config];
+init_per_testcase(overwrite_default_global_cache_dir, Config) ->
+ os:putenv("REBAR_CACHE_DIR", ?config(priv_dir, Config)),
+ [{apps, AppsDir}, {checkouts, CheckoutsDir}, {state, _State} | Config] = rebar_test_utils:init_rebar_state(Config),
+ NewState = rebar_state:new([{base_dir, filename:join([AppsDir, "_build"])}
+ ,{root_dir, AppsDir}]),
+ [{apps, AppsDir}, {checkouts, CheckoutsDir}, {state, NewState} | Config];
init_per_testcase(_, Config) ->
C = rebar_test_utils:init_rebar_state(Config),
AppDir = ?config(apps, C),
@@ -162,3 +175,22 @@ alt_base_dir_rel(Config) ->
?assert(filelib:is_dir(filename:join([BaseDir, "lib", Name2, "ebin"]))),
?assert(filelib:is_file(filename:join([BaseDir, "lib", Name2, "ebin", Name2++".app"]))),
?assert(filelib:is_file(filename:join([BaseDir, "lib", Name2, "ebin", Name2++".beam"]))).
+
+global_cache_dir(Config) ->
+ RebarConfig = [{erl_opts, []}],
+ {ok, State} = rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], return),
+ DataDir = ?config(priv_dir, Config),
+ Expected = filename:join([DataDir, "cache"]),
+ ?assertEqual(Expected, rebar_dir:global_cache_dir(rebar_state:opts(State))).
+
+default_global_cache_dir(Config) ->
+ RebarConfig = [{erl_opts, []}],
+ {ok, State} = rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], return),
+ Expected = filename:join([rebar_dir:home_dir(), ".cache", "rebar3"]),
+ ?assertEqual(Expected, rebar_dir:global_cache_dir(rebar_state:opts(State))).
+
+overwrite_default_global_cache_dir(Config) ->
+ RebarConfig = [{erl_opts, []}],
+ {ok, State} = rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], return),
+ Expected = ?config(priv_dir, Config),
+ ?assertEqual(Expected, rebar_dir:global_cache_dir(rebar_state:opts(State))).
diff --git a/test/rebar_upgrade_SUITE.erl b/test/rebar_upgrade_SUITE.erl
index cfe1d8a..e7651a1 100644
--- a/test/rebar_upgrade_SUITE.erl
+++ b/test/rebar_upgrade_SUITE.erl
@@ -11,7 +11,7 @@ groups() ->
triplet_a, triplet_b, triplet_c,
tree_a, tree_b, tree_c, tree_c2, tree_cj, tree_ac, tree_all,
delete_d, promote, stable_lock, fwd_lock,
- compile_upgrade_parity]},
+ compile_upgrade_parity, umbrella_config]},
{git, [], [{group, all}]},
{pkg, [], [{group, all}]}].
@@ -66,6 +66,18 @@ end_per_testcase(_, Config) ->
meck:unload(),
Config.
+setup_project(Case=umbrella_config, Config0, Deps, UpDeps) ->
+ DepsType = ?config(deps_type, Config0),
+ NameRoot = atom_to_list(Case)++"_"++atom_to_list(DepsType),
+ Config = rebar_test_utils:init_rebar_state(Config0, NameRoot++"_"),
+ AppDir = filename:join([?config(apps, Config), "apps", NameRoot]),
+ rebar_test_utils:create_app(AppDir, "Root", "0.0.0", [kernel, stdlib]),
+ TopDeps = rebar_test_utils:top_level_deps(Deps),
+ TopConf = rebar_test_utils:create_config(AppDir, [{deps, []}]),
+ RebarConf = rebar_test_utils:create_config(AppDir, [{deps, TopDeps}]),
+ [{rebarconfig, TopConf},
+ {rebarumbrella, RebarConf},
+ {next_top_deps, rebar_test_utils:top_level_deps(UpDeps)} | Config];
setup_project(Case, Config0, Deps, UpDeps) ->
DepsType = ?config(deps_type, Config0),
Config = rebar_test_utils:init_rebar_state(
@@ -437,7 +449,12 @@ upgrades(compile_upgrade_parity) ->
[],
{"", [{"A","1"}, "D", "J", "E", {"I","1"},
{"B","1"}, "F", "G",
- {"C","1"}, "H"]}}.
+ {"C","1"}, "H"]}};
+upgrades(umbrella_config) ->
+ {[{"A", "1", []}],
+ [{"A", "2", []}],
+ ["A"],
+ {"A", [{"A","2"}]}}.
%% TODO: add a test that verifies that unlocking files and then
%% running the upgrade code is enough to properly upgrade things.
@@ -570,9 +587,36 @@ compile_upgrade_parity(Config) ->
?assertEqual(CompileLockData1, CompileLockData2),
?assertEqual(CompileLockData1, UpgradeLockData).
+umbrella_config(Config) ->
+ apply(?config(mock, Config), []),
+ {ok, TopConfig} = file:consult(?config(rebarconfig, Config)),
+ %% Install dependencies before re-mocking for an upgrade
+ rebar_test_utils:run_and_check(Config, TopConfig, ["lock"], {ok, []}),
+ {App, Unlocks} = ?config(expected, Config),
+ ct:pal("Upgrades: ~p -> ~p", [App, Unlocks]),
+ Expectation = case Unlocks of
+ {error, Term} -> {error, Term};
+ _ -> {ok, Unlocks}
+ end,
+
+ meck:new(rebar_prv_upgrade, [passthrough]),
+ meck:expect(rebar_prv_upgrade, do, fun(S) ->
+ apply(?config(mock_update, Config), []),
+ meck:passthrough([S])
+ end),
+ _NewRebarConf = rebar_test_utils:create_config(filename:dirname(?config(rebarumbrella, Config)),
+ [{deps, ?config(next_top_deps, Config)}]),
+ %% re-run from the top-level with the old config still in place;
+ %% detection must happen when going for umbrella apps!
+ rebar_test_utils:run_and_check(
+ Config, TopConfig, ["upgrade", App], Expectation
+ ),
+ meck:unload(rebar_prv_upgrade).
+
run(Config) ->
apply(?config(mock, Config), []),
- {ok, RebarConfig} = file:consult(?config(rebarconfig, Config)),
+ ConfigPath = ?config(rebarconfig, Config),
+ {ok, RebarConfig} = file:consult(ConfigPath),
%% Install dependencies before re-mocking for an upgrade
rebar_test_utils:run_and_check(Config, RebarConfig, ["lock"], {ok, []}),
{App, Unlocks} = ?config(expected, Config),
@@ -587,7 +631,7 @@ run(Config) ->
apply(?config(mock_update, Config), []),
meck:passthrough([S])
end),
- NewRebarConf = rebar_test_utils:create_config(?config(apps, Config),
+ NewRebarConf = rebar_test_utils:create_config(filename:dirname(ConfigPath),
[{deps, ?config(next_top_deps, Config)}]),
{ok, NewRebarConfig} = file:consult(NewRebarConf),
rebar_test_utils:run_and_check(