From 02e33a265bff8c76ebc6f1ddfc0f8fa8515874aa Mon Sep 17 00:00:00 2001 From: Tristan Sloughter Date: Mon, 16 Feb 2015 08:29:02 -0600 Subject: check for newly added deps in config file that aren't level 0 in the lock --- src/rebar3.erl | 12 +----------- src/rebar_config.erl | 37 ++++++++++++++++++++++++++++++++++++- test/rebar_deps_SUITE.erl | 44 ++++++++++++++++++++++++++++++++++++++++---- 3 files changed, 77 insertions(+), 16 deletions(-) diff --git a/src/rebar3.erl b/src/rebar3.erl index 268be68..03b7b98 100644 --- a/src/rebar3.erl +++ b/src/rebar3.erl @@ -142,15 +142,7 @@ init_config() -> rebar_config:consult_file(ConfigFile) end, - Config1 = case rebar_config:consult_file(?LOCK_FILE) of - [D] -> - %% We want the top level deps only from the lock file. - %% This ensures deterministic overrides for configs. - Deps = [X || X <- D, element(3, X) =:= 0], - [{{locks, default}, D}, {{deps, default}, Deps} | Config]; - _ -> - Config - end, + Config1 = rebar_config:merge_locks(Config, rebar_config:consult_file(?LOCK_FILE)), %% If $HOME/.rebar3/config exists load and use as global config Home = rebar_dir:home_dir(), @@ -229,8 +221,6 @@ version() -> ?CONSOLE("rebar ~s on Erlang/OTP ~s Erts ~s", [Vsn, erlang:system_info(otp_release), erlang:system_info(version)]). - - %% TODO: Actually make it 'global' %% %% set global flag based on getopt option boolean value diff --git a/src/rebar_config.erl b/src/rebar_config.erl index 949d6d4..43730ea 100644 --- a/src/rebar_config.erl +++ b/src/rebar_config.erl @@ -27,7 +27,9 @@ -module(rebar_config). -export([consult/1 - ,consult_file/1]). + ,consult_file/1 + + ,merge_locks/2]). -include("rebar.hrl"). @@ -58,6 +60,18 @@ consult_file(File) -> end end. +merge_locks(Config, []) -> + Config; +merge_locks(Config, [Locks]) -> + {deps, ConfigDeps} = lists:keyfind(deps, 1, Config), + %% We want the top level deps only from the lock file. + %% This ensures deterministic overrides for configs. + %% Then check if any new deps have been added to the config + %% since it was locked. + Deps = [X || X <- Locks, element(3, X) =:= 0], + NewDeps = find_newly_added(ConfigDeps, Locks), + [{{locks, default}, Locks}, {{deps, default}, NewDeps++Deps} | Config]. + %% =================================================================== %% Internal functions %% =================================================================== @@ -84,3 +98,24 @@ bs(Vars) -> lists:foldl(fun({K,V}, Bs) -> erl_eval:add_binding(K, V, Bs) end, erl_eval:new_bindings(), Vars). + +%% Find deps that have been added to the config after the lock was created +find_newly_added(ConfigDeps, LockedDeps) -> + [Dep || Dep <- ConfigDeps, + begin + NewDep = ec_cnv:to_binary(element(1, Dep)), + case lists:keyfind(NewDep, 1, LockedDeps) of + false -> + true; + Match -> + case element(3, Match) of + 0 -> + true; + _ -> + ?WARN("Newly added dep ~s is locked at a lower level. " + "If you really want to unlock it, use 'rebar3 upgrade ~s'", + [NewDep, NewDep]), + false + end + end + end]. diff --git a/test/rebar_deps_SUITE.erl b/test/rebar_deps_SUITE.erl index 3228bc6..0e5c6fe 100644 --- a/test/rebar_deps_SUITE.erl +++ b/test/rebar_deps_SUITE.erl @@ -3,7 +3,7 @@ -include_lib("common_test/include/ct.hrl"). -include_lib("eunit/include/eunit.hrl"). -all() -> [sub_app_deps, {group, git}, {group, pkg}]. +all() -> [sub_app_deps, newly_added_dep, {group, git}, {group, pkg}]. groups() -> [{all, [], [flat, pick_highest_left, pick_highest_right, @@ -29,6 +29,8 @@ init_per_group(_, Config) -> end_per_group(_, Config) -> Config. +init_per_testcase(newly_added_dep, Config) -> + rebar_test_utils:init_rebar_state(Config); init_per_testcase(sub_app_deps, Config) -> rebar_test_utils:init_rebar_state(Config); init_per_testcase(Case, Config) -> @@ -129,9 +131,9 @@ expand_deps(pkg, [{Name, Vsn, Deps} | Rest]) -> setup_project(Case, Config0, Deps) -> DepsType = ?config(deps_type, Config0), Config = rebar_test_utils:init_rebar_state( - Config0, - atom_to_list(Case)++"_"++atom_to_list(DepsType)++"_" - ), + Config0, + atom_to_list(Case)++"_"++atom_to_list(DepsType)++"_" + ), AppDir = ?config(apps, Config), rebar_test_utils:create_app(AppDir, "A", "0.0.0", [kernel, stdlib]), TopDeps = top_level_deps(Deps), @@ -218,6 +220,40 @@ sub_app_deps(Config) -> Config, RebarConfig, ["compile"], {ok, [{app, Name}, {dep, "a"}, {dep, "b", "1.0.0"}]}). +%% Newly added dependency after locking +newly_added_dep(Config) -> + AppDir = ?config(apps, Config), + Deps = expand_deps(git, [{"a", "1.0.0", []} + ,{"b", "1.0.0", [{"c", "1.0.0", []}]} + ,{"c", "2.0.0", []}]), + mock_git_resource:mock([{deps, flat_deps(Deps)}]), + + Name = rebar_test_utils:create_random_name("app_"), + Vsn = rebar_test_utils:create_random_vsn(), + + SubAppsDir = filename:join([AppDir, Name]), + rebar_test_utils:create_app(SubAppsDir, Name, Vsn, [kernel, stdlib]), + + TopDeps = top_level_deps(expand_deps(git, [{"b", "1.0.0", []}])), + {ok, RebarConfig} = file:consult(rebar_test_utils:create_config(AppDir, [{deps, TopDeps}])), + rebar_test_utils:run_and_check( + Config, RebarConfig, ["compile"], + {ok, [{app, Name}, {dep, "b", "1.0.0"}, {dep, "c", "1.0.0"}]}), + + %% Add a and c to top level + TopDeps2 = top_level_deps(expand_deps(git, [{"a", "1.0.0", []} + ,{"c", "2.0.0", []} + ,{"b", "1.0.0", []}])), + {ok, RebarConfig2} = file:consult(rebar_test_utils:create_config(AppDir, [{deps, TopDeps2}])), + LockFile = filename:join(AppDir, "rebar.lock"), + RebarConfig3 = rebar_config:merge_locks(RebarConfig2, + rebar_config:consult_file(LockFile)), + + %% a should now be installed and c should not change + rebar_test_utils:run_and_check( + Config, RebarConfig3, ["compile"], + {ok, [{app, Name}, {dep, "a"}, {dep, "b", "1.0.0"}, {dep, "c", "1.0.0"}]}). + run(Config) -> {ok, RebarConfig} = file:consult(?config(rebarconfig, Config)), -- cgit v1.1