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.

148 line
5.2 KiB

  1. -module(rebar_prv_deps).
  2. -behaviour(provider).
  3. -export([init/1,
  4. do/1,
  5. format_error/1]).
  6. -include("rebar.hrl").
  7. -define(PROVIDER, deps).
  8. -define(DEPS, [install_deps]).
  9. -spec init(rebar_state:t()) -> {ok, rebar_state:t()}.
  10. init(State) ->
  11. State1 = rebar_state:add_provider(
  12. State,
  13. providers:create([
  14. {name, ?PROVIDER},
  15. {module, ?MODULE},
  16. {bare, true},
  17. {deps, ?DEPS},
  18. {example, "rebar3 deps"},
  19. {short_desc, "List dependencies"},
  20. {desc, "List dependencies. Those not matching "
  21. "the config file are followed by "
  22. "an asterisk (*)."},
  23. {opts, []}])),
  24. {ok, State1}.
  25. -spec do(rebar_state:t()) -> {ok, rebar_state:t()} | {error, string()}.
  26. do(State) ->
  27. Profiles = rebar_state:current_profiles(State),
  28. [display(State, Profile) || Profile <- Profiles],
  29. {ok, State}.
  30. -spec format_error(any()) -> iolist().
  31. format_error(Reason) ->
  32. io_lib:format("~p", [Reason]).
  33. display(State, Profile = default) ->
  34. display_profile_deps(State, Profile),
  35. ?CONSOLE("", []);
  36. display(State, Profile) ->
  37. ?CONSOLE("-- ~p --", [Profile]),
  38. display_profile_deps(State, Profile),
  39. ?CONSOLE("", []).
  40. display_profile_deps(State, Profile) ->
  41. DepsDir = rebar_prv_install_deps:profile_dep_dir(State, Profile),
  42. ProfileDeps = rebar_state:get(State, {deps, Profile}, []),
  43. % ProfileDeps include those deps from rebar.lock that have been
  44. % removed from rebar.config
  45. ConfiguredDeps = [parse_dep_without_locks(DepsDir, Dep, State)
  46. || Dep <- ProfileDeps],
  47. LockedDepsMap = locked_deps_map(State, Profile),
  48. [display_dep(State, Dep, LockedDepsMap) || Dep <- ConfiguredDeps].
  49. parse_dep_without_locks(DepsDir, Dep, State) ->
  50. ParsedDep = rebar_app_utils:parse_dep(Dep, root, DepsDir, State, [], 0),
  51. case Dep of
  52. {_Name, Src, Level} when is_tuple(Src), is_integer(Level) ->
  53. % This Dep is not in rebar.config but in rebar.lock
  54. rebar_app_info:source(ParsedDep, undefined);
  55. _ ->
  56. rebar_app_utils:expand_deps_sources(ParsedDep, State)
  57. end.
  58. locked_deps_map(State, Profile) ->
  59. ParsedDeps = rebar_state:get(State, {parsed_deps, Profile}, []),
  60. lists:foldl(fun(Dep, DepsIn) ->
  61. case rebar_app_info:is_lock(Dep) of
  62. true ->
  63. DepName = rebar_app_info:name(Dep),
  64. maps:put(rebar_utils:to_binary(DepName), Dep, DepsIn);
  65. _ ->
  66. DepsIn
  67. end
  68. end, maps:new(), ParsedDeps).
  69. display_dep(State, Dep, LockedDeps) ->
  70. Name = rebar_utils:to_binary(rebar_app_info:name(Dep)),
  71. NeedsUpdate = rebar_fetch:needs_update(Dep, State),
  72. Source = rebar_app_info:source(Dep),
  73. LockedSource = case maps:get(Name, LockedDeps, undefined) of
  74. undefined -> undefined;
  75. LockedDep -> rebar_app_info:source(LockedDep)
  76. end,
  77. display_dep_line(Name, NeedsUpdate, source_text(LockedSource), source_text(Source)).
  78. % Dep is a checkout
  79. display_dep_line(Name, _NeedsUpdate, _LockedSource, Source = checkout) ->
  80. ?CONSOLE("~ts* (~ts)", [Name, Source]);
  81. % Dep exists only in lock file
  82. display_dep_line(Name, _NeedsUpdate, LockedSource, _Source = undefined) ->
  83. ?CONSOLE("~ts* (locked ~ts <> none)", [Name, LockedSource]);
  84. % Dep not locked, report whether the disk copy matches the Source
  85. display_dep_line(Name, true, undefined, Source) ->
  86. ?CONSOLE("~ts* (~ts)", [Name, Source]);
  87. display_dep_line(Name, _, undefined, Source) ->
  88. ?CONSOLE("~ts (~ts)", [Name, Source]);
  89. % Dep locked, install_deps provider should have had updated the disk copy with
  90. % the locked version
  91. display_dep_line(Name, false, _LockedSource, Source) ->
  92. % dep locked and no need to update (LockedSource and Source might not match
  93. % because of one using {ref, X} and the other {tag, Y})
  94. ?CONSOLE("~ts (locked ~ts)", [Name, Source]);
  95. display_dep_line(Name, _NeedsUpdate, LockedSource, Source) ->
  96. % dep locked with mismatching lock and config files
  97. ?CONSOLE("~ts* (locked ~ts <> ~ts)", [Name, LockedSource, Source]).
  98. source_text(Source) when is_list(Source); is_atom(Source) ->
  99. Source;
  100. source_text({pkg, _Name, Vsn, _Hash, _RepoConfig}) ->
  101. source_text({pkg, _Name, Vsn, _Hash});
  102. source_text({pkg, _Name, Vsn, _Hash}) ->
  103. [<<"package">>, " ", rebar_utils:to_binary(Vsn)];
  104. source_text(Source) when is_tuple(Source), tuple_size(Source) < 3 ->
  105. element(1, Source);
  106. source_text(Source) when is_tuple(Source) ->
  107. Type = element(1, Source),
  108. case element(3, Source) of
  109. {ref , Ref} ->
  110. SmallRef = case rebar_utils:to_binary(Ref) of
  111. <<R:7/binary, _/binary>> -> <<R/binary, "...">>;
  112. R -> R
  113. end,
  114. [atom_to_binary(Type, unicode), " source ", SmallRef];
  115. {_ , Vsn} ->
  116. [atom_to_binary(Type, unicode), " source ", rebar_utils:to_binary(Vsn)];
  117. _ ->
  118. [atom_to_binary(Type, unicode), " source"]
  119. end.