Pārlūkot izejas kodu

Merge pull request #610 from tsloughter/deps_tree

add tree option to deps command that prints pkg deps tree
pull/691/head
Fred Hebert pirms 9 gadiem
vecāks
revīzija
1a061b9c9a
6 mainītis faili ar 120 papildinājumiem un 32 dzēšanām
  1. +1
    -6
      src/rebar_app_discover.erl
  2. +23
    -13
      src/rebar_config.erl
  3. +39
    -5
      src/rebar_digraph.erl
  4. +29
    -6
      src/rebar_prv_deps.erl
  5. +2
    -2
      src/rebar_prv_install_deps.erl
  6. +26
    -0
      src/rebar_utils.erl

+ 1
- 6
src/rebar_app_discover.erl Parādīt failu

@ -61,7 +61,7 @@ merge_deps(AppInfo, State) ->
State1 = lists:foldl(fun(Profile, StateAcc) ->
AppProfDeps = rebar_state:get(AppState, {deps, Profile}, []),
TopLevelProfDeps = rebar_state:get(StateAcc, {deps, Profile}, []),
ProfDeps2 = dedup(rebar_utils:tup_umerge(
ProfDeps2 = rebar_utils:tup_dedup(rebar_utils:tup_umerge(
rebar_utils:tup_sort(TopLevelProfDeps)
,rebar_utils:tup_sort(AppProfDeps))),
rebar_state:set(StateAcc, {deps, Profile}, ProfDeps2)
@ -156,11 +156,6 @@ create_app_info(AppDir, AppFile) ->
end,
rebar_app_info:dir(rebar_app_info:valid(AppInfo1, Valid), AppDir).
dedup([]) -> [];
dedup([A]) -> [A];
dedup([H,H|T]) -> dedup([H|T]);
dedup([H|T]) -> [H|dedup(T)].
%% Read in and parse the .app file if it is availabe. Do the same for
%% the .app.src file if it exists.
try_handle_app_file([], AppDir, [], AppSrcScriptFile, Validate) ->

+ 23
- 13
src/rebar_config.erl Parādīt failu

@ -124,27 +124,37 @@ bs(Vars) ->
%% Find deps that have been added to the config after the lock was created
find_newly_added(ConfigDeps, LockedDeps) ->
rebar_utils:filtermap(fun(Dep) when is_tuple(Dep) ->
check_newly_added(element(1, Dep), LockedDeps);
(Dep) ->
check_newly_added(Dep, LockedDeps)
end, ConfigDeps).
check_newly_added(Dep, LockedDeps) when is_atom(Dep) ->
NewDep = ec_cnv:to_binary(Dep),
case lists:keyfind(NewDep, 1, LockedDeps) of
[D || {true, D} <- [check_newly_added(Dep, LockedDeps) || Dep <- ConfigDeps]].
check_newly_added({_, _}=Dep, LockedDeps) ->
check_newly_added_(Dep, LockedDeps);
check_newly_added({Name, _, Source}, LockedDeps) ->
check_newly_added_({Name, Source}, LockedDeps);
check_newly_added(Dep, LockedDeps) ->
check_newly_added_(Dep, LockedDeps).
check_newly_added_({Name, Source}, LockedDeps) ->
case check_newly_added_(Name, LockedDeps) of
{true, Name1} ->
{true, {Name1, Source}};
false ->
true;
false
end;
check_newly_added_(Dep, LockedDeps) when is_atom(Dep) ->
Name = ec_cnv:to_binary(Dep),
case lists:keyfind(Name, 1, LockedDeps) of
false ->
{true, Name};
Match ->
case element(3, Match) of
0 ->
true;
{true, Name};
_ ->
?WARN("Newly added dep ~s is locked at a lower level. "
"If you really want to unlock it, use 'rebar3 upgrade ~s'",
[NewDep, NewDep]),
[Name, Name]),
false
end
end;
check_newly_added(Dep, _) ->
check_newly_added_(Dep, _) ->
throw(?PRV_ERROR({bad_dep_name, Dep})).

+ 39
- 5
src/rebar_digraph.erl Parādīt failu

@ -3,7 +3,9 @@
-export([compile_order/1
,restore_graph/1
,cull_deps/3
,cull_deps/4
,subgraph/2
,print_solution/2
,format_error/1]).
-include("rebar.hrl").
@ -68,7 +70,12 @@ restore_graph({Vs, Es}) ->
%% Pick packages to fullfill dependencies
%% The first dep while traversing the graph is chosen and any conflicting
%% dep encountered later on is ignored.
cull_deps(Graph, Vertices, Level) ->
{ok, LvlVertices, Discarded, _} = cull_deps(Graph, Vertices, Level, none),
{ok, LvlVertices, Discarded}.
cull_deps(Graph, Vertices, Level, SolutionGraph) ->
cull_deps(Graph,
Vertices,
Level+1,
@ -78,13 +85,14 @@ cull_deps(Graph, Vertices, Level) ->
lists:foldl(fun({Key, _}=N, Solution) ->
dict:store(Key, N, Solution)
end, dict:new(), Vertices),
[]).
[],
SolutionGraph).
cull_deps(_Graph, [], _Level, Levels, Solution, Discarded) ->
cull_deps(_Graph, [], _Level, Levels, Solution, Discarded, SolutionGraph) ->
{_, Vertices} = lists:unzip(dict:to_list(Solution)),
LvlVertices = [{App,Vsn,dict:fetch(App,Levels)} || {App,Vsn} <- Vertices],
{ok, LvlVertices, Discarded};
cull_deps(Graph, Vertices, Level, Levels, Solution, Discarded) ->
{ok, LvlVertices, Discarded, SolutionGraph};
cull_deps(Graph, Vertices, Level, Levels, Solution, Discarded, SolutionGraph) ->
{NV, NS, LS, DS} =
lists:foldl(fun(V, {NewVertices, SolutionAcc, LevelsAcc, DiscardedAcc}) ->
OutNeighbors = lists:keysort(1, digraph:out_neighbours(Graph, V)),
@ -95,6 +103,7 @@ cull_deps(Graph, Vertices, Level, Levels, Solution, Discarded) ->
{ok, _} -> % conflict resolution!
{NewVertices1, SolutionAcc1, LevelsAcc1, [N|DiscardedAcc1]};
error ->
add_to_solution_graph(N, V, SolutionGraph),
{[N | NewVertices1],
dict:store(Key, N, SolutionAcc1),
dict:store(Key, Level, LevelsAcc1),
@ -102,11 +111,36 @@ cull_deps(Graph, Vertices, Level, Levels, Solution, Discarded) ->
end
end, {NewVertices, SolutionAcc, LevelsAcc, DiscardedAcc}, OutNeighbors)
end, {[], Solution, Levels, Discarded}, lists:keysort(1, Vertices)),
cull_deps(Graph, NV, Level+1, LS, NS, DS).
cull_deps(Graph, NV, Level+1, LS, NS, DS, SolutionGraph).
subgraph(Graph, Vertices) ->
digraph_utils:subgraph(Graph, Vertices).
add_to_solution_graph(_, _, none) ->
ok;
add_to_solution_graph(N, V, SolutionGraph) ->
NewV = digraph:add_vertex(SolutionGraph, N),
digraph:add_edge(SolutionGraph, V, NewV).
print_solution(Graph, Deps) ->
SolutionGraph = digraph:new(),
[digraph:add_vertex(SolutionGraph, V) || V <- Deps],
cull_deps(Graph, Deps, 0, SolutionGraph),
print_solution(SolutionGraph, Deps, 0).
print_solution(_, [], _) ->
ok;
print_solution(SolutionGraph, [{N, V} | Vertices], 0) ->
?CONSOLE("~s-~s", [N, V]),
OutNeighbors = lists:keysort(1, digraph:out_neighbours(SolutionGraph, {N,V})),
print_solution(SolutionGraph, OutNeighbors, 4),
print_solution(SolutionGraph, Vertices, 0);
print_solution(SolutionGraph, [{N, V} | Vertices], Indent) ->
?CONSOLE("~s~s-~s", [[" " || _ <- lists:seq(0, Indent)], N, V]),
OutNeighbors = lists:keysort(1, digraph:out_neighbours(SolutionGraph, {N,V})),
print_solution(SolutionGraph, OutNeighbors, Indent+4),
print_solution(SolutionGraph, Vertices, Indent).
format_error(no_solution) ->
io_lib:format("No solution for packages found.", []).

+ 29
- 6
src/rebar_prv_deps.erl Parādīt failu

@ -24,16 +24,25 @@ init(State) ->
{short_desc, "List dependencies"},
{desc, "List dependencies. Those not matching lock files "
"are followed by an asterisk (*)."},
{opts, []}])),
{opts, [{tree, $t, "tree", undefined, "Display package dependencies in tree format (git and hg deps not supported)."}]}])),
{ok, State1}.
-spec do(rebar_state:t()) -> {ok, rebar_state:t()} | {error, string()}.
do(State) ->
Profiles = rebar_state:current_profiles(State),
List = [{Profile, rebar_state:get(State, {deps, Profile}, [])}
|| Profile <- Profiles],
[display(State, Profile, Deps) || {Profile, Deps} <- List],
{ok, State}.
case display_tree(State) of
true ->
{_Packages, Graph} = rebar_state:packages(State),
List = merge_deps_per_profile(State),
{_SrcDeps, PkgDeps} = rebar_prv_install_deps:parse_deps("", List, State, [], 0),
rebar_digraph:print_solution(Graph, PkgDeps),
{ok, State};
false ->
Profiles = rebar_state:current_profiles(State),
List = [{Profile, rebar_state:get(State, {deps, Profile}, [])}
|| Profile <- Profiles],
[display(State, Profile, Deps) || {Profile, Deps} <- List],
{ok, State}
end.
-spec format_error(any()) -> iolist().
format_error(Reason) ->
@ -116,3 +125,17 @@ display_dep(State, {Name, Source, Level}) when is_tuple(Source), is_integer(Leve
?CONSOLE("~s~s (locked ~s source)", [Name, NeedsUpdate, type(Source)]).
type(Source) when is_tuple(Source) -> element(1, Source).
display_tree(State) ->
{Args, _} = rebar_state:command_parsed_args(State),
proplists:get_value(tree, Args, false).
merge_deps_per_profile(State) ->
Profiles = rebar_state:current_profiles(State),
lists:foldl(fun(Profile, Deps) ->
D = rebar_utils:deps_to_binary(rebar_state:get(State, {deps, Profile}, [])),
D1 = rebar_utils:tup_sort(D),
rebar_utils:tup_dedup(
rebar_utils:tup_umerge(D1
,Deps))
end, [], Profiles).

+ 2
- 2
src/rebar_prv_install_deps.erl Parādīt failu

@ -36,6 +36,7 @@
-include_lib("providers/include/providers.hrl").
-export([handle_deps_as_profile/4,
parse_deps/5,
find_cycles/1,
cull_compile/2]).
@ -122,7 +123,6 @@ handle_deps_as_profile(Profile, State, Deps, Upgrade) ->
Locks = [],
Level = 0,
DepsDir = profile_dep_dir(State, Profile),
{SrcDeps, PkgDeps} = parse_deps(DepsDir, Deps, State, Locks, Level),
AllSrcProfileDeps = [{Profile, SrcDeps, Locks, Level}],
AllPkgProfileDeps = [{Profile, Locks, PkgDeps, Level}],
@ -511,7 +511,7 @@ parse_dep({Name, Vsn}, {SrcDepsAcc, PkgDepsAcc}, DepsDir, IsLock, State) when is
{SrcDepsAcc, [parse_goal(ec_cnv:to_binary(Name)
,ec_cnv:to_binary(Vsn)) | PkgDepsAcc]}
end;
parse_dep(Name, {SrcDepsAcc, PkgDepsAcc}, DepsDir, IsLock, State) when is_atom(Name) ->
parse_dep(Name, {SrcDepsAcc, PkgDepsAcc}, DepsDir, IsLock, State) when is_atom(Name); is_binary(Name) ->
%% Unversioned package dependency
{PkgName, PkgVsn} = get_package(ec_cnv:to_binary(Name), State),
CheckoutsDir = ec_cnv:to_list(rebar_dir:checkouts_dir(State, Name)),

+ 26
- 0
src/rebar_utils.erl Parādīt failu

@ -54,6 +54,8 @@
expand_env_variable/3,
get_arch/0,
wordsize/0,
deps_to_binary/1,
tup_dedup/1,
tup_umerge/2,
tup_sort/1,
tup_find/2,
@ -236,6 +238,30 @@ erl_opts(Config) ->
%% was enclosed in quotes and might have commas but should not be split.
args_to_tasks(Args) -> new_task(Args, []).
deps_to_binary([]) ->
[];
deps_to_binary([{Name, _, Source} | T]) ->
[{ec_cnv:to_binary(Name), Source} | deps_to_binary(T)];
deps_to_binary([{Name, Source} | T]) ->
[{ec_cnv:to_binary(Name), Source} | deps_to_binary(T)];
deps_to_binary([Name | T]) ->
[ec_cnv:to_binary(Name) | deps_to_binary(T)].
tup_dedup([]) ->
[];
tup_dedup([A]) ->
[A];
tup_dedup([A,B|T]) when element(1, A) =:= element(1, B) ->
tup_dedup([A | T]);
tup_dedup([A,B|T]) when element(1, A) =:= B ->
tup_dedup([A | T]);
tup_dedup([A,B|T]) when A =:= element(1, B) ->
tup_dedup([A | T]);
tup_dedup([A,A|T]) ->
[A|tup_dedup(T)];
tup_dedup([A|T]) ->
[A|tup_dedup(T)].
%% Sort the list in proplist-order, meaning that `{a,b}' and `{a,c}'
%% both compare as usual, and `a' and `b' do the same, but `a' and `{a,b}' will
%% compare based on the first element of the key, and in order. So the following

Notiek ielāde…
Atcelt
Saglabāt