summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/rebar_app_info.erl24
-rw-r--r--src/rebar_prv_install_deps.erl159
-rw-r--r--src/rebar_state.erl24
-rw-r--r--src/rebar_topo.erl43
4 files changed, 115 insertions, 135 deletions
diff --git a/src/rebar_app_info.erl b/src/rebar_app_info.erl
index 3c38083..a08ca92 100644
--- a/src/rebar_app_info.erl
+++ b/src/rebar_app_info.erl
@@ -1,6 +1,8 @@
-module(rebar_app_info).
-export([new/0,
+ new/1,
+ new/2,
new/3,
name/1,
name/2,
@@ -15,6 +17,8 @@
original_vsn/1,
original_vsn/2,
ebin_dir/1,
+ deps/1,
+ deps/2,
dir/1,
dir/2,
source/1,
@@ -28,6 +32,7 @@
config :: rebar_config:config() | undefined,
original_vsn :: string(),
app_details :: list(),
+ deps=[] :: list(),
dir :: file:name(),
source :: string() | undefined}).
@@ -45,6 +50,17 @@
new() ->
{ok, #app_info_t{}}.
+-spec new(atom() | binary() | string()) ->
+ {ok, t()}.
+new(AppName) ->
+ {ok, #app_info_t{name=ec_cnv:to_binary(AppName)}}.
+
+-spec new(atom() | binary() | string(), string()) ->
+ {ok, t()}.
+new(AppName, Vsn) ->
+ {ok, #app_info_t{name=ec_cnv:to_binary(AppName),
+ original_vsn=Vsn}}.
+
%% @doc build a complete version of the app info with all fields set.
-spec new(atom() | binary() | string(), string(), file:name()) ->
{ok, t()}.
@@ -101,6 +117,14 @@ original_vsn(#app_info_t{original_vsn=Vsn}) ->
original_vsn(AppInfo=#app_info_t{}, Vsn) ->
AppInfo#app_info_t{original_vsn=Vsn}.
+-spec deps(t()) -> list().
+deps(#app_info_t{deps=Deps}) ->
+ Deps.
+
+-spec deps(t(), list()) -> t().
+deps(AppInfo=#app_info_t{}, Deps) ->
+ AppInfo#app_info_t{deps=Deps}.
+
-spec dir(t()) -> file:name().
dir(#app_info_t{dir=Dir}) ->
Dir.
diff --git a/src/rebar_prv_install_deps.erl b/src/rebar_prv_install_deps.erl
index ccfb3b0..40df88c 100644
--- a/src/rebar_prv_install_deps.erl
+++ b/src/rebar_prv_install_deps.erl
@@ -42,10 +42,6 @@
-define(PROVIDER, install_deps).
-define(DEPS, [app_discovery]).
--record(dep, {name :: binary(),
- vsn :: binary(),
- source :: binary()}).
-
%% ===================================================================
%% Public API
%% ===================================================================
@@ -74,30 +70,30 @@ do(State) ->
Deps ->
%% Split source deps form binary deps, needed to keep backwards compatibility
{SrcDeps, Goals} = parse_deps(Deps),
- case update_src_deps(State, SrcDeps, Goals, [], []) of
- {State1, SrcDeps1, [], Locked} ->
- {ok, rebar_state:set(State1, locks, Locked)};
- {State1, SrcDeps1, Goals1, Locked} ->
- {ok, Solved} = rlx_depsolver:solve(Graph, Goals1),
- M = lists:map(fun({Name, Vsn}) ->
- FmtVsn = ec_cnv:to_binary(rlx_depsolver:format_version(Vsn)),
- {ok, P} = dict:find({Name, FmtVsn}, Packages),
- Link = proplists:get_value(<<"link">>, P),
- #dep{name=Name,
- vsn=FmtVsn,
- source={Name
- ,FmtVsn
- ,Link}}
- end, Solved),
- {State2, Deps1, _, Locked2} = update_deps(State1, M),
- State3 = rebar_state:set(State2, locks, Locked++Locked2),
- {ok, rebar_state:set(State3, goals, Goals1)}
- end
+ State1 = rebar_state:src_deps(rebar_state:goals(State, Goals), SrcDeps),
+ State2 = update_src_deps(State1),
+ Goals1 = rebar_state:goals(State2),
+ {ok, Solved} = rlx_depsolver:solve(Graph, Goals1),
+ Final = lists:map(fun({Name, Vsn}) ->
+ FmtVsn = ec_cnv:to_binary(rlx_depsolver:format_version(Vsn)),
+ {ok, P} = dict:find({Name, FmtVsn}, Packages),
+ PkgDeps = proplists:get_value(<<"deps">>, P),
+ Link = proplists:get_value(<<"link">>, P),
+ Source = {Name, FmtVsn, Link},
+ {ok, AppInfo} = rebar_app_info:new(Name, FmtVsn),
+ AppInfo1 = rebar_app_info:deps(AppInfo, PkgDeps),
+ rebar_app_info:source(AppInfo1, Source)
+ end, Solved),
+ ProjectApps = lists:map(fun(X) ->
+ rebar_app_info:deps(X, [rebar_app_info:name(Y) || Y <- SrcDeps] ++ [element(1, G) || G <- Goals])
+ end, rebar_state:apps_to_build(State2)),
+ FinalDeps = ProjectApps ++ rebar_state:src_deps(State2) ++ Final,
+ {ok, Sort} = rebar_topo:sort_apps(FinalDeps),
+ [io:format("Build ~p~n", [rebar_app_info:name(A)]) || A <- Sort],
+ {ok, State2}
end;
- Locks ->
- Locks1 = [new(Lock) || Lock <- Locks],
- {State2, _, _, _} = update_deps(State, Locks1),
- {ok, State2}
+ _Locks ->
+ {ok, State}
end.
%% set REBAR_DEPS_DIR and ERL_LIBS environment variables
@@ -130,90 +126,30 @@ get_deps_dir(DepsDir, App) ->
%% Internal functions
%% ===================================================================
-new({Name, Vsn, Source}) when is_tuple(Source) ->
- #dep{name=ec_cnv:to_binary(Name), vsn=ec_cnv:to_binary(Vsn), source=Source};
-new({Name, Vsn, Source}) when is_binary(Source) ->
- #dep{name=ec_cnv:to_binary(Name)
- ,vsn=ec_cnv:to_binary(Vsn)
- ,source={ec_cnv:to_binary(Name), ec_cnv:to_binary(Vsn), Source}};
-new(Name) ->
- #dep{name=ec_cnv:to_binary(Name)}.
-
%% Fetch missing binary deps
-update_deps(State, Deps) ->
- DepsDir = get_deps_dir(State),
-
- %% Find available apps to fulfill dependencies
- %% Should only have to do this once, not every iteration
- UnbuiltApps = rebar_app_discover:find_unbuilt_apps([DepsDir]),
- FoundApps = rebar_app_discover:find_apps([DepsDir]),
-
- download_missing_deps(State, DepsDir, UnbuiltApps++FoundApps, Deps).
-
-%% Find source deps to build and download
-update_src_deps(State, Deps, Goals, SrcApps, Locked) ->
- DepsDir = get_deps_dir(State),
-
- %% Find available apps to fulfill dependencies
- %% Should only have to do this once, not every iteration
- UnbuiltApps = rebar_app_discover:find_unbuilt_apps([DepsDir]),
- FoundApps = rebar_app_discover:find_apps([DepsDir]),
-
- %% Resolve deps and their dependencies
- {Deps1, NewGoals} = handle_src_deps(Deps, UnbuiltApps++FoundApps, Goals),
- case download_missing_deps(State, DepsDir, UnbuiltApps++FoundApps, Deps1) of
- {State1, [], SrcApps1, []} ->
- Locked1 = lists:map(fun(AppSrc) ->
- Source = rebar_app_info:source(AppSrc),
- Name = rebar_app_info:name(AppSrc),
- C = rebar_config:consult(rebar_app_info:dir(AppSrc)),
- S = rebar_state:new(rebar_state:new()
- ,C
- ,rebar_app_info:dir(AppSrc)),
- TargetDir = get_deps_dir(DepsDir, Name),
- Ref = rebar_fetch:current_ref(binary_to_list(TargetDir), Source),
- AppInfo = rebar_prv_app_builder:build(S, AppSrc),
-
- {Name
- ,ec_cnv:to_binary(rebar_app_info:original_vsn(AppInfo))
- ,erlang:setelement(3, Source, Ref)}
- end, SrcApps1++SrcApps),
- {State1, Deps1, NewGoals, Locked1++Locked};
- {State1, Missing, SrcApps1, Locked1} ->
- update_src_deps(State1, Missing, NewGoals, SrcApps1++SrcApps, Locked1++Locked)
+update_deps(State) ->
+ State.
+
+update_src_deps(State) ->
+ SrcDeps = rebar_state:src_deps(State),
+ case lists:foldl(fun(AppInfo, {StateAcc, SrcDepsAcc, GoalsAcc}) ->
+ ok = maybe_fetch(StateAcc, AppInfo),
+ C = rebar_config:consult(rebar_app_info:dir(AppInfo)),
+ S = rebar_state:new(rebar_state:new(), C, rebar_app_info:dir(AppInfo)),
+ Deps = rebar_state:get(S, deps, []),
+ {SrcDeps1, Goals} = parse_deps(Deps),
+ NewSrcDeps = SrcDeps1++SrcDepsAcc,
+ {StateAcc, NewSrcDeps, Goals++GoalsAcc}
+ end, {State, [], rebar_state:goals(State)}, SrcDeps) of
+ {State1, [], NewGoals} ->
+ rebar_state:goals(State1, NewGoals);
+ {State1, NewSrcDeps, NewGoals}->
+ State2 = rebar_state:src_deps(rebar_state:goals(State1, NewGoals), SrcDeps++NewSrcDeps),
+ update_src_deps(State2)
end.
-%% Collect deps of new deps
-handle_src_deps(Deps, Found, Goals) ->
- lists:foldl(fun(X, {DepsAcc, GoalsAcc}) ->
- C = rebar_config:consult(rebar_app_info:dir(X)),
- S = rebar_state:new(rebar_state:new(), C, rebar_app_info:dir(X)),
- {ParsedDeps, NewGoals} = parse_deps(rebar_state:get(S, deps, [])),
- {ParsedDeps++DepsAcc, NewGoals++GoalsAcc}
- end, {Deps, Goals}, Found).
-
-%% Fetch missing deps from source
-download_missing_deps(State, DepsDir, Found, Deps) ->
- Missing =
- lists:filter(fun(#dep{name=Name}) ->
- not lists:any(fun(F) ->
- Name =:= rebar_app_info:name(F)
- end, Found)
- end, Deps),
- {SrcApps, Locked} = lists:foldl(fun(Dep=#dep{name=Name, source=Source}, {SrcAppsAcc, LockedAcc}) ->
- TargetDir = get_deps_dir(DepsDir, Name),
- ?INFO("Fetching ~s ~s~n", [Name
- ,element(2, Source)]),
- rebar_fetch:download_source(TargetDir, Source),
- case rebar_app_discover:find_unbuilt_apps([TargetDir]) of
- [AppSrc] ->
- {[rebar_app_info:source(AppSrc, Source) | SrcAppsAcc], LockedAcc};
- [] ->
- {SrcAppsAcc, [Source | LockedAcc]}
- end
- end, {[], []}, Missing),
-
- {State, Missing, lists:reverse(SrcApps), Locked}.
+maybe_fetch(_State, _Dep) ->
+ ok.
parse_deps(Deps) ->
lists:foldl(fun({Name, Vsn}, {SrcDepsAcc, GoalsAcc}) ->
@@ -221,9 +157,10 @@ parse_deps(Deps) ->
,ec_cnv:to_binary(Vsn)) | GoalsAcc]};
(Name, {SrcDepsAcc, GoalsAcc}) when is_atom(Name) ->
{SrcDepsAcc, [ec_cnv:to_binary(Name) | GoalsAcc]};
- (SrcDep, {SrcDepsAcc, GoalsAcc}) ->
- Dep = new(SrcDep),
- {[Dep | SrcDepsAcc], GoalsAcc}
+ ({Name, _, Source}, {SrcDepsAcc, GoalsAcc}) ->
+ {ok, Dep} = rebar_app_info:new(Name),
+ Dep1 = rebar_app_info:source(Dep, Source),
+ {[Dep1 | SrcDepsAcc], GoalsAcc}
end, {[], []}, Deps).
parse_goal(Name, Constraint) ->
diff --git a/src/rebar_state.erl b/src/rebar_state.erl
index 4b4ada8..fc5d750 100644
--- a/src/rebar_state.erl
+++ b/src/rebar_state.erl
@@ -9,6 +9,9 @@
apps_to_build/1, apps_to_build/2,
+ goals/1, goals/2,
+ src_deps/1, src_deps/2,
+
providers/1, providers/2, add_provider/2]).
-include("rebar.hrl").
@@ -29,6 +32,7 @@
envs = new_env() :: rebar_dict(),
command_args = [] :: list(),
+ src_deps = [] :: [rebar_app_info:t()],
apps = dict:new() :: rebar_dict(),
goals = [],
providers = [],
@@ -101,11 +105,27 @@ command_args(#state_t{command_args=CmdArgs}) ->
command_args(State, CmdArgs) ->
State#state_t{command_args=CmdArgs}.
+goals(#state_t{goals=Goals}) ->
+ Goals.
+
+goals(State=#state_t{goals=Goals}, NewGoals) when is_list(Goals) ->
+ State#state_t{goals=NewGoals};
+goals(State=#state_t{goals=Goals}, Goal) ->
+ State#state_t{goals=[Goal | Goals]}.
+
+src_deps(#state_t{src_deps=SrcDeps}) ->
+ SrcDeps.
+
+src_deps(State=#state_t{src_deps=SrcDeps}, NewSrcDeps) when is_list(SrcDeps) ->
+ State#state_t{src_deps=NewSrcDeps};
+src_deps(State=#state_t{src_deps=SrcDeps}, SrcDep) ->
+ State#state_t{src_deps=[SrcDep | SrcDeps]}.
+
apps_to_build(#state_t{apps_to_build=Apps}) ->
Apps.
-apps_to_build(State=#state_t{apps_to_build=Apps}, Apps) when is_list(Apps) ->
- State#state_t{apps_to_build=Apps};
+apps_to_build(State=#state_t{apps_to_build=Apps}, NewApps) when is_list(NewApps) ->
+ State#state_t{apps_to_build=NewApps};
apps_to_build(State=#state_t{apps_to_build=Apps}, App) ->
State#state_t{apps_to_build=[App | Apps]}.
diff --git a/src/rebar_topo.erl b/src/rebar_topo.erl
index d6447c5..e2a03c6 100644
--- a/src/rebar_topo.erl
+++ b/src/rebar_topo.erl
@@ -54,8 +54,8 @@
%% applications. This implies that you have already done the
%% constraint solve before you pass the list of apps here to be
%% sorted.
--spec sort_apps([rlx_app_info:t()]) ->
- {ok, [rlx_app_info:t()]} |
+-spec sort_apps([rebar_app_info:t()]) ->
+ {ok, [rebar_app_info:t()]} |
relx:error().
sort_apps(Apps) ->
Pairs = apps_to_pairs(Apps),
@@ -78,9 +78,9 @@ format_error({cycle, Pairs}) ->
"before we can continue:\n",
case Pairs of
[{P1, P2}] ->
- [rlx_util:indent(2), erlang:atom_to_list(P2), "->", erlang:atom_to_list(P1)];
+ [rebar_util:indent(2), erlang:atom_to_list(P2), "->", erlang:atom_to_list(P1)];
[{P1, P2} | Rest] ->
- [rlx_util:indent(2), erlang:atom_to_list(P2), "->", erlang:atom_to_list(P1),
+ [rebar_util:indent(2), erlang:atom_to_list(P2), "->", erlang:atom_to_list(P1),
[["-> ", erlang:atom_to_list(PP2), " -> ", erlang:atom_to_list(PP1)] || {PP1, PP2} <- Rest]];
[] ->
[]
@@ -89,28 +89,27 @@ format_error({cycle, Pairs}) ->
%%====================================================================
%% Internal Functions
%%====================================================================
--spec names_to_apps([atom()], [rlx_app_info:t()]) -> [rlx_app_info:t()].
+-spec names_to_apps([atom()], [rebar_app_info:t()]) -> [rebar_app_info:t()].
names_to_apps(Names, Apps) ->
[find_app_by_name(Name, Apps) || Name <- Names].
--spec find_app_by_name(atom(), [rlx_app_info:t()]) -> rlx_app_info:t().
+-spec find_app_by_name(atom(), [rebar_app_info:t()]) -> rebar_app_info:t().
find_app_by_name(Name, Apps) ->
{ok, App1} =
ec_lists:find(fun(App) ->
- rlx_app_info:name(App) =:= Name
+ rebar_app_info:name(App) =:= Name
end, Apps),
App1.
--spec apps_to_pairs([rlx_app_info:t()]) -> [pair()].
+-spec apps_to_pairs([rebar_app_info:t()]) -> [pair()].
apps_to_pairs(Apps) ->
lists:flatten([app_to_pairs(App) || App <- Apps]).
--spec app_to_pairs(rlx_app_info:t()) -> [pair()].
+-spec app_to_pairs(rebar_app_info:t()) -> [pair()].
app_to_pairs(App) ->
- [{DepApp, rlx_app_info:name(App)} ||
+ [{DepApp, rebar_app_info:name(App)} ||
DepApp <-
- rlx_app_info:active_deps(App) ++
- rlx_app_info:library_deps(App)].
+ rebar_app_info:deps(App)].
%% @doc Iterate over the system. @private
@@ -195,8 +194,8 @@ topo_pairs_cycle_test() ->
sort(Pairs)).
topo_apps_cycle_test() ->
- {ok, App1} = rlx_app_info:new(app1, "0.1", "/no-dir", [app2], [stdlib]),
- {ok, App2} = rlx_app_info:new(app2, "0.1", "/no-dir", [app1], []),
+ {ok, App1} = rebar_app_info:new(app1, "0.1", "/no-dir", [app2], [stdlib]),
+ {ok, App2} = rebar_app_info:new(app2, "0.1", "/no-dir", [app1], []),
Apps = [App1, App2],
?assertMatch({error, {_, {cycle, [{app2,app1},{app1,app2}]}}},
sort_apps(Apps)).
@@ -204,16 +203,16 @@ topo_apps_cycle_test() ->
topo_apps_good_test() ->
Apps = [App ||
{ok, App} <-
- [rlx_app_info:new(app1, "0.1", "/no-dir", [app2, zapp1], [stdlib, kernel]),
- rlx_app_info:new(app2, "0.1", "/no-dir", [app3], []),
- rlx_app_info:new(app3, "0.1", "/no-dir", [kernel], []),
- rlx_app_info:new(zapp1, "0.1", "/no-dir", [app2,app3,zapp2], []),
- rlx_app_info:new(stdlib, "0.1", "/no-dir", [], []),
- rlx_app_info:new(kernel, "0.1", "/no-dir", [], []),
- rlx_app_info:new(zapp2, "0.1", "/no-dir", [], [])]],
+ [rebar_app_info:new(app1, "0.1", "/no-dir", [app2, zapp1], [stdlib, kernel]),
+ rebar_app_info:new(app2, "0.1", "/no-dir", [app3], []),
+ rebar_app_info:new(app3, "0.1", "/no-dir", [kernel], []),
+ rebar_app_info:new(zapp1, "0.1", "/no-dir", [app2,app3,zapp2], []),
+ rebar_app_info:new(stdlib, "0.1", "/no-dir", [], []),
+ rebar_app_info:new(kernel, "0.1", "/no-dir", [], []),
+ rebar_app_info:new(zapp2, "0.1", "/no-dir", [], [])]],
{ok, Sorted} = sort_apps(Apps),
?assertMatch([stdlib, kernel, zapp2,
app3, app2, zapp1, app1],
- [rlx_app_info:name(App) || App <- Sorted]).
+ [rebar_app_info:name(App) || App <- Sorted]).
-endif.