From be49c5cd44d536c440b3188f3e0a5279218ea4fc Mon Sep 17 00:00:00 2001 From: Tristan Sloughter Date: Tue, 17 Feb 2015 10:04:12 -0600 Subject: use project sub-apps with deps in their rebar.config --- src/rebar_app_discover.erl | 21 +++++++++++++++++++-- src/rebar_prv_install_deps.erl | 2 +- test/rebar_deps_SUITE.erl | 30 +++++++++++++++++++++++++++++- 3 files changed, 49 insertions(+), 4 deletions(-) diff --git a/src/rebar_app_discover.erl b/src/rebar_app_discover.erl index 21dbe1b..0dc062f 100644 --- a/src/rebar_app_discover.erl +++ b/src/rebar_app_discover.erl @@ -16,16 +16,33 @@ do(State, LibDirs) -> Dirs = [filename:join(BaseDir, LibDir) || LibDir <- LibDirs], Apps = find_apps(Dirs, all), ProjectDeps = rebar_state:deps_names(State), + lists:foldl(fun(AppInfo, StateAcc) -> + StateAcc1 = merge_deps(AppInfo, StateAcc), ProjectDeps1 = lists:delete(rebar_app_info:name(AppInfo), ProjectDeps), - rebar_state:project_apps(StateAcc, rebar_app_info:deps(AppInfo, ProjectDeps1)) - end, State, Apps). + rebar_state:project_apps(StateAcc1 + ,rebar_app_info:deps(AppInfo, ProjectDeps1)) + end, State, Apps). format_error({module_list, File}) -> io_lib:format("Error reading module list from ~p~n", [File]); format_error({missing_module, Module}) -> io_lib:format("Module defined in app file missing: ~p~n", [Module]). +merge_deps(AppInfo, State) -> + Profiles = rebar_state:current_profiles(State), + Name = rebar_app_info:name(AppInfo), + C = rebar_config:consult(rebar_app_info:dir(AppInfo)), + AppState = rebar_state:apply_overrides( + rebar_state:apply_profiles( + rebar_state:new(State, C, rebar_app_info:dir(AppInfo)), Profiles), Name), + lists:foldl(fun(Profile, StateAcc) -> + AppProfDeps = rebar_state:get(AppState, {deps, Profile}, []), + TopLevelProfDeps = rebar_state:get(StateAcc, {deps, Profile}, []), + ProfDeps2 = lists:keymerge(1, TopLevelProfDeps, AppProfDeps), + rebar_state:set(StateAcc, {deps, Profile}, ProfDeps2) + end, State, lists:reverse(Profiles)). + -spec all_app_dirs(list(file:name())) -> list(file:name()). all_app_dirs(LibDirs) -> lists:flatmap(fun(LibDir) -> diff --git a/src/rebar_prv_install_deps.erl b/src/rebar_prv_install_deps.erl index 61fbd70..d922522 100644 --- a/src/rebar_prv_install_deps.erl +++ b/src/rebar_prv_install_deps.erl @@ -267,7 +267,7 @@ update_src_deps(Profile, Level, SrcDeps, PkgDeps, SrcApps, State, Upgrade, Seen, ,StateAcc ,LocksAcc), - {SrcDepsAcc1, PkgDepsAcc1, SrcAppsAcc1, StateAcc2, SeenAcc, LocksAcc1} + {SrcDepsAcc1, PkgDepsAcc1, SrcAppsAcc1, StateAcc2, SeenAcc, LocksAcc1} end; false -> {SeenAcc1, StateAcc1} = maybe_lock(Profile, AppInfo, SeenAcc, StateAcc, Level), diff --git a/test/rebar_deps_SUITE.erl b/test/rebar_deps_SUITE.erl index 633e9a2..3228bc6 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() -> [{group, git}, {group, pkg}]. +all() -> [sub_app_deps, {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(sub_app_deps, Config) -> + rebar_test_utils:init_rebar_state(Config); init_per_testcase(Case, Config) -> {Deps, Warnings, Expect} = deps(Case), Expected = case Expect of @@ -191,6 +193,32 @@ circular1(Config) -> run(Config). circular2(Config) -> run(Config). circular_skip(Config) -> run(Config). +%% Test that the deps of project apps that have their own rebar.config +%% are included, but that top level rebar.config deps take precedence +sub_app_deps(Config) -> + AppDir = ?config(apps, Config), + Deps = expand_deps(git, [{"a", "1.0.0", []} + ,{"b", "1.0.0", []} + ,{"b", "2.0.0", []}]), + mock_git_resource:mock([{deps, flat_deps(Deps)}]), + + Name = rebar_test_utils:create_random_name("sub_app1_"), + Vsn = rebar_test_utils:create_random_vsn(), + + SubAppsDir = filename:join([AppDir, Name]), + SubDeps = top_level_deps(expand_deps(git, [{"a", "1.0.0", []} + ,{"b", "2.0.0", []}])), + rebar_test_utils:create_app(SubAppsDir, Name, Vsn, [kernel, stdlib]), + rebar_test_utils:create_config(SubAppsDir, [{deps, SubDeps}]), + + 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, "a"}, {dep, "b", "1.0.0"}]}). + + run(Config) -> {ok, RebarConfig} = file:consult(?config(rebarconfig, Config)), rebar_test_utils:run_and_check( -- cgit v1.1 From 8874e414a80f7f29e3a8c8f00b3887399a7a6cbc Mon Sep 17 00:00:00 2001 From: Tristan Sloughter Date: Thu, 19 Feb 2015 08:13:56 -0600 Subject: sort project apps before merging deps --- src/rebar_app_discover.erl | 4 +++- src/rebar_prv_install_deps.erl | 12 +----------- src/rebar_utils.erl | 12 +++++++++++- 3 files changed, 15 insertions(+), 13 deletions(-) diff --git a/src/rebar_app_discover.erl b/src/rebar_app_discover.erl index 0dc062f..df2211e 100644 --- a/src/rebar_app_discover.erl +++ b/src/rebar_app_discover.erl @@ -17,12 +17,14 @@ do(State, LibDirs) -> Apps = find_apps(Dirs, all), ProjectDeps = rebar_state:deps_names(State), + %% Sort apps so we get the same merged deps config everytime + SortedApps = rebar_utils:sort_deps(Apps), lists:foldl(fun(AppInfo, StateAcc) -> StateAcc1 = merge_deps(AppInfo, StateAcc), ProjectDeps1 = lists:delete(rebar_app_info:name(AppInfo), ProjectDeps), rebar_state:project_apps(StateAcc1 ,rebar_app_info:deps(AppInfo, ProjectDeps1)) - end, State, Apps). + end, State, SortedApps). format_error({module_list, File}) -> io_lib:format("Error reading module list from ~p~n", [File]); diff --git a/src/rebar_prv_install_deps.erl b/src/rebar_prv_install_deps.erl index d922522..8db4761 100644 --- a/src/rebar_prv_install_deps.erl +++ b/src/rebar_prv_install_deps.erl @@ -44,8 +44,6 @@ -define(PROVIDER, install_deps). -define(DEPS, [app_discovery]). --define(APP_NAME_INDEX, 2). - -type src_dep() :: {atom(), {atom(), string(), string()}} | {atom(), string(), {atom(), string(), string()}}. -type pkg_dep() :: {atom(), binary()} | atom(). @@ -296,7 +294,7 @@ update_src_deps(Profile, Level, SrcDeps, PkgDeps, SrcApps, State, Upgrade, Seen, end end, {[], PkgDeps, SrcApps, State, Seen, Locks}, - sort_deps(SrcDeps)) of + rebar_utils:sort_deps(SrcDeps)) of {[], NewPkgDeps, NewSrcApps, State1, Seen1, _NewLocks} -> {State1, NewSrcApps, NewPkgDeps, Seen1}; {NewSrcDeps, NewPkgDeps, NewSrcApps, State1, Seen1, NewLocks} -> @@ -486,14 +484,6 @@ maybe_upgrade(AppInfo, AppDir, true, State) -> false end. -sort_deps(Deps) -> - %% We need a sort stable, based on the name. So that for multiple deps on - %% the same level with the same name, we keep the order the parents had. - %% `lists:keysort/2' is documented as stable in the stdlib. - %% The list of deps is revered when we get it. For the proper stable - %% result, re-reverse it. - lists:keysort(?APP_NAME_INDEX, lists:reverse(Deps)). - -spec parse_goal(binary(), binary()) -> pkg_dep(). parse_goal(Name, Constraint) -> case re:run(Constraint, "([^\\d]*)(\\d.*)", [{capture, [1,2], binary}]) of diff --git a/src/rebar_utils.erl b/src/rebar_utils.erl index 85f59d6..943c0d7 100644 --- a/src/rebar_utils.erl +++ b/src/rebar_utils.erl @@ -26,7 +26,8 @@ %% ------------------------------------------------------------------- -module(rebar_utils). --export([droplast/1, +-export([sort_deps/1, + droplast/1, filtermap/2, is_arch/1, sh/2, @@ -56,11 +57,20 @@ -include("rebar.hrl"). -define(ONE_LEVEL_INDENT, " "). +-define(APP_NAME_INDEX, 2). %% ==================================================================== %% Public API %% ==================================================================== +sort_deps(Deps) -> + %% We need a sort stable, based on the name. So that for multiple deps on + %% the same level with the same name, we keep the order the parents had. + %% `lists:keysort/2' is documented as stable in the stdlib. + %% The list of deps is revered when we get it. For the proper stable + %% result, re-reverse it. + lists:keysort(?APP_NAME_INDEX, lists:reverse(Deps)). + droplast(L) -> lists:reverse(tl(lists:reverse(L))). -- cgit v1.1