diff options
author | Tristan Sloughter <t@crashfast.com> | 2014-08-24 12:01:03 -0500 |
---|---|---|
committer | Tristan Sloughter <t@crashfast.com> | 2014-08-24 12:01:03 -0500 |
commit | 4b31a20a61b89d2979816646f8feca806d419564 (patch) | |
tree | dd628be4acef39699121b2a68942bf16e0178f12 /src/rebar_prv_deps.erl | |
parent | 9c6e20d3287e532946a518f1455be8d6ddcf6b14 (diff) |
improved dep handling and add package list task
Diffstat (limited to 'src/rebar_prv_deps.erl')
-rw-r--r-- | src/rebar_prv_deps.erl | 224 |
1 files changed, 4 insertions, 220 deletions
diff --git a/src/rebar_prv_deps.erl b/src/rebar_prv_deps.erl index 0e5cb31..834e7dc 100644 --- a/src/rebar_prv_deps.erl +++ b/src/rebar_prv_deps.erl @@ -1,29 +1,3 @@ -%% -*- erlang-indent-level: 4;indent-tabs-mode: nil -*- -%% ex: ts=4 sw=4 et -%% ------------------------------------------------------------------- -%% -%% rebar: Erlang Build Tools -%% -%% Copyright (c) 2009 Dave Smith (dizzyd@dizzyd.com) -%% -%% Permission is hereby granted, free of charge, to any person obtaining a copy -%% of this software and associated documentation files (the "Software"), to deal -%% in the Software without restriction, including without limitation the rights -%% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -%% copies of the Software, and to permit persons to whom the Software is -%% furnished to do so, subject to the following conditions: -%% -%% The above copyright notice and this permission notice shall be included in -%% all copies or substantial portions of the Software. -%% -%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -%% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -%% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -%% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -%% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -%% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -%% THE SOFTWARE. -%% ------------------------------------------------------------------- -module(rebar_prv_deps). -behaviour(rebar_provider). @@ -33,22 +7,8 @@ -include("rebar.hrl"). --export([setup_env/1]). - -%% for internal use only --export([get_deps_dir/1]). --export([get_deps_dir/2]). - -define(PROVIDER, deps). --define(DEPS, [app_discovery]). - --record(dep, {name :: binary(), - vsn :: binary(), - source :: binary()}). - -%% =================================================================== -%% Public API -%% =================================================================== +-define(DEPS, []). -spec init(rebar_state:t()) -> {ok, rebar_state:t()}. init(State) -> @@ -57,190 +17,14 @@ init(State) -> bare = false, deps = ?DEPS, example = "rebar deps", - short_desc = "Install dependencies", - desc = info("Install dependencies"), + short_desc = "List dependencies", + desc = info("List dependencies"), opts = []}), {ok, State1}. -spec do(rebar_state:t()) -> {ok, rebar_state:t()}. do(State) -> - %% Read in package index and dep graph - {Packages, Graph} = get_packages(State), - - case rebar_state:get(State, deps, []) of - [] -> - {ok, State}; - Deps -> - %% Split source deps form binary deps, needed to keep backwards compatibility - case parse_deps(Deps) of - {SrcDeps, []} -> - {State1, SrcDeps1} = update_src_deps(State, SrcDeps), - {ok, rebar_state:set(State1, deps, SrcDeps1)}; - {SrcDeps, Goals} -> - {State1, _SrcDeps1} = update_src_deps(State, SrcDeps), - {ok, Solved} = rlx_depsolver:solve(Graph, Goals), - M = lists:map(fun({Name, Vsn}) -> - FmtVsn = to_binary(rlx_depsolver:format_version(Vsn)), - {ok, P} = dict:find({Name, FmtVsn}, Packages), - Link = proplists:get_value(<<"link">>, P), - {Name, Vsn, {Name - ,FmtVsn - ,Link}} - end, Solved), - - {State2, Deps1} = update_deps(State1, M), - State3 = rebar_state:set(State2, deps, Deps1), - {ok, rebar_state:set(State3, goals, Goals)} - end - end. - -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, FoundApps, UnbuiltApps, Deps). - -update_src_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]), - - %% Resolve deps and their dependencies - Deps1 = handle_src_deps(Deps, UnbuiltApps++FoundApps), - {State1, Missing} = download_missing_deps(State, DepsDir, FoundApps, UnbuiltApps, Deps1), - case dict:is_empty(Missing) of - true -> - {State1, Deps1}; - false -> - update_src_deps(State1, Missing) - end. - -handle_src_deps(Deps, Found) -> - lists:foldl(fun(X, DepsAcc) -> - C = rebar_config:consult(rebar_app_info:dir(X)), - S = rebar_state:new(rebar_state:new(), C, rebar_app_info:dir(X)), - {ParsedDeps, _Goals} = parse_deps(rebar_state:get(S, deps, [])), - dict:merge(fun(_K, V1, _V2) -> V1 end, DepsAcc, ParsedDeps) - end, Deps, Found). - -download_missing_deps(State, DepsDir, Found, Unbuilt, Deps) -> - Missing = - dict:filter(fun(Key, _) -> - not lists:any(fun(F) -> - Key =:= to_binary(rebar_app_info:name(F)) - end, Found++Unbuilt) - end, Deps), - dict:map(fun(_Key, #dep{name=Name, source=Source}) -> - TargetDir = get_deps_dir(DepsDir, Name), - case filelib:is_dir(TargetDir) of - true -> - ok; - false -> - ?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] -> - C = rebar_config:consult(rebar_app_info:dir(AppSrc)), - S = rebar_state:new(rebar_state:new() - ,C - ,rebar_app_info:dir(AppSrc)), - rebar_prv_app_builder:build(S, AppSrc); - [] -> - [] - end - end - end, Missing), - - {State, Missing}. - -%% set REBAR_DEPS_DIR and ERL_LIBS environment variables -setup_env(State) -> - DepsDir = get_deps_dir(State), - %% include rebar's DepsDir in ERL_LIBS - Separator = case os:type() of - {win32, nt} -> - ";"; - _ -> - ":" - end, - ERL_LIBS = case os:getenv("ERL_LIBS") of - false -> - {"ERL_LIBS", DepsDir}; - PrevValue -> - {"ERL_LIBS", DepsDir ++ Separator ++ PrevValue} - end, - [{"REBAR_DEPS_DIR", DepsDir}, ERL_LIBS]. - - -get_deps_dir(State) -> - BaseDir = rebar_state:get(State, base_dir, ""), - get_deps_dir(BaseDir, "deps"). - -get_deps_dir(DepsDir, App) -> - filename:join(DepsDir, App). - -%% =================================================================== -%% Internal functions -%% =================================================================== - -new({Name, Vsn, Source})-> - #dep{name=to_binary(Name), vsn=to_binary(Vsn), source=Source}; -new(Name) -> - #dep{name=to_binary(Name)}. - --spec name(record(dep)) -> binary(). -name(#dep{name=Name}) -> - Name. - --spec vsn(record(dep)) -> binary(). -vsn(#dep{vsn=Vsn}) -> - Vsn. - --spec source(record(dep)) -> tuple(). -source(#dep{source=Source}) -> - Source. - -to_binary(X) when is_binary(X) -> - X; -to_binary(X) when is_atom(X) -> - atom_to_binary(X, utf8); -to_binary(X) when is_list(X) -> - iolist_to_binary(X). - -parse_deps(Deps) -> - lists:foldl(fun({Name, Vsn}, {SrcDepsAcc, GoalsAcc}) -> - {SrcDepsAcc, [{to_binary(Name), to_binary(Vsn)} | GoalsAcc]}; - (Name, {SrcDepsAcc, GoalsAcc}) when is_atom(Name) -> - {SrcDepsAcc, [to_binary(Name) | GoalsAcc]}; - (SrcDep, {SrcDepsAcc, GoalsAcc}) -> - Dep = new(SrcDep), - {dict:store(name(Dep), Dep, SrcDepsAcc), GoalsAcc} - end, {dict:new(), []}, Deps). - -get_packages(State) -> - RebarDir = rebar_state:get(State, global_rebar_dir, filename:join(os:getenv("HOME"), ".rebar")), - PackagesFile = filename:join(RebarDir, "packages"), - case ec_file:exists(PackagesFile) of - true -> - try - {ok, Binary} = file:read_file(PackagesFile), - binary_to_term(Binary) - catch - _:_ -> - ?ERROR("Bad packages index, try to fix with `rebar update`~n", []), - {[], rlx_depsolver:new()} - end; - false -> - {[], rlx_depsolver:new()} - end. + {ok, State}. info(Description) -> io_lib:format("~s.~n" |