Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

94 строки
3.5 KiB

10 лет назад
10 лет назад
10 лет назад
10 лет назад
10 лет назад
10 лет назад
10 лет назад
10 лет назад
10 лет назад
10 лет назад
10 лет назад
  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).