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.erl180
1 files changed, 103 insertions, 77 deletions
diff --git a/src/rebar_prv_install_deps.erl b/src/rebar_prv_install_deps.erl
index ba49532..768d41a 100644
--- a/src/rebar_prv_install_deps.erl
+++ b/src/rebar_prv_install_deps.erl
@@ -37,7 +37,10 @@
-export([handle_deps/3,
handle_deps/4,
- handle_deps/5]).
+ handle_deps/5,
+
+ find_cycles/1,
+ cull_compile/2]).
-export_type([dep/0]).
@@ -58,7 +61,7 @@
init(State) ->
State1 = rebar_state:add_provider(State, providers:create([{name, ?PROVIDER},
{module, ?MODULE},
- {bare, true},
+ {bare, false},
{deps, ?DEPS},
{example, undefined},
{short_desc, ""},
@@ -76,6 +79,10 @@ do(State) ->
{Apps, State1} =
lists:foldl(fun deps_per_profile/2, {[], State}, lists:reverse(Profiles)),
+ State2 = rebar_state:update_all_deps(State1, Apps),
+ CodePaths = [rebar_app_info:ebin_dir(A) || A <- Apps],
+ State3 = rebar_state:update_code_paths(State2, all_deps, CodePaths),
+
Source = ProjectApps ++ Apps,
case find_cycles(Source) of
{cycles, Cycles} ->
@@ -84,7 +91,7 @@ do(State) ->
{error, Error};
{no_cycle, Sorted} ->
ToCompile = cull_compile(Sorted, ProjectApps),
- {ok, rebar_state:deps_to_build(State1, ToCompile)}
+ {ok, rebar_state:deps_to_build(State3, ToCompile)}
end
catch
%% maybe_fetch will maybe_throw an exception to break out of some loops
@@ -158,11 +165,7 @@ handle_deps(Profile, State0, Deps, Upgrade, Locks) ->
,lists:ukeysort(2, SrcApps)
,lists:ukeysort(2, Solved)),
- State5 = rebar_state:update_all_deps(State4, AllDeps),
- CodePaths = [rebar_app_info:ebin_dir(A) || A <- AllDeps],
- State6 = rebar_state:update_code_paths(State5, all_deps, CodePaths),
-
- {ok, AllDeps, State6}.
+ {ok, AllDeps, State4}.
%% ===================================================================
%% Internal functions
@@ -202,31 +205,40 @@ update_pkg_deps(Profile, Packages, PkgDeps, Graph, Upgrade, Seen, State, Locks)
update_pkg_deps(Profile, S, Packages, Upgrade, Seen, State, Locks)
end.
+pkg_locked({Name, _, _}, Locks) ->
+ pkg_locked(Name, Locks);
pkg_locked({Name, _}, Locks) ->
+ pkg_locked(Name, Locks);
+pkg_locked(Name, Locks) ->
false =/= lists:keyfind(Name, 1, Locks).
-update_pkg_deps(Profile, Pkgs, Packages, Upgrade, Seen, State, _Locks) ->
+update_pkg_deps(Profile, Pkgs, Packages, Upgrade, Seen, State, Locks) ->
%% Create app_info record for each pkg dep
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)
+ handle_pkg_dep(Profile, Pkg, Packages, Upgrade, DepsDir, Acc, SeenAcc, Locks, 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, State),
+handle_pkg_dep(Profile, Pkg, Packages, Upgrade, DepsDir, Fetched, Seen, Locks, State) ->
+ IsLock = pkg_locked(Pkg, Locks),
+ AppInfo = package_to_app(DepsDir, Packages, Pkg, IsLock, State),
+ Deps = rebar_app_info:deps(AppInfo),
Level = rebar_app_info:dep_level(AppInfo),
{NewSeen, NewState} = maybe_lock(Profile, AppInfo, Seen, State, Level),
{_, AppInfo1} = maybe_fetch(AppInfo, Profile, Upgrade, Seen, NewState),
- {[AppInfo1 | Fetched], NewSeen, NewState}.
+ {AppInfo2, _, _, _, _} =
+ handle_dep(NewState, Profile, DepsDir, AppInfo1, Locks, Level),
+ AppInfo3 = rebar_app_info:deps(AppInfo2, Deps),
+ {[AppInfo3 | Fetched], NewSeen, NewState}.
maybe_lock(Profile, AppInfo, Seen, State, Level) ->
+ Name = rebar_app_info:name(AppInfo),
case rebar_app_info:is_checkout(AppInfo) of
false ->
case Profile of
default ->
- Name = rebar_app_info:name(AppInfo),
case sets:is_element(Name, Seen) of
false ->
Locks = rebar_state:lock(State),
@@ -241,13 +253,13 @@ maybe_lock(Profile, AppInfo, Seen, State, Level) ->
{Seen, State}
end;
_ ->
- {Seen, State}
+ {sets:add_element(Name, Seen), State}
end;
true ->
- {Seen, State}
+ {sets:add_element(Name, Seen), State}
end.
-package_to_app(DepsDir, Packages, {Name, Vsn, Level}, State) ->
+package_to_app(DepsDir, Packages, {Name, Vsn, Level}, IsLock, State) ->
case dict:find({Name, Vsn}, Packages) of
error ->
case rebar_packages:check_registry(Name, Vsn, State) of
@@ -256,14 +268,13 @@ package_to_app(DepsDir, Packages, {Name, Vsn, Level}, State) ->
false ->
throw(?PRV_ERROR({missing_package, Name, Vsn}))
end;
- {ok, P} ->
- PkgDeps = [{PkgName, PkgVsn}
- || {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, filename:join([DepsDir, Name])),
- AppInfo3 = rebar_app_info:dep_level(AppInfo2, Level),
- rebar_app_info:source(AppInfo3, {pkg, Name, Vsn})
+ {ok, PkgDeps} ->
+ Source = {pkg, Name, Vsn},
+ AppInfo = new_dep(DepsDir, Name, Vsn, Source, IsLock, State),
+ AppInfo1 = rebar_app_info:dep_level(rebar_app_info:deps(AppInfo, PkgDeps), Level),
+ BaseDir = rebar_state:get(State, base_dir, []),
+ AppState1 = rebar_state:set(rebar_app_info:state(AppInfo1), base_dir, BaseDir),
+ rebar_app_info:state(AppInfo1, AppState1)
end.
-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())}.
@@ -345,7 +356,6 @@ handle_upgrade(AppInfo, Profile, SrcDeps, PkgDeps, SrcApps, Level, State, Locks)
{true, AppInfo1} ->
handle_dep(AppInfo1, Profile, SrcDeps, PkgDeps, SrcApps,
Level, State, Locks);
-
{false, AppInfo1} ->
{[AppInfo1|SrcDeps], PkgDeps, SrcApps, State, Locks}
end;
@@ -356,7 +366,7 @@ handle_upgrade(AppInfo, Profile, SrcDeps, PkgDeps, SrcApps, Level, State, Locks)
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),
+ handle_dep(State, Profile, DepsDir, AppInfo, Locks, Level),
AppInfo2 = rebar_app_info:dep_level(AppInfo1, Level),
{NewSrcDeps ++ SrcDeps
,NewPkgDeps++PkgDeps
@@ -364,9 +374,9 @@ handle_dep(AppInfo, Profile, SrcDeps, PkgDeps, SrcApps, Level, State, Locks) ->
,State1
,NewLocks}.
--spec handle_dep(rebar_state:t(), file:filename_all(), rebar_app_info:t(), list(), integer()) ->
+-spec handle_dep(rebar_state:t(), atom(), file:filename_all(), rebar_app_info:t(), list(), integer()) ->
{rebar_app_info:t(), [rebar_app_info:t()], [pkg_dep()], [integer()]}.
-handle_dep(State, DepsDir, AppInfo, Locks, Level) ->
+handle_dep(State, Profile, DepsDir, AppInfo, Locks, Level) ->
Profiles = rebar_state:current_profiles(State),
Name = rebar_app_info:name(AppInfo),
@@ -374,22 +384,26 @@ handle_dep(State, DepsDir, AppInfo, Locks, Level) ->
S = rebar_app_info:state(AppInfo),
S1 = rebar_state:new(S, C, rebar_app_info:dir(AppInfo)),
- S2 = rebar_state:apply_profiles(S1, Profiles),
- S3 = rebar_state:apply_overrides(S2, Name),
- AppInfo1 = rebar_app_info:state(AppInfo, S3),
+ S2 = rebar_state:apply_overrides(S1, Name),
+
+ S3 = rebar_state:apply_profiles(S2, Profiles),
+ Plugins = rebar_state:get(S3, plugins, []),
+ S4 = rebar_state:set(S3, {plugins, Profile}, Plugins),
+ AppInfo1 = rebar_app_info:state(AppInfo, S4),
%% Dep may have plugins to install. Find and install here.
- State1 = rebar_plugins:handle_plugins(rebar_state:get(S3, plugins, []), State),
+ S5 = rebar_plugins:install(S4),
+ AppInfo2 = rebar_app_info:state(AppInfo1, S5),
- Deps = rebar_state:get(S3, deps, []),
%% Upgrade lock level to be the level the dep will have in this dep tree
+ Deps = rebar_state:get(S5, deps, []),
NewLocks = [{DepName, Source, LockLevel+Level} ||
- {DepName, Source, LockLevel} <- rebar_state:get(S3, {locks, default}, [])],
- AppInfo2 = rebar_app_info:deps(AppInfo1, rebar_state:deps_names(Deps)),
- {SrcDeps, PkgDeps} = parse_deps(DepsDir, Deps, S3, Locks, Level),
- {AppInfo2, SrcDeps, PkgDeps, Locks++NewLocks, State1}.
+ {DepName, Source, LockLevel} <- rebar_state:get(S5, {locks, default}, [])],
+ AppInfo3 = rebar_app_info:deps(AppInfo2, rebar_state:deps_names(Deps)),
+ {SrcDeps, PkgDeps} = parse_deps(DepsDir, Deps, S5, Locks, Level+1),
+ {AppInfo3, SrcDeps, PkgDeps, Locks++NewLocks, State}.
--spec maybe_fetch(rebar_app_info:t(), atom(), boolean() | {true, binary(), integer()},
+-spec maybe_fetch(rebar_app_info:t(), atom(), boolean(),
sets:set(binary()), rebar_state:t()) -> {boolean(), rebar_app_info:t()}.
maybe_fetch(AppInfo, Profile, Upgrade, Seen, State) ->
AppDir = ec_cnv:to_list(rebar_app_info:dir(AppInfo)),
@@ -405,7 +419,7 @@ maybe_fetch(AppInfo, Profile, Upgrade, Seen, State) ->
case fetch_app(AppInfo, AppDir, State) of
true ->
maybe_symlink_default(State, Profile, AppDir, AppInfo),
- {true, update_app_info(AppInfo)};
+ {true, update_app_info(AppDir, AppInfo)};
Other ->
{Other, AppInfo}
end;
@@ -432,7 +446,7 @@ maybe_fetch(AppInfo, Profile, Upgrade, Seen, 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]),
+ DefaultAppDir = filename:join([rebar_state:get(State, base_dir, []), "default", "lib", Name]),
rebar_app_discover:find_app(DefaultAppDir, all).
needs_symlinking(State, Profile) ->
@@ -477,69 +491,69 @@ parse_deps(DepsDir, Deps, State, Locks, Level) ->
end,
case lists:keyfind(ec_cnv:to_binary(Name), 1, Locks) of
false ->
- parse_dep(Dep, Acc, DepsDir, State);
+ parse_dep(Dep, Acc, DepsDir, false, State);
LockedDep ->
LockedLevel = element(3, LockedDep),
case LockedLevel > Level of
true ->
- parse_dep(Dep, Acc, DepsDir, State);
+ parse_dep(Dep, Acc, DepsDir, false, State);
false ->
- parse_dep(LockedDep, Acc, DepsDir, State)
+ parse_dep(LockedDep, Acc, DepsDir, true, State)
end
end
end, {[], []}, Deps).
-parse_dep({Name, Vsn}, {SrcDepsAcc, PkgDepsAcc}, DepsDir, State) when is_list(Vsn) ->
+parse_dep({Name, Vsn}, {SrcDepsAcc, PkgDepsAcc}, DepsDir, IsLock, State) when is_list(Vsn) ->
CheckoutsDir = ec_cnv:to_list(rebar_dir:checkouts_dir(State, Name)),
case rebar_app_info:discover(CheckoutsDir) of
{ok, _App} ->
- Dep = new_dep(DepsDir, Name, [], [], State),
+ Dep = new_dep(DepsDir, Name, [], [], IsLock, State),
{[Dep | SrcDepsAcc], PkgDepsAcc};
not_found ->
{SrcDepsAcc, [parse_goal(ec_cnv:to_binary(Name)
,ec_cnv:to_binary(Vsn)) | PkgDepsAcc]}
end;
-parse_dep(Name, {SrcDepsAcc, PkgDepsAcc}, DepsDir, State) when is_atom(Name) ->
+parse_dep(Name, {SrcDepsAcc, PkgDepsAcc}, DepsDir, IsLock, State) when is_atom(Name) ->
{PkgName, PkgVsn} = get_package(ec_cnv:to_binary(Name), State),
CheckoutsDir = ec_cnv:to_list(rebar_dir:checkouts_dir(State, Name)),
case rebar_app_info:discover(CheckoutsDir) of
{ok, _App} ->
- Dep = new_dep(DepsDir, Name, [], [], State),
+ Dep = new_dep(DepsDir, Name, [], [], IsLock, State),
{[Dep | SrcDepsAcc], PkgDepsAcc};
not_found ->
{SrcDepsAcc, [{PkgName, PkgVsn} | PkgDepsAcc]}
end;
-parse_dep({Name, Source}, {SrcDepsAcc, PkgDepsAcc}, DepsDir, State) when is_tuple(Source) ->
- Dep = new_dep(DepsDir, Name, [], Source, State),
+parse_dep({Name, Source}, {SrcDepsAcc, PkgDepsAcc}, DepsDir, IsLock, State) when is_tuple(Source) ->
+ Dep = new_dep(DepsDir, Name, [], Source, IsLock, State),
{[Dep | SrcDepsAcc], PkgDepsAcc};
-parse_dep({Name, Source}, {SrcDepsAcc, PkgDepsAcc}, DepsDir, State) when is_tuple(Source) ->
- Dep = new_dep(DepsDir, Name, [], Source, State),
+parse_dep({Name, Source}, {SrcDepsAcc, PkgDepsAcc}, DepsDir, IsLock, State) when is_tuple(Source) ->
+ Dep = new_dep(DepsDir, Name, [], Source, IsLock, State),
{[Dep | SrcDepsAcc], PkgDepsAcc};
-parse_dep({Name, _Vsn, Source}, {SrcDepsAcc, PkgDepsAcc}, DepsDir, State) when is_tuple(Source) ->
- Dep = new_dep(DepsDir, Name, [], Source, State),
+parse_dep({Name, _Vsn, Source}, {SrcDepsAcc, PkgDepsAcc}, DepsDir, IsLock, State) when is_tuple(Source) ->
+ Dep = new_dep(DepsDir, Name, [], Source, IsLock, State),
{[Dep | SrcDepsAcc], PkgDepsAcc};
-parse_dep({Name, _Vsn, Source, Opts}, {SrcDepsAcc, PkgDepsAcc}, DepsDir, State) when is_tuple(Source) ->
+parse_dep({Name, _Vsn, Source, Opts}, {SrcDepsAcc, PkgDepsAcc}, DepsDir, IsLock, State) when is_tuple(Source) ->
?WARN("Dependency option list ~p in ~p is not supported and will be ignored", [Opts, Name]),
- Dep = new_dep(DepsDir, Name, [], Source, State),
+ Dep = new_dep(DepsDir, Name, [], Source, IsLock, State),
{[Dep | SrcDepsAcc], PkgDepsAcc};
-parse_dep({_Name, {pkg, Name, Vsn}, Level}, {SrcDepsAcc, PkgDepsAcc}, DepsDir, State) when is_integer(Level) ->
+parse_dep({_Name, {pkg, Name, Vsn}, Level}, {SrcDepsAcc, PkgDepsAcc}, DepsDir, IsLock, State) when is_integer(Level) ->
CheckoutsDir = ec_cnv:to_list(rebar_dir:checkouts_dir(State, Name)),
case rebar_app_info:discover(CheckoutsDir) of
{ok, _App} ->
- Dep = new_dep(DepsDir, Name, [], [], State),
+ Dep = new_dep(DepsDir, Name, [], [], IsLock, State),
{[Dep | SrcDepsAcc], PkgDepsAcc};
not_found ->
{SrcDepsAcc, [{Name, Vsn} | PkgDepsAcc]}
end;
-parse_dep({Name, Source, Level}, {SrcDepsAcc, PkgDepsAcc}, DepsDir, State) when is_tuple(Source)
+parse_dep({Name, Source, Level}, {SrcDepsAcc, PkgDepsAcc}, DepsDir, IsLock, State) when is_tuple(Source)
, is_integer(Level) ->
- Dep = new_dep(DepsDir, Name, [], Source, State),
+ Dep = new_dep(DepsDir, Name, [], Source, IsLock, State),
{[Dep | SrcDepsAcc], PkgDepsAcc};
-parse_dep(Dep, _, _, _) ->
+parse_dep(Dep, _, _, _, _) ->
throw(?PRV_ERROR({parse_dep, Dep})).
-new_dep(DepsDir, Name, Vsn, Source, State) ->
+new_dep(DepsDir, Name, Vsn, Source, IsLock, State) ->
CheckoutsDir = ec_cnv:to_list(rebar_dir:checkouts_dir(State, Name)),
{ok, Dep} = case rebar_app_info:discover(CheckoutsDir) of
{ok, App} ->
@@ -560,7 +574,7 @@ new_dep(DepsDir, Name, Vsn, Source, State) ->
ParentOverrides = rebar_state:overrides(State),
Dep1 = rebar_app_info:state(Dep,
rebar_state:overrides(S, ParentOverrides++Overrides)),
- rebar_app_info:source(Dep1, Source).
+ rebar_app_info:is_lock(rebar_app_info:source(Dep1, Source), IsLock).
fetch_app(AppInfo, AppDir, State) ->
?INFO("Fetching ~s (~p)", [rebar_app_info:name(AppInfo), rebar_app_info:source(AppInfo)]),
@@ -572,8 +586,12 @@ fetch_app(AppInfo, AppDir, State) ->
throw(Error)
end.
-update_app_info(AppInfo) ->
- AppDetails = rebar_app_info:app_details(AppInfo),
+%% This is called after the dep has been downloaded and unpacked, if it hadn't been already.
+%% So this is the first time for newly downloaded apps that its .app/.app.src data can
+%% be read in an parsed.
+update_app_info(AppDir, AppInfo) ->
+ {ok, Found} = rebar_app_info:discover(AppDir),
+ AppDetails = rebar_app_info:app_details(Found),
Applications = proplists:get_value(applications, AppDetails, []),
IncludedApplications = proplists:get_value(included_applications, AppDetails, []),
AppInfo1 = rebar_app_info:applications(
@@ -581,22 +599,29 @@ update_app_info(AppInfo) ->
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);
-maybe_upgrade(AppInfo, AppDir, true, State) ->
+maybe_upgrade(AppInfo, AppDir, Upgrade, State) ->
Source = rebar_app_info:source(AppInfo),
- case rebar_fetch:needs_update(AppDir, Source, State) of
+ case Upgrade orelse rebar_app_info:is_lock(AppInfo) of
true ->
- ?INFO("Upgrading ~s", [rebar_app_info:name(AppInfo)]),
- case rebar_fetch:download_source(AppDir, Source, State) of
+ case rebar_fetch:needs_update(AppDir, Source, State) of
true ->
- true;
- Error ->
- throw(Error)
+ ?INFO("Upgrading ~s", [rebar_app_info:name(AppInfo)]),
+ case rebar_fetch:download_source(AppDir, Source, State) of
+ true ->
+ true;
+ Error ->
+ throw(Error)
+ end;
+ false ->
+ case Upgrade of
+ true ->
+ ?INFO("No upgrade needed for ~s", [rebar_app_info:name(AppInfo)]),
+ false;
+ false ->
+ false
+ end
end;
false ->
- ?INFO("No upgrade needed for ~s", [rebar_app_info:name(AppInfo)]),
false
end.
@@ -632,7 +657,8 @@ warn_skip_pkg({Name, Source}, State) ->
not_needs_compile(App) ->
not(rebar_app_info:is_checkout(App))
- andalso rebar_app_info:valid(App).
+ andalso rebar_app_info:valid(App)
+ andalso rebar_state:has_all_artifacts(rebar_app_info:state(App)) =:= true.
get_package(Dep, State) ->
case rebar_state:registry(State) of