summaryrefslogtreecommitdiff
path: root/src/rebar_prv_install_deps.erl
diff options
context:
space:
mode:
Diffstat (limited to 'src/rebar_prv_install_deps.erl')
-rw-r--r--src/rebar_prv_install_deps.erl156
1 files changed, 103 insertions, 53 deletions
diff --git a/src/rebar_prv_install_deps.erl b/src/rebar_prv_install_deps.erl
index c535b4d..5aa34c3 100644
--- a/src/rebar_prv_install_deps.erl
+++ b/src/rebar_prv_install_deps.erl
@@ -82,13 +82,9 @@ do(State) ->
?PRV_ERROR({cycles, Cycles});
{error, Error} ->
{error, Error};
- no_cycle ->
- case compile_order(Source, ProjectApps) of
- {ok, ToCompile} ->
- {ok, rebar_state:deps_to_build(State1, ToCompile)};
- {error, Error} ->
- {error, Error}
- end
+ {no_cycle, Sorted} ->
+ ToCompile = cull_compile(Sorted, ProjectApps),
+ {ok, rebar_state:deps_to_build(State1, ToCompile)}
end
catch
%% maybe_fetch will maybe_throw an exception to break out of some loops
@@ -132,30 +128,39 @@ handle_deps(Profile, State, Deps, Locks) when is_list(Locks) ->
handle_deps(_Profile, State, [], _, _) ->
{ok, [], State};
handle_deps(Profile, State0, Deps, Upgrade, Locks) ->
- %% Read in package index and dep graph
- {Packages, Graph} = rebar_state:packages(State0),
- Registry = rebar_packages:registry(State0),
- State = rebar_state:packages(rebar_state:registry(State0, Registry), {Packages, Graph}),
%% Split source deps from pkg deps, needed to keep backwards compatibility
- DepsDir = rebar_dir:deps_dir(State),
- {SrcDeps, PkgDeps} = parse_deps(DepsDir, Deps, State, Locks, 0),
+ DepsDir = profile_dep_dir(State0, Profile),
+
+ {SrcDeps, PkgDeps} = parse_deps(DepsDir, Deps, State0, Locks, 0),
%% Fetch transitive src deps
- {State1, SrcApps, PkgDeps1, Seen} =
- update_src_deps(Profile, 0, SrcDeps, PkgDeps, [], State, Upgrade, sets:new(), Locks),
+ {State1, SrcApps, PkgDeps1, Seen} = update_src_deps(Profile, 0, SrcDeps, PkgDeps, []
+ ,State0, Upgrade, sets:new(), Locks),
- {Solved, State2} =
- update_pkg_deps(Profile, Packages, PkgDeps1, Graph, Upgrade, Seen, State1),
+ {Solved, State4} =
+ case PkgDeps1 of
+ [] ->
+ {[], State1};
+ _ ->
+ %% Read in package index and dep graph
+ {Packages, Graph} = rebar_state:packages(State1),
+ Registry = rebar_packages:registry(State1),
+ State2 = rebar_state:packages(rebar_state:registry(State1, Registry)
+ ,{Packages, Graph}),
+
+ update_pkg_deps(Profile, Packages, PkgDeps1
+ ,Graph, Upgrade, Seen, State2)
+ end,
AllDeps = lists:ukeymerge(2
,lists:ukeysort(2, SrcApps)
,lists:ukeysort(2, Solved)),
- %% Sort all apps to build order
- State3 = rebar_state:all_deps(State2, AllDeps),
+
+ State5 = rebar_state:update_all_deps(State4, AllDeps),
CodePaths = [rebar_app_info:ebin_dir(A) || A <- AllDeps],
- ok = code:add_pathsa(CodePaths),
+ State6 = rebar_state:update_code_paths(State5, all_deps, CodePaths),
- {ok, AllDeps, State3}.
+ {ok, AllDeps, State6}.
%% ===================================================================
%% Internal functions
@@ -171,17 +176,11 @@ find_cycles(Apps) ->
case rebar_digraph:compile_order(Apps) of
{error, {cycles, Cycles}} -> {cycles, Cycles};
{error, Error} -> {error, Error};
- {ok, _} -> no_cycle
+ {ok, Sorted} -> {no_cycle, Sorted}
end.
-compile_order(Source, ProjectApps) ->
- case rebar_digraph:compile_order(Source) of
- {ok, Sort} ->
- %% Valid apps are compiled and good
- {ok, lists:dropwhile(fun not_needs_compile/1, Sort -- ProjectApps)};
- {error, Error} ->
- {error, Error}
- end.
+cull_compile(TopSortedDeps, ProjectApps) ->
+ lists:dropwhile(fun not_needs_compile/1, TopSortedDeps -- ProjectApps).
update_pkg_deps(Profile, Packages, PkgDeps, Graph, Upgrade, Seen, State) ->
case PkgDeps of
@@ -203,7 +202,7 @@ update_pkg_deps(Profile, Packages, PkgDeps, Graph, Upgrade, Seen, State) ->
update_pkg_deps(Profile, Pkgs, Packages, Upgrade, Seen, State) ->
%% Create app_info record for each pkg dep
- DepsDir = rebar_dir:deps_dir(State),
+ DepsDir = profile_dep_dir(State, Profile),
{Solved, _, State1}
= lists:foldl(fun(Pkg, {Acc, SeenAcc, StateAcc}) ->
handle_pkg_dep(Profile, Pkg, Packages, Upgrade, DepsDir, Acc, SeenAcc, StateAcc)
@@ -214,7 +213,7 @@ handle_pkg_dep(Profile, Pkg, Packages, Upgrade, DepsDir, Fetched, Seen, State) -
AppInfo = package_to_app(DepsDir, Packages, Pkg),
Level = rebar_app_info:dep_level(AppInfo),
{NewSeen, NewState} = maybe_lock(Profile, AppInfo, Seen, State, Level),
- {_, AppInfo1} = maybe_fetch(AppInfo, Upgrade, Seen, NewState),
+ {_, AppInfo1} = maybe_fetch(AppInfo, Profile, Upgrade, Seen, NewState),
{[AppInfo1 | Fetched], NewSeen, NewState}.
maybe_lock(Profile, AppInfo, Seen, State, Level) ->
@@ -252,7 +251,7 @@ package_to_app(DepsDir, Packages, {Name, Vsn, Level}) ->
|| {PkgName,PkgVsn} <- proplists:get_value(<<"deps">>, P, [])],
{ok, AppInfo} = rebar_app_info:new(Name, Vsn),
AppInfo1 = rebar_app_info:deps(AppInfo, PkgDeps),
- AppInfo2 = rebar_app_info:dir(AppInfo1, rebar_dir:deps_dir(DepsDir, Name)),
+ AppInfo2 = rebar_app_info:dir(AppInfo1, filename:join([DepsDir, Name])),
AppInfo3 = rebar_app_info:dep_level(AppInfo2, Level),
rebar_app_info:source(AppInfo3, {pkg, Name, Vsn})
end.
@@ -278,7 +277,7 @@ update_src_dep(AppInfo, Profile, Level, SrcDeps, PkgDeps, SrcApps, State, Upgrad
Name = rebar_app_info:name(AppInfo),
case sets:is_element(Name, Seen) of
true ->
- update_seen_src_dep(AppInfo, Level,
+ update_seen_src_dep(AppInfo, Profile, Level,
SrcDeps, PkgDeps, SrcApps,
State, Upgrade, Seen, BaseLocks, Locks);
false ->
@@ -288,7 +287,13 @@ update_src_dep(AppInfo, Profile, Level, SrcDeps, PkgDeps, SrcApps, State, Upgrad
end.
-update_seen_src_dep(AppInfo, Level, SrcDeps, PkgDeps, SrcApps, State, Upgrade, Seen, BaseLocks, Locks) ->
+profile_dep_dir(State, Profile) ->
+ case Profile of
+ default -> filename:join([rebar_dir:profile_dir(State, [default]), rebar_state:get(State, deps_dir, ?DEFAULT_DEPS_DIR)]);
+ _ -> rebar_dir:deps_dir(State)
+ end.
+
+update_seen_src_dep(AppInfo, Profile, 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
@@ -303,7 +308,7 @@ update_seen_src_dep(AppInfo, Level, SrcDeps, PkgDeps, SrcApps, State, Upgrade, S
{SrcDeps, PkgDeps, SrcApps, State, Seen, Locks};
true ->
{NewSrcDeps, NewPkgDeps, NewSrcApps, NewState, NewLocks}
- = handle_dep(AppInfo, SrcDeps, PkgDeps, SrcApps,
+ = handle_dep(AppInfo, Profile, SrcDeps, PkgDeps, SrcApps,
Level, State, Locks),
{NewSrcDeps, NewPkgDeps, NewSrcApps, NewState, Seen, NewLocks}
end.
@@ -313,22 +318,22 @@ update_unseen_src_dep(AppInfo, Profile, Level, SrcDeps, PkgDeps, SrcApps, State,
{NewSrcDeps, NewPkgDeps, NewSrcApps, State2, NewLocks}
= case Upgrade of
true ->
- handle_upgrade(AppInfo, SrcDeps, PkgDeps, SrcApps,
+ handle_upgrade(AppInfo, Profile, SrcDeps, PkgDeps, SrcApps,
Level, State1, Locks);
_ ->
- {_, AppInfo1} = maybe_fetch(AppInfo, false, Seen, State1),
- handle_dep(AppInfo1, SrcDeps, PkgDeps, SrcApps,
+ {_, AppInfo1} = maybe_fetch(AppInfo, Profile, false, Seen, State1),
+ handle_dep(AppInfo1, Profile, SrcDeps, PkgDeps, SrcApps,
Level, State1, Locks)
end,
{NewSrcDeps, NewPkgDeps, NewSrcApps, State2, NewSeen, NewLocks}.
-handle_upgrade(AppInfo, SrcDeps, PkgDeps, SrcApps, Level, State, Locks) ->
+handle_upgrade(AppInfo, Profile, 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
+ case maybe_fetch(AppInfo, Profile, true, sets:new(), State) of
{true, AppInfo1} ->
- handle_dep(AppInfo1, SrcDeps, PkgDeps, SrcApps,
+ handle_dep(AppInfo1, Profile, SrcDeps, PkgDeps, SrcApps,
Level, State, Locks);
{false, AppInfo1} ->
@@ -338,8 +343,8 @@ handle_upgrade(AppInfo, SrcDeps, PkgDeps, SrcApps, Level, State, Locks) ->
{[AppInfo|SrcDeps], PkgDeps, SrcApps, State, Locks}
end.
-handle_dep(AppInfo, SrcDeps, PkgDeps, SrcApps, Level, State, Locks) ->
- DepsDir = rebar_dir:deps_dir(State),
+handle_dep(AppInfo, Profile, SrcDeps, PkgDeps, SrcApps, Level, State, Locks) ->
+ DepsDir = profile_dep_dir(State, Profile),
{AppInfo1, NewSrcDeps, NewPkgDeps, NewLocks, State1} =
handle_dep(State, DepsDir, AppInfo, Locks, Level),
AppInfo2 = rebar_app_info:dep_level(AppInfo1, Level),
@@ -374,9 +379,9 @@ handle_dep(State, DepsDir, AppInfo, Locks, Level) ->
{SrcDeps, PkgDeps} = parse_deps(DepsDir, Deps, S3, Locks, Level),
{AppInfo2, SrcDeps, PkgDeps, Locks++NewLocks, State1}.
--spec maybe_fetch(rebar_app_info:t(), boolean() | {true, binary(), integer()},
+-spec maybe_fetch(rebar_app_info:t(), atom(), boolean() | {true, binary(), integer()},
sets:set(binary()), rebar_state:t()) -> {boolean(), rebar_app_info:t()}.
-maybe_fetch(AppInfo, Upgrade, Seen, State) ->
+maybe_fetch(AppInfo, Profile, Upgrade, Seen, State) ->
AppDir = ec_cnv:to_list(rebar_app_info:dir(AppInfo)),
%% Don't fetch dep if it exists in the _checkouts dir
case rebar_app_info:is_checkout(AppInfo) of
@@ -385,22 +390,27 @@ maybe_fetch(AppInfo, Upgrade, Seen, State) ->
false ->
case rebar_app_discover:find_app(AppDir, all) of
false ->
- case in_default(AppInfo, State) of
+ case already_in_default(AppInfo, State) of
false ->
- {fetch_app(AppInfo, AppDir, State), AppInfo};
+ case fetch_app(AppInfo, AppDir, State) of
+ true ->
+ maybe_symlink_default(State, Profile, AppDir, AppInfo),
+ {true, update_app_info(AppInfo)};
+ Other ->
+ {Other, AppInfo}
+ end;
{true, FoundApp} ->
%% Preserve the state we created with overrides
AppState = rebar_app_info:state(AppInfo),
FoundApp1 = rebar_app_info:state(FoundApp, AppState),
- ?INFO("Linking ~s to ~s", [rebar_app_info:dir(FoundApp1), AppDir]),
- filelib:ensure_dir(AppDir),
- rebar_file_utils:symlink_or_copy(rebar_app_info:dir(FoundApp1), AppDir),
+ symlink_dep(rebar_app_info:dir(FoundApp1), AppDir),
{true, FoundApp1}
end;
{true, AppInfo1} ->
%% Preserve the state we created with overrides
AppState = rebar_app_info:state(AppInfo),
AppInfo2 = rebar_app_info:state(AppInfo1, AppState),
+ maybe_symlink_default(State, Profile, AppDir, AppInfo2),
case sets:is_element(rebar_app_info:name(AppInfo), Seen) of
true ->
{false, AppInfo2};
@@ -410,11 +420,42 @@ maybe_fetch(AppInfo, Upgrade, Seen, State) ->
end
end.
-in_default(AppInfo, State) ->
+already_in_default(AppInfo, State) ->
Name = ec_cnv:to_list(rebar_app_info:name(AppInfo)),
DefaultAppDir = filename:join([rebar_state:get(State, base_dir), "default", "lib", Name]),
rebar_app_discover:find_app(DefaultAppDir, all).
+needs_symlinking(State, Profile) ->
+ case {rebar_state:current_profiles(State), Profile} of
+ {[default], default} ->
+ %% file will be in default already -- this is the only run we have
+ false;
+ {_, default} ->
+ %% file fetched to default, needs to be linked to the current
+ %% run's directory.
+ true;
+ _ ->
+ %% File fetched to the right directory already
+ false
+ end.
+
+maybe_symlink_default(State, Profile, AppDir, AppInfo) ->
+ case needs_symlinking(State, Profile) of
+ true ->
+ SymDir = filename:join([rebar_dir:deps_dir(State),
+ rebar_app_info:name(AppInfo)]),
+ symlink_dep(AppDir, SymDir),
+ true;
+ false ->
+ false
+ end.
+
+
+symlink_dep(From, To) ->
+ ?INFO("Linking ~s to ~s", [From, To]),
+ filelib:ensure_dir(To),
+ rebar_file_utils:symlink_or_copy(From, To).
+
-spec parse_deps(binary(), list(), rebar_state:t(), list(), integer()) -> {[rebar_app_info:t()], [pkg_dep()]}.
parse_deps(DepsDir, Deps, State, Locks, Level) ->
lists:foldl(fun(Dep, Acc) ->
@@ -521,6 +562,15 @@ fetch_app(AppInfo, AppDir, State) ->
Result
end.
+update_app_info(AppInfo) ->
+ AppDetails = rebar_app_info:app_details(AppInfo),
+ Applications = proplists:get_value(applications, AppDetails, []),
+ IncludedApplications = proplists:get_value(included_applications, AppDetails, []),
+ AppInfo1 = rebar_app_info:applications(
+ rebar_app_info:app_details(AppInfo, AppDetails),
+ IncludedApplications++Applications),
+ rebar_app_info:valid(AppInfo1, false).
+
maybe_upgrade(AppInfo, AppDir, false, State) ->
Source = rebar_app_info:source(AppInfo),
rebar_fetch:needs_update(AppDir, Source, State);
@@ -576,7 +626,7 @@ not_needs_compile(App) ->
get_package(Dep, State) ->
case rebar_state:registry(State) of
{ok, T} ->
- HighestDepVsn = rebar_packages:find_highest_matching(Dep, "0", T),
+ {ok, HighestDepVsn} = rebar_packages:find_highest_matching(Dep, "0", T),
{Dep, HighestDepVsn};
error ->
throw(?PRV_ERROR({load_registry_fail, Dep}))