diff options
author | Tristan Sloughter <t@crashfast.com> | 2014-11-21 20:48:01 -0600 |
---|---|---|
committer | Tristan Sloughter <t@crashfast.com> | 2014-11-22 20:24:21 -0600 |
commit | f22db1302d710fbf017108852991cd6ac538de17 (patch) | |
tree | 2cac83b89b7aaac9da911eb63eb6ee1016ac6a60 | |
parent | e9b58f2775704226b514e967097e902a232081f3 (diff) |
new dep graph working
-rw-r--r-- | include/rebar.hrl | 16 | ||||
-rw-r--r-- | src/rebar_digraph.erl | 101 | ||||
-rw-r--r-- | src/rebar_erlc_compiler.erl | 79 | ||||
-rw-r--r-- | src/rebar_packages.erl | 6 | ||||
-rw-r--r-- | src/rebar_prv_install_deps.erl | 2 | ||||
-rw-r--r-- | src/rebar_prv_update.erl | 4 |
6 files changed, 125 insertions, 83 deletions
diff --git a/include/rebar.hrl b/include/rebar.hrl index af3f81c..794d738 100644 --- a/include/rebar.hrl +++ b/include/rebar.hrl @@ -27,3 +27,19 @@ -else. -type rebar_dict() :: dict(). -endif. + +-ifdef(namespaced_types). +-type rebar_digraph() :: digraph:graph(). +-else. +-type rebar_digraph() :: digraph(). +-endif. + +-define(GRAPH_VSN, 2). +-type v() :: {digraph:vertex(), term()} | 'false'. +-type e() :: {digraph:vertex(), digraph:vertex()}. +-type graph() :: {list(v()), list(e())}. +-record(graph, + { + vsn = ?GRAPH_VSN :: pos_integer(), + info = {[], []} :: graph() + }). diff --git a/src/rebar_digraph.erl b/src/rebar_digraph.erl new file mode 100644 index 0000000..decc542 --- /dev/null +++ b/src/rebar_digraph.erl @@ -0,0 +1,101 @@ +-module(rebar_digraph). + +-export([check_graph/2 + ,restore_graph/1 + ,store_graph/3 + ,solve/2 + ,subgraph/2]). + +-include("rebar.hrl"). + +check_graph(_File, #graph{vsn=?GRAPH_VSN}) -> + ok; +check_graph(File, #graph{vsn=Vsn}) -> + ?ABORT("~s file version is incompatible. expected: ~b got: ~b", + [File, ?GRAPH_VSN, Vsn]); +check_graph(File, _) -> + ?ABORT("~s file is invalid. Please delete before next run.", + [File]). + +restore_graph({Vs, Es}) -> + G = digraph:new(), + lists:foreach(fun({V, LastUpdated}) -> + digraph:add_vertex(G, V, LastUpdated) + end, Vs), + lists:foreach(fun({V1, V2}) -> + digraph:add_edge(G, V1, V2) + end, Es), + G; +restore_graph(File) -> + G = digraph:new(), + case file:read_file(File) of + {ok, Data} -> + try binary_to_term(Data) of + G -> + %% ok = check_erlcinfo(Config, Graph), + #graph{info=Graph} = G, + {Vs, Es} = Graph, + lists:foreach( + fun({V, LastUpdated}) -> + digraph:add_vertex(G, V, LastUpdated) + end, Vs), + lists:foreach( + fun({V1, V2}) -> + digraph:add_edge(G, V1, V2) + end, Es) + catch + error:badarg -> + ?ERROR( + "Failed (binary_to_term) to restore rebar info file." + " Discard file.", []), + ok + end; + _Err -> + ok + end, + G. + +store_graph(_G, _File, _Modified = false) -> + ok; +store_graph(G, File, _Modified) -> + Vs = lists:map( + fun(V) -> + digraph:vertex(G, V) + end, digraph:vertices(G)), + Es = lists:flatmap( + fun({V, _}) -> + lists:map( + fun(E) -> + {_, V1, V2, _} = digraph:edge(G, E), + {V1, V2} + end, digraph:out_edges(G, V)) + end, Vs), + + ok = filelib:ensure_dir(File), + Data = term_to_binary(#graph{info={Vs, Es}}, [{compressed, 9}]), + file:write_file(File, Data). + +solve(Graph, Vertices) -> + solve(Graph, Vertices, dict:new()). + +solve(_Graph, [], Solution) -> + {_, Vertices} = lists:unzip(dict:to_list(Solution)), + Vertices; +solve(Graph, Vertices, Solution) -> + {NV, NS} = + lists:foldl(fun(V, {NewVertices, SolutionAcc}) -> + OutNeighbors = digraph:out_neighbours(Graph, V), + lists:foldl(fun({Key, _}=N, {NewVertices1, SolutionAcc1}) -> + case dict:is_key(Key, SolutionAcc1) orelse + lists:keymember(Key, 1, Vertices) of + true -> + {NewVertices1, SolutionAcc1}; + false -> + {[N | NewVertices1], dict:store(Key, N, SolutionAcc1)} + end + end, {NewVertices, SolutionAcc}, OutNeighbors) + end, {[], Solution}, Vertices), + solve(Graph, NV, NS). + +subgraph(Graph, Vertices) -> + digraph_utils:subgraph(Graph, Vertices). diff --git a/src/rebar_erlc_compiler.erl b/src/rebar_erlc_compiler.erl index 1277242..5e7787c 100644 --- a/src/rebar_erlc_compiler.erl +++ b/src/rebar_erlc_compiler.erl @@ -38,25 +38,9 @@ -define(ERLCINFO_VSN, 1). -define(ERLCINFO_FILE, "erlcinfo"). --type erlc_info_v() :: {digraph:vertex(), term()} | 'false'. --type erlc_info_e() :: {digraph:vertex(), digraph:vertex()}. --type erlc_info() :: {list(erlc_info_v()), list(erlc_info_e())}. --record(erlcinfo, - { - vsn = ?ERLCINFO_VSN :: pos_integer(), - info = {[], []} :: erlc_info() - }). -define(RE_PREFIX, "^[^._]"). --ifdef(namespaced_types). -%% digraph:graph() exists starting from Erlang 17. --type rebar_digraph() :: digraph:graph(). --else. -%% digraph() has been obsoleted in Erlang 17 and deprecated in 18. --type rebar_digraph() :: digraph(). --endif. - %% =================================================================== %% Public API %% =================================================================== @@ -408,20 +392,11 @@ needs_compile(Source, Target, Parents) -> lists:any(fun(I) -> TargetLastMod < filelib:last_modified(I) end, [Source] ++ Parents). -check_erlcinfo(_Config, #erlcinfo{vsn=?ERLCINFO_VSN}) -> - ok; -check_erlcinfo(Config, #erlcinfo{vsn=Vsn}) -> - ?ABORT("~s file version is incompatible. expected: ~b got: ~b", - [erlcinfo_file(Config), ?ERLCINFO_VSN, Vsn]); -check_erlcinfo(Config, _) -> - ?ABORT("~s file is invalid. Please delete before next run.", - [erlcinfo_file(Config)]). - erlcinfo_file(_Config) -> filename:join([rebar_utils:get_cwd(), ?CONFIG_DIR, ?ERLCINFO_FILE]). init_erlcinfo(Config, Erls) -> - G = restore_erlcinfo(Config), + G = rebar_digraph:restore_graph(erlcinfo_file(Config)), %% Get a unique list of dirs based on the source files' locations. %% This is used for finding files in sub dirs of the configured %% src_dirs. For example, src/sub_dir/foo.erl. @@ -433,7 +408,7 @@ init_erlcinfo(Config, Erls) -> Updates = [update_erlcinfo(G, Erl, include_path(Erl, Config) ++ Dirs) || Erl <- Erls], Modified = lists:member(modified, Updates), - ok = store_erlcinfo(G, Config, Modified), + ok = rebar_digraph:store_graph(G, erlcinfo_file(Config), Modified), G. update_erlcinfo(G, Source, Dirs) -> @@ -470,56 +445,6 @@ modify_erlcinfo(G, Source, Dirs) -> digraph:add_edge(G, Source, Incl) end, AbsIncls). -restore_erlcinfo(Config) -> - File = erlcinfo_file(Config), - G = digraph:new(), - case file:read_file(File) of - {ok, Data} -> - try binary_to_term(Data) of - Erlcinfo -> - ok = check_erlcinfo(Config, Erlcinfo), - #erlcinfo{info=ErlcInfo} = Erlcinfo, - {Vs, Es} = ErlcInfo, - lists:foreach( - fun({V, LastUpdated}) -> - digraph:add_vertex(G, V, LastUpdated) - end, Vs), - lists:foreach( - fun({V1, V2}) -> - digraph:add_edge(G, V1, V2) - end, Es) - catch - error:badarg -> - ?ERROR( - "Failed (binary_to_term) to restore rebar info file." - " Discard file.", []), - ok - end; - _Err -> - ok - end, - G. - -store_erlcinfo(_G, _Config, _Modified = false) -> - ok; -store_erlcinfo(G, Config, _Modified) -> - Vs = lists:map( - fun(V) -> - digraph:vertex(G, V) - end, digraph:vertices(G)), - Es = lists:flatmap( - fun({V, _}) -> - lists:map( - fun(E) -> - {_, V1, V2, _} = digraph:edge(G, E), - {V1, V2} - end, digraph:out_edges(G, V)) - end, Vs), - File = erlcinfo_file(Config), - ok = filelib:ensure_dir(File), - Data = term_to_binary(#erlcinfo{info={Vs, Es}}, [{compressed, 9}]), - file:write_file(File, Data). - %% NOTE: If, for example, one of the entries in Files, refers to %% gen_server.erl, that entry will be dropped. It is dropped because %% such an entry usually refers to the beam file, and we don't pass a diff --git a/src/rebar_packages.erl b/src/rebar_packages.erl index 7974fda..7334365 100644 --- a/src/rebar_packages.erl +++ b/src/rebar_packages.erl @@ -14,12 +14,12 @@ get_packages(State) -> try {ok, Binary} = file:read_file(PackagesFile), {Dict, Graph} = binary_to_term(Binary), - {Dict, Graph} + {Dict, rebar_digraph:restore_graph(Graph)} catch _:_ -> ?ERROR("Bad packages index, try to fix with `rebar update`~n", []), - {dict:new(), rlx_depsolver:new_graph()} + {dict:new(), digraph:new()} end; false -> - {dict:new(), rlx_depsolver:new_graph()} + {dict:new(), digraph:new()} end. diff --git a/src/rebar_prv_install_deps.erl b/src/rebar_prv_install_deps.erl index f3c050e..7e41429 100644 --- a/src/rebar_prv_install_deps.erl +++ b/src/rebar_prv_install_deps.erl @@ -130,7 +130,7 @@ handle_deps(State, Deps, Update) -> []; PkgDeps1 -> %% Find pkg deps needed - S = case rlx_depsolver:solve(Graph, PkgDeps1) of + S = case rebar_digraph:solve(Graph, PkgDeps1) of {ok, Solution} -> Solution; Reason -> diff --git a/src/rebar_prv_update.erl b/src/rebar_prv_update.erl index 4751e05..16987be 100644 --- a/src/rebar_prv_update.erl +++ b/src/rebar_prv_update.erl @@ -40,8 +40,8 @@ do(State) -> Home = rebar_utils:home_dir(), PackagesFile = filename:join([Home, ?CONFIG_DIR, "packages"]), filelib:ensure_dir(PackagesFile), - {ok, _RequestId} = httpc:request(get, {Url, []}, [], [{stream, TmpFile} - ,{sync, true}]), + {ok, _RequestId} = httpc:request(get, {Url, [{"Accept", "application/erlang"}]}, + [], [{stream, TmpFile}, {sync, true}]), ok = ec_file:copy(TmpFile, PackagesFile) catch _:_ -> |