149 lines
5.2 KiB
Erlang
149 lines
5.2 KiB
Erlang
-module(rebar_prv_deps).
|
|
|
|
-behaviour(provider).
|
|
|
|
-export([init/1,
|
|
do/1,
|
|
format_error/1]).
|
|
|
|
-include("rebar.hrl").
|
|
|
|
-define(PROVIDER, deps).
|
|
-define(DEPS, [install_deps]).
|
|
|
|
-spec init(rebar_state:t()) -> {ok, rebar_state:t()}.
|
|
init(State) ->
|
|
State1 = rebar_state:add_provider(
|
|
State,
|
|
providers:create([
|
|
{name, ?PROVIDER},
|
|
{module, ?MODULE},
|
|
{bare, true},
|
|
{deps, ?DEPS},
|
|
{example, "rebar3 deps"},
|
|
{short_desc, "List dependencies"},
|
|
{desc, "List dependencies. Those not matching "
|
|
"the config file are followed by "
|
|
"an asterisk (*)."},
|
|
{opts, []}])),
|
|
{ok, State1}.
|
|
|
|
|
|
-spec do(rebar_state:t()) -> {ok, rebar_state:t()} | {error, string()}.
|
|
do(State) ->
|
|
Profiles = rebar_state:current_profiles(State),
|
|
[display(State, Profile) || Profile <- Profiles],
|
|
{ok, State}.
|
|
|
|
|
|
-spec format_error(any()) -> iolist().
|
|
format_error(Reason) ->
|
|
io_lib:format("~p", [Reason]).
|
|
|
|
|
|
display(State, Profile = default) ->
|
|
display_profile_deps(State, Profile),
|
|
?CONSOLE("", []);
|
|
display(State, Profile) ->
|
|
?CONSOLE("-- ~p --", [Profile]),
|
|
display_profile_deps(State, Profile),
|
|
?CONSOLE("", []).
|
|
|
|
|
|
display_profile_deps(State, Profile) ->
|
|
DepsDir = rebar_prv_install_deps:profile_dep_dir(State, Profile),
|
|
|
|
ProfileDeps = rebar_state:get(State, {deps, Profile}, []),
|
|
% ProfileDeps include those deps from rebar.lock that have been
|
|
% removed from rebar.config
|
|
ConfiguredDeps = [parse_dep_without_locks(DepsDir, Dep, State)
|
|
|| Dep <- ProfileDeps],
|
|
LockedDepsMap = locked_deps_map(State, Profile),
|
|
[display_dep(State, Dep, LockedDepsMap) || Dep <- ConfiguredDeps].
|
|
|
|
|
|
parse_dep_without_locks(DepsDir, Dep, State) ->
|
|
ParsedDep = rebar_app_utils:parse_dep(Dep, root, DepsDir, State, [], 0),
|
|
case Dep of
|
|
{_Name, Src, Level} when is_tuple(Src), is_integer(Level) ->
|
|
% This Dep is not in rebar.config but in rebar.lock
|
|
rebar_app_info:source(ParsedDep, undefined);
|
|
_ ->
|
|
rebar_app_utils:expand_deps_sources(ParsedDep, State)
|
|
end.
|
|
|
|
|
|
locked_deps_map(State, Profile) ->
|
|
ParsedDeps = rebar_state:get(State, {parsed_deps, Profile}, []),
|
|
lists:foldl(fun(Dep, DepsIn) ->
|
|
case rebar_app_info:is_lock(Dep) of
|
|
true ->
|
|
DepName = rebar_app_info:name(Dep),
|
|
maps:put(rebar_utils:to_binary(DepName), Dep, DepsIn);
|
|
_ ->
|
|
DepsIn
|
|
end
|
|
end, maps:new(), ParsedDeps).
|
|
|
|
|
|
display_dep(State, Dep, LockedDeps) ->
|
|
Name = rebar_utils:to_binary(rebar_app_info:name(Dep)),
|
|
NeedsUpdate = rebar_fetch:needs_update(Dep, State),
|
|
Source = rebar_app_info:source(Dep),
|
|
LockedSource = case maps:get(Name, LockedDeps, undefined) of
|
|
undefined -> undefined;
|
|
LockedDep -> rebar_app_info:source(LockedDep)
|
|
end,
|
|
|
|
display_dep_line(Name, NeedsUpdate, source_text(LockedSource), source_text(Source)).
|
|
|
|
|
|
% Dep is a checkout
|
|
display_dep_line(Name, _NeedsUpdate, _LockedSource, Source = checkout) ->
|
|
?CONSOLE("~ts* (~ts)", [Name, Source]);
|
|
|
|
% Dep exists only in lock file
|
|
display_dep_line(Name, _NeedsUpdate, LockedSource, _Source = undefined) ->
|
|
?CONSOLE("~ts* (locked ~ts <> none)", [Name, LockedSource]);
|
|
|
|
% Dep not locked, report whether the disk copy matches the Source
|
|
display_dep_line(Name, true, undefined, Source) ->
|
|
?CONSOLE("~ts* (~ts)", [Name, Source]);
|
|
display_dep_line(Name, _, undefined, Source) ->
|
|
?CONSOLE("~ts (~ts)", [Name, Source]);
|
|
|
|
% Dep locked, install_deps provider should have had updated the disk copy with
|
|
% the locked version
|
|
display_dep_line(Name, false, _LockedSource, Source) ->
|
|
% dep locked and no need to update (LockedSource and Source might not match
|
|
% because of one using {ref, X} and the other {tag, Y})
|
|
?CONSOLE("~ts (locked ~ts)", [Name, Source]);
|
|
display_dep_line(Name, _NeedsUpdate, LockedSource, Source) ->
|
|
% dep locked with mismatching lock and config files
|
|
?CONSOLE("~ts* (locked ~ts <> ~ts)", [Name, LockedSource, Source]).
|
|
|
|
|
|
source_text(Source) when is_list(Source); is_atom(Source) ->
|
|
Source;
|
|
source_text({pkg, _Name, Vsn, _Hash, _RepoConfig}) ->
|
|
source_text({pkg, _Name, Vsn, _Hash});
|
|
source_text({pkg, _Name, Vsn, _Hash}) ->
|
|
[<<"package">>, " ", rebar_utils:to_binary(Vsn)];
|
|
source_text(Source) when is_tuple(Source), tuple_size(Source) < 3 ->
|
|
element(1, Source);
|
|
source_text(Source) when is_tuple(Source) ->
|
|
Type = element(1, Source),
|
|
case element(3, Source) of
|
|
{ref , Ref} ->
|
|
SmallRef = case rebar_utils:to_binary(Ref) of
|
|
<<R:7/binary, _/binary>> -> <<R/binary, "...">>;
|
|
R -> R
|
|
end,
|
|
[atom_to_binary(Type, unicode), " source ", SmallRef];
|
|
{_ , Vsn} ->
|
|
[atom_to_binary(Type, unicode), " source ", rebar_utils:to_binary(Vsn)];
|
|
_ ->
|
|
[atom_to_binary(Type, unicode), " source"]
|
|
end.
|
|
|