summaryrefslogtreecommitdiff
path: root/src/rebar_prv_install_deps.erl
diff options
context:
space:
mode:
authorFred Hebert <mononcqc@ferd.ca>2014-12-16 14:43:38 +0000
committerFred Hebert <mononcqc@ferd.ca>2014-12-16 14:43:38 +0000
commit2985c7bed515bd1664313d696f45fe50b4574640 (patch)
treef41beaa5a87ab7364797e9c74d74681791d2dc57 /src/rebar_prv_install_deps.erl
parent449d6baabcebbeb017445430de3c185e147e097b (diff)
Adding pkg deps tests and refactorings
- Adding tests for package deps - Adding conflict/override warnings for package deps - Adding cycle detection for packages - Adding cycle detection for mixed packages+source - Fixing internal dependency format of package resources when converted to rebar_app_info - normalizing level-order prioritization to be based on lexicographical sort of app names rather than traversal order (which is undefined for package deps) - Fixing tests for source deps for deep cycle detection - Fixing bugs with source deps - Relaxed version format checks for test utils A lot of fixes are combined in there because I didn't want to commit non-passing code, and many bugs were found when adding the second batch of tests as part of the original effort.
Diffstat (limited to 'src/rebar_prv_install_deps.erl')
-rw-r--r--src/rebar_prv_install_deps.erl49
1 files changed, 34 insertions, 15 deletions
diff --git a/src/rebar_prv_install_deps.erl b/src/rebar_prv_install_deps.erl
index 5878e8c..3728b70 100644
--- a/src/rebar_prv_install_deps.erl
+++ b/src/rebar_prv_install_deps.erl
@@ -81,15 +81,20 @@ do(State) ->
end,
Source = ProjectApps ++ SrcApps,
- case rebar_digraph:compile_order(Source) of
- {ok, Sort} ->
- {ok, rebar_state:deps_to_build(State1,
- lists:dropwhile(fun rebar_app_info:valid/1
- , Sort -- ProjectApps))};
- {error, {cycles, Cycles}} ->
+ case find_cycles(Source ++ rebar_state:all_deps(State1)) of
+ {cycles, Cycles} ->
?PRV_ERROR({cycles, Cycles});
{error, Error} ->
- {error, Error}
+ {error, Error};
+ no_cycle ->
+ case rebar_digraph:compile_order(Source) of
+ {ok, Sort} ->
+ {ok, rebar_state:deps_to_build(State1,
+ lists:dropwhile(fun rebar_app_info:valid/1,
+ Sort -- ProjectApps))};
+ {error, Error} ->
+ {error, Error}
+ end
end
catch
%% maybe_fetch will maybe_throw an exception to break out of some loops
@@ -97,6 +102,13 @@ do(State) ->
{error, Reason}
end.
+find_cycles(Apps) ->
+ case rebar_digraph:compile_order(Apps) of
+ {error, {cycles, Cycles}} -> {cycles, Cycles};
+ {error, Error} -> {error, Error};
+ {ok, _} -> no_cycle
+ end.
+
-spec format_error(any()) -> iolist().
format_error({cycles, Cycles}) ->
Prints = [["applications: ",
@@ -119,11 +131,9 @@ handle_deps(State, [], _) ->
handle_deps(State, Deps, Update) ->
%% Read in package index and dep graph
{Packages, Graph} = rebar_packages:get_packages(State),
-
%% Split source deps from pkg deps, needed to keep backwards compatibility
DepsDir = rebar_dir:deps_dir(State),
{SrcDeps, PkgDeps} = parse_deps(State, DepsDir, Deps),
-
%% Fetch transitive src deps
{State1, SrcApps, PkgDeps1, Seen} =
update_src_deps(0, SrcDeps, PkgDeps, [], State, Update, sets:new()),
@@ -134,15 +144,16 @@ handle_deps(State, Deps, Update) ->
PkgDeps2 ->
%% Find pkg deps needed
S = case rebar_digraph:cull_deps(Graph, PkgDeps2) of
- {ok, []} ->
+ {ok, [], _} ->
throw({rebar_digraph, no_solution});
- {ok, Solution} ->
+ {ok, Solution, []} ->
+ Solution;
+ {ok, Solution, Discarded} ->
+ [warn_skip_pkg(Pkg) || Pkg <- Discarded],
Solution
end,
-
update_pkg_deps(S, Packages, Update, Seen, State1)
end,
-
AllDeps = lists:ukeymerge(2
,lists:ukeysort(2, SrcApps)
,lists:ukeysort(2, Solved)),
@@ -193,7 +204,8 @@ package_to_app(DepsDir, Packages, {Name, Vsn}) ->
error ->
{error, missing_package};
{ok, P} ->
- PkgDeps = proplists:get_value(<<"deps">>, P, []),
+ PkgDeps = [{atom_to_binary(PkgName,utf8), list_to_binary(PkgVsn)}
+ || {PkgName,PkgVsn} <- proplists:get_value(<<"deps">>, P, [])],
Link = proplists:get_value(<<"link">>, P, ""),
{ok, AppInfo} = rebar_app_info:new(Name, Vsn),
AppInfo1 = rebar_app_info:deps(AppInfo, PkgDeps),
@@ -233,7 +245,9 @@ update_src_deps(Level, SrcDeps, PkgDeps, SrcApps, State, Update, Seen) ->
end,
{SrcDepsAcc1, PkgDepsAcc1, SrcAppsAcc1, StateAcc2, SeenAcc1}
end
- end, {[], PkgDeps, SrcApps, State, Seen}, SrcDeps) of
+ end,
+ {[], PkgDeps, SrcApps, State, Seen},
+ lists:sort(SrcDeps)) of
{[], NewPkgDeps, NewSrcApps, State1, Seen1} ->
{State1, NewSrcApps, NewPkgDeps, Seen1};
{NewSrcDeps, NewPkgDeps, NewSrcApps, State1, Seen1} ->
@@ -427,3 +441,8 @@ warn_skip_deps(AppInfo) ->
"has already been fetched~n",
[rebar_app_info:name(AppInfo),
rebar_app_info:source(AppInfo)]).
+
+warn_skip_pkg({Name, Source}) ->
+ ?WARN("Skipping ~s (version ~s from package index) as an app of the same "
+ "name has already been fetched~n",
+ [Name, Source]).