summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/rebar_prv_install_deps.erl250
1 files changed, 132 insertions, 118 deletions
diff --git a/src/rebar_prv_install_deps.erl b/src/rebar_prv_install_deps.erl
index 8db4761..76b8872 100644
--- a/src/rebar_prv_install_deps.erl
+++ b/src/rebar_prv_install_deps.erl
@@ -74,15 +74,7 @@ do(State) ->
ProjectApps = rebar_state:project_apps(State),
{Apps, State1} =
- lists:foldl(fun(Profile, {AppsAcc, StateAcc}) ->
- Locks = rebar_state:get(StateAcc, {locks, Profile}, []),
- {ok, NewApps, NewState} =
- handle_deps(Profile
- ,StateAcc
- ,rebar_state:get(StateAcc, {deps, Profile}, [])
- ,Locks),
- {NewApps++AppsAcc, NewState}
- end, {[], State}, lists:reverse(Profiles)),
+ lists:foldl(fun deps_per_profile/2, {[], State}, lists:reverse(Profiles)),
Source = ProjectApps ++ Apps,
case find_cycles(Source) of
@@ -91,11 +83,9 @@ do(State) ->
{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))};
+ case compile_order(Source, ProjectApps) of
+ {ok, ToCompile} ->
+ {ok, rebar_state:deps_to_build(State1, ToCompile)};
{error, Error} ->
{error, Error}
end
@@ -106,13 +96,6 @@ 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({parse_dep, Dep}) ->
io_lib:format("Failed parsing dep ~p", [Dep]);
@@ -155,22 +138,8 @@ handle_deps(Profile, State, Deps, Upgrade, Locks) ->
{State1, SrcApps, PkgDeps1, Seen} =
update_src_deps(Profile, 0, SrcDeps, PkgDeps, [], State, Upgrade, sets:new(), Locks),
- {Solved, State2} = case PkgDeps1 of
- [] -> %% No pkg deps
- {[], State1};
- PkgDeps2 ->
- %% Find pkg deps needed
- S = case rebar_digraph:cull_deps(Graph, PkgDeps2) of
- {ok, [], _} ->
- throw({rebar_digraph, no_solution});
- {ok, Solution, []} ->
- Solution;
- {ok, Solution, Discarded} ->
- [warn_skip_pkg(Pkg) || Pkg <- Discarded],
- Solution
- end,
- update_pkg_deps(Profile, S, Packages, Upgrade, Seen, State1)
- end,
+ {Solved, State2} =
+ update_pkg_deps(Profile, Packages, PkgDeps1, Graph, Upgrade, Seen, State1),
AllDeps = lists:ukeymerge(2
,lists:ukeysort(2, SrcApps)
@@ -184,33 +153,74 @@ handle_deps(Profile, State, Deps, Upgrade, Locks) ->
%% Internal functions
%% ===================================================================
+deps_per_profile(Profile, {Apps, State}) ->
+ Locks = rebar_state:get(State, {locks, Profile}, []),
+ ProfileDeps = rebar_state:get(State, {deps, Profile}, []),
+ {ok, NewApps, NewState} = handle_deps(Profile, State, ProfileDeps, Locks),
+ {NewApps++Apps, NewState}.
+
+find_cycles(Apps) ->
+ case rebar_digraph:compile_order(Apps) of
+ {error, {cycles, Cycles}} -> {cycles, Cycles};
+ {error, Error} -> {error, Error};
+ {ok, _} -> no_cycle
+ end.
+
+compile_order(Source, ProjectApps) ->
+ case rebar_digraph:compile_order(Source) of
+ {ok, Sort} ->
+ %% Valid apps are compiled and good
+ {ok, lists:dropwhile(fun rebar_app_info:valid/1, Sort -- ProjectApps)};
+ {error, Error} ->
+ {error, Error}
+ end.
+
+update_pkg_deps(Profile, Packages, PkgDeps, Graph, Upgrade, Seen, State) ->
+ case PkgDeps of
+ [] -> %% No pkg deps
+ {[], State};
+ PkgDeps ->
+ %% Find pkg deps needed
+ S = case rebar_digraph:cull_deps(Graph, PkgDeps) of
+ {ok, [], _} ->
+ throw({rebar_digraph, no_solution});
+ {ok, Solution, []} ->
+ Solution;
+ {ok, Solution, Discarded} ->
+ [warn_skip_pkg(Pkg) || Pkg <- Discarded],
+ Solution
+ end,
+ update_pkg_deps(Profile, S, Packages, Upgrade, Seen, State)
+ end.
+
update_pkg_deps(Profile, Pkgs, Packages, Upgrade, Seen, State) ->
%% Create app_info record for each pkg dep
DepsDir = rebar_dir:deps_dir(State),
{Solved, _, State1}
= lists:foldl(fun(Pkg, {Acc, SeenAcc, StateAcc}) ->
- AppInfo = package_to_app(DepsDir
- ,Packages
- ,Pkg),
- {SeenAcc1, StateAcc1} = maybe_lock(Profile, AppInfo, SeenAcc, StateAcc, 0),
- case maybe_fetch(AppInfo, Upgrade, SeenAcc1, State) of
- true ->
- {[AppInfo | Acc], SeenAcc1, StateAcc1};
- false ->
- {Acc, SeenAcc1, StateAcc1}
- end
+ handle_pkg_dep(Profile, Pkg, Packages, Upgrade, DepsDir, Acc, SeenAcc, StateAcc)
end, {[], Seen, State}, Pkgs),
{Solved, State1}.
+handle_pkg_dep(Profile, Pkg, Packages, Upgrade, DepsDir, Fetched, Seen, State) ->
+ AppInfo = package_to_app(DepsDir, Packages, Pkg),
+ {NewSeen, NewState} = maybe_lock(Profile, AppInfo, Seen, State, 0),
+ case maybe_fetch(AppInfo, Upgrade, NewSeen, NewState) of
+ true ->
+ {[AppInfo | Fetched], NewSeen, NewState};
+ false ->
+ {Fetched, NewSeen, NewState}
+ end.
+
+
maybe_lock(Profile, AppInfo, Seen, State, Level) ->
- Name = rebar_app_info:name(AppInfo),
case Profile of
default ->
+ Name = rebar_app_info:name(AppInfo),
case sets:is_element(Name, Seen) of
false ->
- AppName = rebar_app_info:name(AppInfo),
Locks = rebar_state:lock(State),
- case lists:any(fun(App) -> rebar_app_info:name(App) =:= AppName end, Locks) of
+ case lists:any(fun(App) -> rebar_app_info:name(App) =:= Name end, Locks) of
true ->
{sets:add_element(Name, Seen), State};
false ->
@@ -239,81 +249,78 @@ package_to_app(DepsDir, Packages, {Name, Vsn}) ->
-spec update_src_deps(atom(), non_neg_integer(), list(), list(), list(), rebar_state:t(), boolean(), sets:set(binary()), list()) -> {rebar_state:t(), list(), list(), sets:set(binary())}.
update_src_deps(Profile, Level, SrcDeps, PkgDeps, SrcApps, State, Upgrade, Seen, Locks) ->
- case lists:foldl(fun(AppInfo, {SrcDepsAcc, PkgDepsAcc, SrcAppsAcc, StateAcc, SeenAcc, LocksAcc}) ->
- %% If not seen, add to list of locks to write out
- Name = rebar_app_info:name(AppInfo),
- case sets:is_element(Name, SeenAcc) of
- true ->
- %% If from lock file don't print warning about skipping
- case lists:keymember(Name, 1, Locks) of
- false ->
- warn_skip_deps(AppInfo);
- true ->
- ok
- end,
- %% scan for app children here if upgrading
- case Upgrade of
- false ->
- {SrcDepsAcc, PkgDepsAcc, SrcAppsAcc, StateAcc, SeenAcc, LocksAcc};
- true ->
- {SrcDepsAcc1, PkgDepsAcc1, SrcAppsAcc1, StateAcc2, LocksAcc1} =
- handle_dep(AppInfo
- ,SrcDepsAcc
- ,PkgDepsAcc
- ,SrcAppsAcc
- ,Level
- ,StateAcc
- ,LocksAcc),
-
- {SrcDepsAcc1, PkgDepsAcc1, SrcAppsAcc1, StateAcc2, SeenAcc, LocksAcc1}
- end;
- false ->
- {SeenAcc1, StateAcc1} = maybe_lock(Profile, AppInfo, SeenAcc, StateAcc, Level),
- {SrcDepsAcc1, PkgDepsAcc1, SrcAppsAcc1, StateAcc2, LocksAcc1} =
- case Upgrade of
- true ->
- %{true, UpgradeName, UpgradeLevel} ->
- handle_upgrade(AppInfo
- ,SrcDepsAcc
- ,PkgDepsAcc
- ,SrcAppsAcc
- ,Level
- ,StateAcc1
- ,LocksAcc);
- _ ->
- maybe_fetch(AppInfo, false, SeenAcc, StateAcc),
- handle_dep(AppInfo
- ,SrcDepsAcc
- ,PkgDepsAcc
- ,SrcAppsAcc
- ,Level
- ,StateAcc1
- ,LocksAcc)
- end,
- {SrcDepsAcc1, PkgDepsAcc1, SrcAppsAcc1, StateAcc2, SeenAcc1, LocksAcc1}
- end
- end,
- {[], PkgDeps, SrcApps, State, Seen, Locks},
- rebar_utils:sort_deps(SrcDeps)) of
+ case lists:foldl(
+ fun(AppInfo, {SrcDepsAcc, PkgDepsAcc, SrcAppsAcc, StateAcc, SeenAcc, LocksAcc}) ->
+ update_src_dep(AppInfo, Profile, Level,
+ SrcDepsAcc, PkgDepsAcc, SrcAppsAcc, StateAcc,
+ Upgrade, SeenAcc, Locks, LocksAcc)
+ end,
+ {[], PkgDeps, SrcApps, State, Seen, Locks},
+ rebar_utils:sort_deps(SrcDeps)) of
{[], NewPkgDeps, NewSrcApps, State1, Seen1, _NewLocks} ->
{State1, NewSrcApps, NewPkgDeps, Seen1};
{NewSrcDeps, NewPkgDeps, NewSrcApps, State1, Seen1, NewLocks} ->
update_src_deps(Profile, Level+1, NewSrcDeps, NewPkgDeps, NewSrcApps, State1, Upgrade, Seen1, NewLocks)
end.
+update_src_dep(AppInfo, Profile, Level, SrcDeps, PkgDeps, SrcApps, State, Upgrade, Seen, BaseLocks, Locks) ->
+ %% If not seen, add to list of locks to write out
+ Name = rebar_app_info:name(AppInfo),
+ case sets:is_element(Name, Seen) of
+ true ->
+ update_seen_src_dep(AppInfo, Level,
+ SrcDeps, PkgDeps, SrcApps,
+ State, Upgrade, Seen, BaseLocks, Locks);
+ false ->
+ update_unseen_src_dep(AppInfo, Profile, Level,
+ SrcDeps, PkgDeps, SrcApps,
+ State, Upgrade, Seen, Locks)
+
+ end.
+
+update_seen_src_dep(AppInfo, Level, SrcDeps, PkgDeps, SrcApps, State, Upgrade, Seen, BaseLocks, Locks) ->
+ Name = rebar_app_info:name(AppInfo),
+ %% If seen from lock file don't print warning about skipping
+ case lists:keymember(Name, 1, BaseLocks) of
+ false ->
+ warn_skip_deps(AppInfo);
+ true ->
+ ok
+ end,
+ %% scan for app children here if upgrading
+ case Upgrade of
+ false ->
+ {SrcDeps, PkgDeps, SrcApps, State, Seen, Locks};
+ true ->
+ {NewSrcDeps, NewPkgDeps, NewSrcApps, NewState, NewLocks}
+ = handle_dep(AppInfo, SrcDeps, PkgDeps, SrcApps,
+ Level, State, Locks),
+ {NewSrcDeps, NewPkgDeps, NewSrcApps, NewState, Seen, NewLocks}
+ end.
+
+update_unseen_src_dep(AppInfo, Profile, Level, SrcDeps, PkgDeps, SrcApps, State, Upgrade, Seen, Locks) ->
+ {NewSeen, State1} = maybe_lock(Profile, AppInfo, Seen, State, Level),
+ {NewSrcDeps, NewPkgDeps, NewSrcApps, State2, NewLocks}
+ = case Upgrade of
+ true ->
+ handle_upgrade(AppInfo, SrcDeps, PkgDeps, SrcApps,
+ Level, State1, Locks);
+ _ ->
+ %% why do we use the old state there?
+ maybe_fetch(AppInfo, false, Seen, State),
+ handle_dep(AppInfo, SrcDeps, PkgDeps, SrcApps,
+ Level, State1, Locks)
+ end,
+ {NewSrcDeps, NewPkgDeps, NewSrcApps, State2, NewSeen, NewLocks}.
+
handle_upgrade(AppInfo, SrcDeps, PkgDeps, SrcApps, Level, State, Locks) ->
Name = rebar_app_info:name(AppInfo),
case lists:keyfind(Name, 1, Locks) of
false ->
case maybe_fetch(AppInfo, true, sets:new(), State) of
true ->
- handle_dep(AppInfo
- ,SrcDeps
- ,PkgDeps
- ,SrcApps
- ,Level
- ,State
- ,Locks);
+ handle_dep(AppInfo, SrcDeps, PkgDeps, SrcApps,
+ Level, State, Locks);
false ->
{[AppInfo|SrcDeps], PkgDeps, SrcApps, State, Locks}
@@ -359,12 +366,11 @@ handle_dep(State, DepsDir, AppInfo, Locks, Level) ->
sets:set(binary()), rebar_state:t()) -> boolean().
maybe_fetch(AppInfo, Upgrade, Seen, State) ->
AppDir = ec_cnv:to_list(rebar_app_info:dir(AppInfo)),
- Apps = rebar_app_discover:find_apps(["_checkouts"], all),
- case rebar_app_utils:find(rebar_app_info:name(AppInfo), Apps) of
- {ok, _} ->
- %% Don't fetch dep if it exists in the _checkouts dir
+ %% Don't fetch dep if it exists in the _checkouts dir
+ case in_checkouts(AppInfo) of
+ true ->
false;
- error ->
+ false ->
case not app_exists(AppDir) of
true ->
fetch_app(AppInfo, AppDir, State);
@@ -378,6 +384,14 @@ maybe_fetch(AppInfo, Upgrade, Seen, State) ->
end
end.
+in_checkouts(AppInfo) ->
+ Apps = rebar_app_discover:find_apps(["_checkouts"], all),
+ case rebar_app_utils:find(rebar_app_info:name(AppInfo), Apps) of
+ {ok, _} -> true;
+ error -> false
+ end.
+
+
-spec parse_deps(binary(), list(), list(), list(), integer()) -> {[rebar_app_info:t()], [pkg_dep()]}.
parse_deps(DepsDir, Deps, State, Locks, Level) ->
lists:foldl(fun(Dep, Acc) ->