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.

92 lines
3.5 KiB

9 years ago
9 years ago
9 years ago
  1. -module(rebar_prv_deps_tree).
  2. -behaviour(provider).
  3. -export([init/1,
  4. do/1,
  5. format_error/1]).
  6. -include("rebar.hrl").
  7. -define(PROVIDER, tree).
  8. -define(DEPS, [lock]).
  9. -spec init(rebar_state:t()) -> {ok, rebar_state:t()}.
  10. init(State) ->
  11. State1 = rebar_state:add_provider(
  12. State,
  13. providers:create([{name, ?PROVIDER},
  14. {module, ?MODULE},
  15. {bare, true},
  16. {deps, ?DEPS},
  17. {example, "rebar3 tree"},
  18. {short_desc, "Print dependency tree."},
  19. {desc, ""},
  20. {opts, [{verbose, $v, "verbose", undefined, "Print repo and branch/tag/ref for git and hg deps"}]}])),
  21. {ok, State1}.
  22. -spec do(rebar_state:t()) -> {ok, rebar_state:t()} | {error, string()}.
  23. do(State) ->
  24. {Args, _} = rebar_state:command_parsed_args(State),
  25. Verbose = proplists:get_value(verbose, Args, false),
  26. print_deps_tree(rebar_state:all_deps(State), Verbose, State),
  27. {ok, State}.
  28. -spec format_error(any()) -> iolist().
  29. format_error(Reason) ->
  30. io_lib:format("~p", [Reason]).
  31. %% Internal functions
  32. print_deps_tree(SrcDeps, Verbose, State) ->
  33. D = lists:foldl(fun(App, Dict) ->
  34. Name = rebar_app_info:name(App),
  35. Vsn = rebar_app_info:original_vsn(App),
  36. Vsn1 = rebar_utils:vcs_vsn(App, Vsn, State),
  37. Source = rebar_app_info:source(App),
  38. Parent = rebar_app_info:parent(App),
  39. dict:append_list(Parent, [{Name, Vsn1, Source}], Dict)
  40. end, dict:new(), SrcDeps),
  41. ProjectAppNames = [{rebar_app_info:name(App)
  42. ,rebar_utils:vcs_vsn(App, rebar_app_info:original_vsn(App), State)
  43. ,project} || App <- rebar_state:project_apps(State)],
  44. case dict:find(root, D) of
  45. {ok, Children} ->
  46. print_children("", lists:keysort(1, Children++ProjectAppNames), D, Verbose);
  47. error ->
  48. print_children("", lists:keysort(1, ProjectAppNames), D, Verbose)
  49. end.
  50. print_children(_, [], _, _) ->
  51. ok;
  52. print_children(Prefix, [{Name, Vsn, Source} | Rest], Dict, Verbose) ->
  53. Prefix1 = case Rest of
  54. [] ->
  55. io:format("~ts~ts", [Prefix, <<226,148,148,226,148,128,32>>]), %Binary for └─ utf8%
  56. [Prefix, " "];
  57. _ ->
  58. io:format("~ts~ts", [Prefix, <<226,148,156,226,148,128,32>>]), %Binary for ├─ utf8%
  59. [Prefix, <<226,148,130,32,32>>] %Binary for │ utf8%
  60. end,
  61. io:format("~ts~ts~ts (~ts)~n", [Name, <<226,148,128>>, Vsn, type(Source, Verbose)]), %Binary for ─ utf8%
  62. case dict:find(Name, Dict) of
  63. {ok, Children} ->
  64. print_children(Prefix1, lists:keysort(1, Children), Dict, Verbose),
  65. print_children(Prefix, Rest, Dict, Verbose);
  66. error ->
  67. print_children(Prefix, Rest, Dict, Verbose)
  68. end.
  69. type(project, _) ->
  70. "project app";
  71. type(checkout, _) ->
  72. "checkout app";
  73. type(Source, Verbose) when is_tuple(Source) ->
  74. case {element(1, Source), Verbose} of
  75. {pkg, _} ->
  76. "hex package";
  77. {Other, false} ->
  78. io_lib:format("~ts repo", [Other]);
  79. {_, true} ->
  80. io_lib:format("~ts", [element(2, Source)])
  81. end.