diff options
-rw-r--r-- | src/rebar_app_info.erl | 24 | ||||
-rw-r--r-- | src/rebar_prv_install_deps.erl | 159 | ||||
-rw-r--r-- | src/rebar_state.erl | 24 | ||||
-rw-r--r-- | src/rebar_topo.erl | 43 |
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. |