diff options
Diffstat (limited to 'src/rebar_prv_install_deps.erl')
-rw-r--r-- | src/rebar_prv_install_deps.erl | 26 |
1 files changed, 20 insertions, 6 deletions
diff --git a/src/rebar_prv_install_deps.erl b/src/rebar_prv_install_deps.erl index c9fe0ad..dc208a7 100644 --- a/src/rebar_prv_install_deps.erl +++ b/src/rebar_prv_install_deps.erl @@ -140,7 +140,9 @@ handle_deps_as_profile(Profile, State, Deps, Upgrade) -> DepsDir = profile_dep_dir(State, Profile), Deps1 = rebar_app_utils:parse_deps(DepsDir, Deps, State, Locks, Level), ProfileLevelDeps = [{Profile, Deps1, Level}], - handle_profile_level(ProfileLevelDeps, [], sets:new(), Upgrade, Locks, State). + RootSeen = sets:from_list([rebar_app_info:name(AppInfo) + || AppInfo <- rebar_state:project_apps(State)]), + handle_profile_level(ProfileLevelDeps, [], RootSeen, RootSeen, Upgrade, Locks, State). %% =================================================================== %% Internal functions @@ -153,7 +155,9 @@ deps_per_profile(Profiles, Upgrade, State) -> Deps = lists:foldl(fun(Profile, DepAcc) -> [parsed_profile_deps(State, Profile, Level) | DepAcc] end, [], Profiles), - handle_profile_level(Deps, [], sets:new(), Upgrade, Locks, State). + RootSeen = sets:from_list([rebar_app_info:name(AppInfo) + || AppInfo <- rebar_state:project_apps(State)]), + handle_profile_level(Deps, [], RootSeen, RootSeen, Upgrade, Locks, State). parsed_profile_deps(State, Profile, Level) -> ParsedDeps = rebar_state:get(State, {parsed_deps, Profile}, []), @@ -162,17 +166,27 @@ parsed_profile_deps(State, Profile, Level) -> %% 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([], Apps, _Seen, _Upgrade, _Locks, State) -> +%% +%% There are two 'seen' sets: one for the top-level apps (`RootSeen') and +%% one for all dependencies (`Seen'). The former is used to know when +%% to skip the resolving of dependencies altogether (since they're already +%% top-level apps), while the latter is used to prevent reprocessing +%% deps more than one. +handle_profile_level([], Apps, _RootSeen, _Seen, _Upgrade, _Locks, State) -> {Apps, State}; -handle_profile_level([{Profile, Deps, Level} | Rest], Apps, Seen, Upgrade, Locks, State) -> +handle_profile_level([{Profile, Deps, Level} | Rest], Apps, RootSeen, Seen, Upgrade, Locks, State) -> + Deps0 = [rebar_app_utils:expand_deps_sources(Dep, State) + || Dep <- Deps, + %% skip top-level apps being double-declared + not sets:is_element(rebar_app_info:name(Dep), RootSeen)], {Deps1, Apps1, State1, Seen1} = - update_deps(Profile, Level, Deps, Apps + update_deps(Profile, Level, Deps0, Apps ,State, Upgrade, Seen, Locks), Deps2 = case Deps1 of [] -> Rest; _ -> Rest ++ [{Profile, Deps1, Level+1}] end, - handle_profile_level(Deps2, Apps1, sets:union(Seen, Seen1), Upgrade, Locks, State1). + handle_profile_level(Deps2, Apps1, RootSeen, sets:union(Seen, Seen1), Upgrade, Locks, State1). find_cycles(Apps) -> case rebar_digraph:compile_order(Apps) of |