You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

94 rivejä
3.5 KiB

10 vuotta sitten
10 vuotta sitten
10 vuotta sitten
10 vuotta sitten
10 vuotta sitten
10 vuotta sitten
10 vuotta sitten
10 vuotta sitten
10 vuotta sitten
10 vuotta sitten
10 vuotta sitten
  1. -module(rebar_digraph).
  2. -export([sort_apps/1
  3. ,restore_graph/1
  4. ,solve/2
  5. ,subgraph/2
  6. ,format_error/1]).
  7. -include("rebar.hrl").
  8. sort_apps(Apps) ->
  9. Graph = digraph:new(),
  10. lists:foreach(fun(App) ->
  11. Name = rebar_app_info:name(App),
  12. Deps = rebar_app_info:deps(App),
  13. add(Graph, {Name, Deps})
  14. end, Apps),
  15. case digraph_utils:topsort(Graph) of
  16. false ->
  17. {error, no_sort};
  18. V ->
  19. {ok, names_to_apps(lists:reverse(V), Apps)}
  20. end.
  21. add(Graph, {PkgName, Deps}) ->
  22. case digraph:vertex(Graph, PkgName) of
  23. false ->
  24. V = digraph:add_vertex(Graph, PkgName);
  25. {V, []} ->
  26. V
  27. end,
  28. lists:foreach(fun(DepName) ->
  29. V3 = case digraph:vertex(Graph, DepName) of
  30. false ->
  31. digraph:add_vertex(Graph, DepName);
  32. {V2, []} ->
  33. V2
  34. end,
  35. digraph:add_edge(Graph, V, V3)
  36. end, Deps).
  37. restore_graph({Vs, Es}) ->
  38. Graph = digraph:new(),
  39. lists:foreach(fun({V, LastUpdated}) ->
  40. digraph:add_vertex(Graph, V, LastUpdated)
  41. end, Vs),
  42. lists:foreach(fun({V1, V2}) ->
  43. digraph:add_edge(Graph, V1, V2)
  44. end, Es),
  45. Graph.
  46. solve(Graph, Vertices) ->
  47. solve(Graph, Vertices, lists:foldl(fun({Key, _}=N, Solution) ->
  48. dict:store(Key, N, Solution)
  49. end, dict:new(), Vertices)).
  50. solve(_Graph, [], Solution) ->
  51. {_, Vertices} = lists:unzip(dict:to_list(Solution)),
  52. {ok, Vertices};
  53. solve(Graph, Vertices, Solution) ->
  54. {NV, NS} =
  55. lists:foldl(fun(V, {NewVertices, SolutionAcc}) ->
  56. OutNeighbors = digraph:out_neighbours(Graph, V),
  57. lists:foldl(fun({Key, _}=N, {NewVertices1, SolutionAcc1}) ->
  58. case dict:is_key(Key, SolutionAcc1) of
  59. true ->
  60. {NewVertices1, SolutionAcc1};
  61. false ->
  62. {[N | NewVertices1], dict:store(Key, N, SolutionAcc1)}
  63. end
  64. end, {NewVertices, SolutionAcc}, OutNeighbors)
  65. end, {[], Solution}, Vertices),
  66. solve(Graph, NV, NS).
  67. subgraph(Graph, Vertices) ->
  68. digraph_utils:subgraph(Graph, Vertices).
  69. format_error(no_solution) ->
  70. io_lib:format("No solution for packages found.", []).
  71. %%====================================================================
  72. %% Internal Functions
  73. %%====================================================================
  74. -spec names_to_apps([atom()], [rebar_app_info:t()]) -> [rebar_app_info:t()].
  75. names_to_apps(Names, Apps) ->
  76. [element(2, App) || App <- [find_app_by_name(Name, Apps) || Name <- Names], App =/= error].
  77. -spec find_app_by_name(atom(), [rebar_app_info:t()]) -> {ok, rebar_app_info:t()} | error.
  78. find_app_by_name(Name, Apps) ->
  79. ec_lists:find(fun(App) ->
  80. ec_cnv:to_atom(rebar_app_info:name(App)) =:= ec_cnv:to_atom(Name)
  81. end, Apps).