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 /src/rebar_digraph.erl | |
parent | e9b58f2775704226b514e967097e902a232081f3 (diff) |
new dep graph working
Diffstat (limited to 'src/rebar_digraph.erl')
-rw-r--r-- | src/rebar_digraph.erl | 101 |
1 files changed, 101 insertions, 0 deletions
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). |