diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/rebar_app_discover.erl | 12 | ||||
-rw-r--r-- | src/rebar_prv_compile.erl (renamed from src/rebar_prv_app_builder.erl) | 8 | ||||
-rw-r--r-- | src/rebar_prv_install_deps.erl | 143 | ||||
-rw-r--r-- | src/rebar_state.erl | 42 |
4 files changed, 117 insertions, 88 deletions
diff --git a/src/rebar_app_discover.erl b/src/rebar_app_discover.erl index aaaeb03..12193b5 100644 --- a/src/rebar_app_discover.erl +++ b/src/rebar_app_discover.erl @@ -7,8 +7,9 @@ do(State, LibDirs) -> Apps = find_apps(LibDirs, all), + ProjectDeps = rebar_state:deps_names(State), lists:foldl(fun(AppInfo, StateAcc) -> - rebar_state:apps_to_build(StateAcc, AppInfo) + rebar_state:project_apps(StateAcc, rebar_app_info:deps(AppInfo, ProjectDeps)) end, State, Apps). -spec all_app_dirs(list(file:name())) -> list(file:name()). @@ -35,15 +36,10 @@ app_dirs(LibDir) -> "*.app"]), lists:usort(lists:foldl(fun(Path, Acc) -> - Files = filelib:wildcard(to_list(Path)), + Files = filelib:wildcard(ec_cnv:to_list(Path)), [app_dir(File) || File <- Files] ++ Acc end, [], [Path1, Path2, Path3, Path4])). -to_list(S) when is_list(S) -> - S; -to_list(S) when is_binary(S) -> - binary_to_list(S). - find_unbuilt_apps(LibDirs) -> find_apps(LibDirs, invalid). @@ -149,7 +145,7 @@ get_modules_list(AppFile, AppDetail) -> ok | {error, Reason::term()}. has_all_beams(EbinDir, [Module | ModuleList]) -> BeamFile = filename:join([EbinDir, - list_to_binary(atom_to_list(Module) ++ ".beam")]), + ec_cnv:to_list(Module) ++ ".beam"]), case filelib:is_file(BeamFile) of true -> has_all_beams(EbinDir, ModuleList); diff --git a/src/rebar_prv_app_builder.erl b/src/rebar_prv_compile.erl index 4c2d978..6eb2339 100644 --- a/src/rebar_prv_app_builder.erl +++ b/src/rebar_prv_compile.erl @@ -1,4 +1,4 @@ --module(rebar_prv_app_builder). +-module(rebar_prv_compile). -behaviour(rebar_provider). @@ -29,10 +29,12 @@ init(State) -> -spec do(rebar_state:t()) -> {ok, rebar_state:t()} | relx:error(). do(State) -> - Apps = rebar_state:apps_to_build(State), + Apps = rebar_state:project_apps(State), lists:foreach(fun(AppInfo) -> - _AppInfo1 = build(State, AppInfo) + C = rebar_config:consult(rebar_app_info:dir(AppInfo)), + S = rebar_state:new(rebar_state:new(), C, rebar_app_info:dir(AppInfo)), + _AppInfo1 = build(S, AppInfo) end, Apps), rebar_lock:create(State), diff --git a/src/rebar_prv_install_deps.erl b/src/rebar_prv_install_deps.erl index 3e13fc2..ebb877b 100644 --- a/src/rebar_prv_install_deps.erl +++ b/src/rebar_prv_install_deps.erl @@ -42,6 +42,11 @@ -define(PROVIDER, install_deps). -define(DEPS, [app_discovery]). +-type src_dep() :: {atom(), string(), {atom(), string(), string()}}. +-type binary_dep() :: {atom(), binary()} | atom(). + +-type dep() :: src_dep() | binary_dep(). + %% =================================================================== %% Public API %% =================================================================== @@ -60,53 +65,9 @@ init(State) -> -spec do(rebar_state:t()) -> {ok, rebar_state:t()}. do(State) -> - %% Read in package index and dep graph - {Packages, Graph} = rebar_packages:get_packages(State), case rebar_state:get(State, locks, []) of [] -> - case rebar_state:get(State, deps, []) of - [] -> - {ok, State}; - Deps -> - %% Split source deps form binary deps, needed to keep backwards compatibility - DepsDir = get_deps_dir(State), - {SrcDeps, Goals} = parse_deps(DepsDir, Deps), - State1 = rebar_state:src_deps(rebar_state:goals(State, Goals), lists:ukeysort(2, SrcDeps)), - State2 = update_src_deps(State1), - case rebar_state:goals(State2) of - [] -> - ProjectApps = lists:map(fun(X) -> - rebar_app_info:deps(X, [rebar_app_info:name(Y) || Y <- SrcDeps]) - end, rebar_state:apps_to_build(State2)), - FinalDeps = ProjectApps ++ rebar_state:src_deps(State2), - {ok, Sort} = rebar_topo:sort_apps(FinalDeps), - State3 = rebar_state:apps_to_build(State2, Sort), - {ok, State3}; - Goals1 -> - {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), - AppInfo2 = - rebar_app_info:dir(AppInfo1, get_deps_dir(DepsDir, <<Name/binary, "-", FmtVsn/binary>>)), - AppInfo3 = rebar_app_info:source(AppInfo2, Source), - ok = maybe_fetch(AppInfo3), - AppInfo3 - end, Solved), - ProjectApps = lists:map(fun(X) -> - rebar_app_info:deps(X, [rebar_app_info:name(Y) || Y <- SrcDeps] ++ [element(1, G) || G <- Goals1]) - end, rebar_state:apps_to_build(State2)), - FinalDeps = ProjectApps ++ rebar_state:src_deps(State2) ++ Final, - {ok, Sort} = rebar_topo:sort_apps(FinalDeps), - State3 = rebar_state:apps_to_build(State2, Sort), - {ok, State3} - end - end; + handle_deps(State, rebar_state:get(State, deps, [])); _Locks -> {ok, State} end. @@ -130,10 +91,12 @@ setup_env(State) -> [{"REBAR_DEPS_DIR", DepsDir}, ERL_LIBS]. +-spec get_deps_dir(rebar_state:t()) -> file:filename_all(). get_deps_dir(State) -> BaseDir = rebar_state:get(State, base_dir, ""), get_deps_dir(BaseDir, "deps"). +-spec get_deps_dir(file:filename_all(), rebar_state:t()) -> file:filename_all(). get_deps_dir(DepsDir, App) -> filename:join(DepsDir, App). @@ -141,28 +104,84 @@ get_deps_dir(DepsDir, App) -> %% Internal functions %% =================================================================== +handle_deps(State, []) -> + {ok, State}; +handle_deps(State, Deps) -> + %% Read in package index and dep graph + {Packages, Graph} = rebar_packages:get_packages(State), + ProjectApps = rebar_state:project_apps(State), + + %% Split source deps form binary deps, needed to keep backwards compatibility + DepsDir = get_deps_dir(State), + {SrcDeps, BinaryDeps} = parse_deps(DepsDir, Deps), + State1 = rebar_state:src_deps(rebar_state:binary_deps(State, BinaryDeps), + lists:ukeysort(2, SrcDeps)), + + %% Fetch transitive src deps + State2 = update_src_deps(State1), + Solved = case rebar_state:binary_deps(State2) of + [] -> %% No binary deps + []; + BinaryDeps1 -> + %% Find binary deps needed + {ok, S} = rlx_depsolver:solve(Graph, BinaryDeps1), + + %% Create app_info record for each binary dep + lists:map(fun({Name, Vsn}) -> + AppInfo = package_to_app(DepsDir + ,Packages + ,Name + ,Vsn), + ok = maybe_fetch(AppInfo), + AppInfo + end, S) + end, + + FinalDeps = ProjectApps ++ rebar_state:src_deps(State2) ++ Solved, + %% Sort all apps to build order + {ok, Sort} = rebar_topo:sort_apps(FinalDeps), + {ok, rebar_state:project_apps(State2, Sort)}. + +-spec package_to_app(file:name(), dict:dict(), binary(), binary()) -> rebar_app_info:t(). +package_to_app(DepsDir, Packages, 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), + + {ok, AppInfo} = rebar_app_info:new(Name, FmtVsn), + AppInfo1 = rebar_app_info:deps(AppInfo, PkgDeps), + AppInfo2 = + rebar_app_info:dir(AppInfo1, get_deps_dir(DepsDir, <<Name/binary, "-", FmtVsn/binary>>)), + rebar_app_info:source(AppInfo2, {Name, FmtVsn, Link}). + +-spec update_src_deps(rebar_state:t()) -> rebat_state:t(). update_src_deps(State) -> SrcDeps = rebar_state:src_deps(State), DepsDir = get_deps_dir(State), - case lists:foldl(fun(AppInfo, {SrcDepsAcc, GoalsAcc}) -> + case lists:foldl(fun(AppInfo, {SrcDepsAcc, BinaryDepsAcc}) -> ok = maybe_fetch(AppInfo), - {NewSrcDeps, NewGoals} = handle_dep(DepsDir, AppInfo), - {lists:ukeymerge(2, SrcDepsAcc, lists:ukeysort(2, NewSrcDeps)), NewGoals++GoalsAcc} - end, {SrcDeps, rebar_state:goals(State)}, SrcDeps) of - {SrcDeps, NewGoals} -> - rebar_state:goals(State, NewGoals); - {NewSrcDeps, NewGoals} -> - io:format("NEWSRC ~p~n", [NewSrcDeps]), - State1 = rebar_state:src_deps(rebar_state:goals(State, NewGoals), NewSrcDeps), + {AppInfo1, NewSrcDeps, NewBinaryDeps} = handle_dep(DepsDir, AppInfo), + {lists:ukeymerge(2, lists:ukeysort(2, [AppInfo1 | SrcDepsAcc]), lists:ukeysort(2, NewSrcDeps)), NewBinaryDeps++BinaryDepsAcc} + end, {[], rebar_state:binary_deps(State)}, SrcDeps) of + {NewSrcDeps, NewBinaryDeps} when length(SrcDeps) =:= length(NewSrcDeps) -> + rebar_state:src_deps(rebar_state:binary_deps(State, NewBinaryDeps), NewSrcDeps); + {NewSrcDeps, NewBinaryDeps} -> + State1 = rebar_state:src_deps(rebar_state:binary_deps(State, NewBinaryDeps), NewSrcDeps), update_src_deps(State1) end. +-spec handle_dep(binary(), rebar_state:t()) -> {[rebar_app_info:t()], [binary_dep()]}. handle_dep(DepsDir, 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, []), - parse_deps(DepsDir, Deps). + AppInfo1 = rebar_app_info:deps(AppInfo, rebar_state:deps_names(S)), + {SrcDeps, BinaryDeps} = parse_deps(DepsDir, Deps), + {AppInfo1, SrcDeps, BinaryDeps}. +-spec maybe_fetch(rebar_app_info:t()) -> ok. maybe_fetch(AppInfo) -> AppDir = rebar_app_info:dir(AppInfo), case filelib:is_dir(AppDir) of @@ -174,19 +193,21 @@ maybe_fetch(AppInfo) -> ok end. +-spec parse_deps(binary(), [dep()]) -> {[rebar_app_info:t()], [binary_dep()]}. parse_deps(DepsDir, Deps) -> - lists:foldl(fun({Name, Vsn}, {SrcDepsAcc, GoalsAcc}) -> + lists:foldl(fun({Name, Vsn}, {SrcDepsAcc, BinaryDepsAcc}) -> {SrcDepsAcc, [parse_goal(ec_cnv:to_binary(Name) - ,ec_cnv:to_binary(Vsn)) | GoalsAcc]}; - (Name, {SrcDepsAcc, GoalsAcc}) when is_atom(Name) -> - {SrcDepsAcc, [ec_cnv:to_binary(Name) | GoalsAcc]}; - ({Name, _, Source}, {SrcDepsAcc, GoalsAcc}) -> + ,ec_cnv:to_binary(Vsn)) | BinaryDepsAcc]}; + (Name, {SrcDepsAcc, BinaryDepsAcc}) when is_atom(Name) -> + {SrcDepsAcc, [ec_cnv:to_binary(Name) | BinaryDepsAcc]}; + ({Name, _, Source}, {SrcDepsAcc, BinaryDepsAcc}) -> {ok, Dep} = rebar_app_info:new(Name), Dep1 = rebar_app_info:source( rebar_app_info:dir(Dep, get_deps_dir(DepsDir, Name)), Source), - {[Dep1 | SrcDepsAcc], GoalsAcc} + {[Dep1 | SrcDepsAcc], BinaryDepsAcc} end, {[], []}, Deps). +-spec parse_goal(binary(), binary()) -> binary_dep(). parse_goal(Name, Constraint) -> case re:run(Constraint, "([^\\d]*)(\\d.*)", [{capture, [1,2], binary}]) of {match, [<<>>, Vsn]} -> diff --git a/src/rebar_state.erl b/src/rebar_state.erl index fc5d750..da0c9d8 100644 --- a/src/rebar_state.erl +++ b/src/rebar_state.erl @@ -7,9 +7,10 @@ set_skip_dir/2, is_skip_dir/2, reset_skip_dirs/1, create_logic_providers/2, - apps_to_build/1, apps_to_build/2, + project_apps/1, project_apps/2, - goals/1, goals/2, + deps_names/1, + binary_deps/1, binary_deps/2, src_deps/1, src_deps/2, providers/1, providers/2, add_provider/2]). @@ -33,10 +34,10 @@ command_args = [] :: list(), src_deps = [] :: [rebar_app_info:t()], - apps = dict:new() :: rebar_dict(), - goals = [], + binary_deps = [], + project_apps = [], + providers = [], - apps_to_build = [], skip_dirs = new_skip_dirs() :: rebar_dict() }). -export_type([t/0]). @@ -105,13 +106,22 @@ 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]}. +deps_names(State) -> + Deps = rebar_state:get(State, deps, []), + lists:map(fun(Dep) when is_tuple(Dep) -> + ec_cnv:to_binary(element(1, Dep)); + (Dep) when is_atom(Dep) -> + ec_cnv:to_binary(Dep) + end, Deps). + +binary_deps(#state_t{binary_deps=BinaryDeps}) -> + BinaryDeps. + +binary_deps(State=#state_t{binary_deps=BinaryDeps}, NewBinaryDeps) when is_list(BinaryDeps) -> + State#state_t{binary_deps=NewBinaryDeps}; +binary_deps(State=#state_t{binary_deps=BinaryDeps}, BinaryDep) -> + State#state_t{binary_deps=[BinaryDep | BinaryDeps]}. src_deps(#state_t{src_deps=SrcDeps}) -> SrcDeps. @@ -121,13 +131,13 @@ src_deps(State=#state_t{src_deps=SrcDeps}, NewSrcDeps) when is_list(SrcDeps) -> 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}) -> +project_apps(#state_t{project_apps=Apps}) -> 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]}. +project_apps(State=#state_t{}, NewApps) when is_list(NewApps) -> + State#state_t{project_apps=NewApps}; +project_apps(State=#state_t{project_apps=Apps}, App) -> + State#state_t{project_apps=[App | Apps]}. providers(#state_t{providers=Providers}) -> Providers. |