summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTristan Sloughter <t@crashfast.com>2015-08-14 23:14:15 -0500
committerTristan Sloughter <t@crashfast.com>2015-08-15 21:33:52 -0500
commitbe4ae19fecbade303978920701e9e3f8b38d3c54 (patch)
treebdd4e1fbc953aff73b811cee5e4cc1d2790e803f
parente49e59d09a73d4a27e1bd18ee59dd1b9ac6522bb (diff)
track parent app of deps and add tree provider to display the relations
-rw-r--r--README.md1
-rw-r--r--priv/shell-completion/bash/rebar37
-rw-r--r--priv/shell-completion/fish/rebar3.fish6
-rw-r--r--priv/shell-completion/zsh/_rebar36
-rw-r--r--src/rebar.app.src3
-rw-r--r--src/rebar_app_info.erl10
-rw-r--r--src/rebar_digraph.erl85
-rw-r--r--src/rebar_prv_deps.erl37
-rw-r--r--src/rebar_prv_deps_tree.erl79
-rw-r--r--src/rebar_prv_install_deps.erl111
10 files changed, 203 insertions, 142 deletions
diff --git a/README.md b/README.md
index ae93f40..0d24dda 100644
--- a/README.md
+++ b/README.md
@@ -42,6 +42,7 @@ locations ([hex.pm](http://hex.pm), git, hg, and so on).
| report | Report on environment and versions for bug reports |
| shell | Run shell with project apps in path |
| tar | Package release into tarball |
+| tree | Print dependency tree |
| unlock | Unlock dependencies |
| update | Update package index |
| upgrade | Fetch latest version of dep |
diff --git a/priv/shell-completion/bash/rebar3 b/priv/shell-completion/bash/rebar3
index 4e28d3d..40009b7 100644
--- a/priv/shell-completion/bash/rebar3
+++ b/priv/shell-completion/bash/rebar3
@@ -15,6 +15,7 @@ _rebar3()
compile \
cover \
ct \
+ deps \
dialyzer \
do \
edoc \
@@ -29,6 +30,7 @@ _rebar3()
report \
shell \
tar \
+ tree \
unlock \
update \
upgrade \
@@ -77,6 +79,8 @@ _rebar3()
--basic_html \
--ct_hooks \
--verbose"
+ elif [[ ${prev} == deps ]] ; then
+ :
elif [[ ${prev} == dialyzer ]] ; then
sopts="-u -s"
lopts="--update-plt --succ-typings"
@@ -168,6 +172,9 @@ _rebar3()
--system_libs \
--version \
--root"
+ elif [[ ${prev} == tree ]] ; then
+ sopts="-v"
+ lopts="--verbose"
elif [[ ${prev} == update ]] ; then
:
elif [[ ${prev} == upgrade ]] ; then
diff --git a/priv/shell-completion/fish/rebar3.fish b/priv/shell-completion/fish/rebar3.fish
index ad3dad9..df1697e 100644
--- a/priv/shell-completion/fish/rebar3.fish
+++ b/priv/shell-completion/fish/rebar3.fish
@@ -50,6 +50,7 @@ end
## report Provide a crash report to be sent to the rebar3 issues page.
## shell Run shell with project apps and deps in path.
## tar Tar archive of release built of project.
+## tree Print dependency tree.
## unlock Unlock dependencies.
## update Update package index.
## upgrade Upgrade dependencies.
@@ -149,6 +150,10 @@ complete -f -c 'rebar3' -n '__fish_rebar3_using_command tar' -l system_libs
complete -f -c 'rebar3' -n '__fish_rebar3_using_command tar' -l version -d "Print relx version"
complete -f -c 'rebar3' -n '__fish_rebar3_using_command tar' -s r -l root -d "The project root directory"
+complete -f -c 'rebar3' -n '__fish_rebar3_needs_command' -a tree -d "Print depdency tree."
+
+complete -f -c 'rebar3' -n '__fish_rebar3_needs_command tree' -s v -l verbose -d "Print repo and branch/tag/ref for git and hg deps."
+
complete -f -c 'rebar3' -n '__fish_rebar3_needs_command' -a unlock -d "Unlock dependencies."
complete -f -c 'rebar3' -n '__fish_rebar3_needs_command' -a update -d "Update package index."
@@ -158,4 +163,3 @@ complete -f -c 'rebar3' -n '__fish_rebar3_needs_command' -a upgrade -d "Upgrade
complete -f -c 'rebar3' -n '__fish_rebar3_needs_command' -a version -d "Print version for rebar and current Erlang."
complete -f -c 'rebar3' -n '__fish_rebar3_needs_command' -a xref -d "Run cross reference analysis."
-
diff --git a/priv/shell-completion/zsh/_rebar3 b/priv/shell-completion/zsh/_rebar3
index b03b7c9..04575bc 100644
--- a/priv/shell-completion/zsh/_rebar3
+++ b/priv/shell-completion/zsh/_rebar3
@@ -191,6 +191,11 @@ _rebar3 () {
'(-r --root)'{-r,--root}'[The project root directory]:system libs:_files -/' \
&& ret=0
;;
+ (tree)
+ _arguments \
+ '(-v --verbose)'{-v,--verbose}'[Print repo and branch/tag/ref for git and hg deps]' \
+ && ret=0
+ ;;
(unlock)
_arguments \
'*: :_rebar3_list_deps' \
@@ -236,6 +241,7 @@ _rebar3_tasks() {
'report:Provide a crash report to be sent to the rebar3 issues page.'
'shell:Run shell with project apps and deps in path.'
'tar:Tar archive of release built of project.'
+ 'tree:Print dependency tree.'
'unlock:Unlock dependencies.'
'update:Update package index.'
'upgrade:Upgrade dependencies.'
diff --git a/src/rebar.app.src b/src/rebar.app.src
index 0a2e6cf..4ef493b 100644
--- a/src/rebar.app.src
+++ b/src/rebar.app.src
@@ -23,7 +23,7 @@
erlware_commons,
providers,
bbmustache,
- ssl_verify_hostname,
+ ssl_verify_hostname,
relx,
inets]},
{env, [
@@ -41,6 +41,7 @@
rebar_prv_compile,
rebar_prv_cover,
rebar_prv_deps,
+ rebar_prv_deps_tree,
rebar_prv_dialyzer,
rebar_prv_do,
rebar_prv_edoc,
diff --git a/src/rebar_app_info.erl b/src/rebar_app_info.erl
index 6962c5a..7e31f6d 100644
--- a/src/rebar_app_info.erl
+++ b/src/rebar_app_info.erl
@@ -17,6 +17,8 @@
app_file/2,
app_details/1,
app_details/2,
+ parent/1,
+ parent/2,
original_vsn/1,
original_vsn/2,
ebin_dir/1,
@@ -54,6 +56,7 @@
app_file :: file:filename_all() | undefined,
config :: rebar_state:t() | undefined,
original_vsn :: binary() | string() | undefined,
+ parent :: binary() | root,
app_details=[] :: list(),
applications=[] :: list(),
deps=[] :: list(),
@@ -203,6 +206,13 @@ app_details(#app_info_t{app_details=AppDetails}) ->
app_details(AppInfo=#app_info_t{}, AppDetails) ->
AppInfo#app_info_t{app_details=AppDetails}.
+parent(#app_info_t{parent=Parent}) ->
+ Parent.
+
+-spec parent(t(), binary() | root) -> t().
+parent(AppInfo=#app_info_t{}, Parent) ->
+ AppInfo#app_info_t{parent=Parent}.
+
-spec original_vsn(t()) -> string().
original_vsn(#app_info_t{original_vsn=Vsn}) ->
Vsn.
diff --git a/src/rebar_digraph.erl b/src/rebar_digraph.erl
index af51ecc..1132a6c 100644
--- a/src/rebar_digraph.erl
+++ b/src/rebar_digraph.erl
@@ -3,9 +3,7 @@
-export([compile_order/1
,restore_graph/1
,cull_deps/2
- ,cull_deps/3
,subgraph/2
- ,print_solution/2
,format_error/1]).
-include("rebar.hrl").
@@ -71,14 +69,8 @@ restore_graph({Vs, Es}) ->
%% The first dep while traversing the graph is chosen and any conflicting
%% dep encountered later on is ignored.
cull_deps(Graph, Vertices) ->
- {ok, LvlVertices, Discarded, _} = cull_deps(Graph, Vertices, none),
- {ok, LvlVertices, Discarded}.
-
-print_solution(Graph, PkgDeps=[{_, _, Deps} | _]) ->
- SolutionGraph = digraph:new(),
- [digraph:add_vertex(SolutionGraph, V) || V <- Deps],
- cull_deps(Graph, PkgDeps, SolutionGraph),
- print_solution(SolutionGraph, Deps, 0).
+ {Solution, Levels} = build_initial_dicts(Vertices),
+ cull_deps(Graph, Vertices, Levels, Solution, []).
format_error(no_solution) ->
io_lib:format("No solution for packages found.", []).
@@ -87,39 +79,30 @@ format_error(no_solution) ->
%% Internal Functions
%%====================================================================
-cull_deps(Graph, Vertices, SolutionGraph) ->
- {Solution, Levels} = build_initial_dicts(Vertices),
- cull_deps(Graph,
- Vertices,
- Levels,
- Solution,
- [],
- SolutionGraph).
-
-cull_deps(_Graph, [], Levels, Solution, Discarded, SolutionGraph) ->
+cull_deps(_Graph, [], Levels, Solution, Discarded) ->
{_, Vertices} = lists:unzip(dict:to_list(Solution)),
- LvlVertices = [{Profile, {App,Vsn,dict:fetch(App,Levels)}} || {Profile, {App,Vsn}} <- Vertices],
- {ok, LvlVertices, Discarded, SolutionGraph};
-cull_deps(Graph, [{Profile, Level, Vs} | Vertices], Levels, Solution, Discarded, SolutionGraph) ->
+ LvlVertices = [{Profile, {Parent,App,Vsn,dict:fetch(App,Levels)}} || {Profile, {Parent,App,Vsn}} <- Vertices],
+ {ok, LvlVertices, Discarded};
+cull_deps(Graph, [{Profile, Level, Vs} | Vertices], Levels, Solution, Discarded) ->
{NV, NS, LS, DS} =
- lists:foldl(fun(V, {Acc, SolutionAcc, LevelsAcc, DiscardedAcc}) ->
- OutNeighbors = lists:keysort(1, digraph:out_neighbours(Graph, V)),
- handle_neighbors(Profile, Level, V
+ lists:foldl(fun({_, Name, Vsn}, {Acc, SolutionAcc, LevelsAcc, DiscardedAcc}) ->
+ OutNeighbors = lists:keysort(1, digraph:out_neighbours(Graph, {Name,Vsn})),
+ handle_neighbors(Profile, Level, Name
,OutNeighbors, Acc, SolutionAcc
- ,LevelsAcc, DiscardedAcc, SolutionGraph)
+ ,LevelsAcc, DiscardedAcc)
- end, {[], Solution, Levels, Discarded}, lists:keysort(1, Vs)),
+ end, {[], Solution, Levels, Discarded}, lists:keysort(2, Vs)),
- cull_deps(Graph, Vertices++NV, LS, NS, DS, SolutionGraph).
+ cull_deps(Graph, Vertices++NV, LS, NS, DS).
%% For each outgoing edge of a dep check if it should be added to the solution
%% and add it to the list of vertices to do the same for
-handle_neighbors(Profile, Level, Vertex, OutNeighbors, Vertices
- ,Solution, Levels, Discarded, SolutionGraph) ->
- case lists:foldl(fun({Key, _}=N, {NewVertices, Solution1, Levels1, Discarded1}) ->
- maybe_add_to_solution(Profile, Level, Vertex, Key, N
+handle_neighbors(Profile, Level, Parent, OutNeighbors, Vertices
+ ,Solution, Levels, Discarded) ->
+ case lists:foldl(fun({Name, _}=N, {NewVertices, Solution1, Levels1, Discarded1}) ->
+ maybe_add_to_solution(Profile, Level, Name, N, Parent
,NewVertices, Solution1
- ,Levels1, Discarded1, SolutionGraph)
+ ,Levels1, Discarded1)
end, {[], Solution, Levels, Discarded}, OutNeighbors) of
{[], SolutionAcc2, LevelsAcc2, DiscardedAcc2} ->
{Vertices, SolutionAcc2, LevelsAcc2, DiscardedAcc2};
@@ -128,10 +111,10 @@ handle_neighbors(Profile, Level, Vertex, OutNeighbors, Vertices
,SolutionAcc2, LevelsAcc2, DiscardedAcc2}
end.
-maybe_add_to_solution(Profile, Level, Vertex, Key, Value, Vertices
- ,Solution, Levels, Discarded, SolutionGraph) ->
+maybe_add_to_solution(Profile, Level, Key, {Name, Vsn}=Value, Parent
+ ,Vertices ,Solution, Levels, Discarded) ->
case dict:find(Key, Solution) of
- {ok, Value} -> % already seen
+ {ok, {Profile, {Parent, Name, Vsn}}} -> % already seen
{Vertices,
Solution,
Levels,
@@ -142,9 +125,8 @@ maybe_add_to_solution(Profile, Level, Vertex, Key, Value, Vertices
Levels,
[Value|Discarded]};
error ->
- add_to_solution_graph(Value, Vertex, SolutionGraph),
- {[Value | Vertices],
- dict:store(Key, {Profile, Value}, Solution),
+ {[{Parent, Name, Vsn} | Vertices],
+ dict:store(Key, {Profile, {Parent, Name, Vsn}}, Solution),
dict:store(Key, Level+1, Levels),
Discarded}
end.
@@ -164,31 +146,12 @@ maybe_add_to_dict(Key, Value, Dict) ->
%% and the level it is from (for the lock file)
build_initial_dicts(Vertices) ->
lists:foldl(fun({Profile, Level, Vs}, {Solution, Levels}) ->
- lists:foldl(fun({Key, Vsn}, {SAcc, LAcc}) ->
- {maybe_add_to_dict(Key, {Profile, {Key,Vsn}}, SAcc),
+ lists:foldl(fun({Parent, Key, Vsn}, {SAcc, LAcc}) ->
+ {maybe_add_to_dict(Key, {Profile, {Parent,Key,Vsn}}, SAcc),
maybe_add_to_dict(Key, Level, LAcc)}
end, {Solution, Levels}, Vs)
end, {dict:new(), dict:new()}, 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(_, [], _) ->
- 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).
-
-spec names_to_apps([atom()], [rebar_app_info:t()]) -> [rebar_app_info:t()].
names_to_apps(Names, Apps) ->
[element(2, App) || App <- [find_app_by_name(Name, Apps) || Name <- Names], App =/= error].
diff --git a/src/rebar_prv_deps.erl b/src/rebar_prv_deps.erl
index 112b60b..9ff2bfa 100644
--- a/src/rebar_prv_deps.erl
+++ b/src/rebar_prv_deps.erl
@@ -24,26 +24,16 @@ init(State) ->
{short_desc, "List dependencies"},
{desc, "List dependencies. Those not matching lock files "
"are followed by an asterisk (*)."},
- {opts, [{tree, $t, "tree", undefined, "Display package dependencies in tree format (git and hg deps not supported)."}]}])),
+ {opts, []}])),
{ok, State1}.
-spec do(rebar_state:t()) -> {ok, rebar_state:t()} | {error, string()}.
do(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),
- PkgDeps1 = [{default, 0, PkgDeps}],
- rebar_digraph:print_solution(Graph, PkgDeps1),
- {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.
+ 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}.
-spec format_error(any()) -> iolist().
format_error(Reason) ->
@@ -92,7 +82,6 @@ dedup([Dep|Deps], [Name|DepNames]) ->
name(T) when is_tuple(T) -> element(1, T);
name(B) when is_binary(B) -> B.
-
display_deps(State, Deps) ->
lists:foreach(fun(Dep) -> display_dep(State, Dep) end, Deps).
@@ -126,17 +115,3 @@ 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).
diff --git a/src/rebar_prv_deps_tree.erl b/src/rebar_prv_deps_tree.erl
new file mode 100644
index 0000000..6c69aba
--- /dev/null
+++ b/src/rebar_prv_deps_tree.erl
@@ -0,0 +1,79 @@
+-module(rebar_prv_deps_tree).
+
+-behaviour(provider).
+
+-export([init/1,
+ do/1,
+ format_error/1]).
+
+-include("rebar.hrl").
+
+-define(PROVIDER, tree).
+-define(DEPS, [lock]).
+
+-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 tree"},
+ {short_desc, "Print dependency tree."},
+ {desc, ""},
+ {opts, [{verbose, $v, "verbose", undefined, "Print repo and branch/tag/ref for git and hg deps"}]}])),
+ {ok, State1}.
+
+-spec do(rebar_state:t()) -> {ok, rebar_state:t()} | {error, string()}.
+do(State) ->
+ {Args, _} = rebar_state:command_parsed_args(State),
+ Verbose = proplists:get_value(verbose, Args, false),
+ print_deps_tree(rebar_state:all_deps(State), Verbose),
+ {ok, State}.
+
+-spec format_error(any()) -> iolist().
+format_error(Reason) ->
+ io_lib:format("~p", [Reason]).
+
+%% Internal functions
+
+print_deps_tree(SrcDeps, Verbose) ->
+ D = lists:foldl(fun(App, Dict) ->
+ Name = rebar_app_info:name(App),
+ Vsn = rebar_app_info:original_vsn(App),
+ Source = rebar_app_info:source(App),
+ Parent = rebar_app_info:parent(App),
+ dict:append_list(Parent, [{Name, Vsn, Source}], Dict)
+ end, dict:new(), SrcDeps),
+ case dict:find(root, D) of
+ {ok, Children} ->
+ print_children(-1, lists:keysort(1, Children), D, Verbose);
+ error ->
+ none
+ end.
+
+print_children(_, [], _, _) ->
+ ok;
+print_children(Indent, [{Name, Vsn, Source} | Rest], Dict, Verbose) ->
+
+ [io:format("| ") || _ <- lists:seq(0, Indent, 2)],
+ io:format("|- "),
+ io:format("~s-~s (~s)~n", [Name, Vsn, type(Source, Verbose)]),
+ case dict:find(Name, Dict) of
+ {ok, Children} ->
+ print_children(Indent+2, lists:keysort(1, Children), Dict, Verbose),
+ print_children(Indent, Rest, Dict, Verbose);
+ error ->
+ print_children(Indent, Rest, Dict, Verbose)
+ end.
+
+type(Source, Verbose) when is_tuple(Source) ->
+ case {element(1, Source), Verbose} of
+ {pkg, _} ->
+ "hex package";
+ {Other, false} ->
+ io_lib:format("~s repo", [Other]);
+ {_, true} ->
+ io_lib:format("~s", [element(2, Source)])
+ end.
diff --git a/src/rebar_prv_install_deps.erl b/src/rebar_prv_install_deps.erl
index be65032..e521b25 100644
--- a/src/rebar_prv_install_deps.erl
+++ b/src/rebar_prv_install_deps.erl
@@ -179,7 +179,7 @@ handle_profile_level([{Profile, SrcDeps, Locks, Level} | Rest], PkgDeps, SrcApps
PkgDeps;
_ ->
[{Profile, Level+1, PkgDeps1} | PkgDeps]
- end, SrcApps1++SrcApps, sets:union(Seen, Seen1), Upgrade, State1).
+ end, SrcApps1, sets:union(Seen, Seen1), Upgrade, State1).
handle_profile_pkg_level([], AllApps, _Seen, _Upgrade, _Locks, State) ->
{AllApps, State};
@@ -213,9 +213,9 @@ find_cycles(Apps) ->
cull_compile(TopSortedDeps, ProjectApps) ->
lists:dropwhile(fun not_needs_compile/1, TopSortedDeps -- ProjectApps).
-pkg_locked({Name, _, _}, Locks) ->
+pkg_locked({_, Name, _, _}, Locks) ->
pkg_locked(Name, Locks);
-pkg_locked({Name, _}, Locks) ->
+pkg_locked({_, Name, _}, Locks) ->
pkg_locked(Name, Locks);
pkg_locked(Name, Locks) ->
false =/= lists:keyfind(Name, 1, Locks).
@@ -231,14 +231,19 @@ update_pkg_deps(Pkgs, Packages, Upgrade, Seen, State, Locks) ->
handle_pkg_dep(Profile, Pkg, Packages, Upgrade, DepsDir, Fetched, Seen, Locks, State) ->
IsLock = pkg_locked(Pkg, Locks),
AppInfo = package_to_app(DepsDir, Packages, Pkg, IsLock, State),
- Deps = rebar_app_info:deps(AppInfo),
- Level = rebar_app_info:dep_level(AppInfo),
- {NewSeen, NewState} = maybe_lock(Profile, AppInfo, Seen, State, Level),
- {_, AppInfo1} = maybe_fetch(AppInfo, Profile, Upgrade, Seen, NewState),
- {AppInfo2, _, _, _, _} =
- handle_dep(NewState, Profile, DepsDir, AppInfo1, Locks, Level),
- AppInfo3 = rebar_app_info:deps(AppInfo2, Deps),
- {[AppInfo3 | Fetched], NewSeen, NewState}.
+ case sets:is_element(rebar_app_info:name(AppInfo), Seen) of
+ true ->
+ {Fetched, Seen, State};
+ false ->
+ Deps = rebar_app_info:deps(AppInfo),
+ Level = rebar_app_info:dep_level(AppInfo),
+ {NewSeen, NewState} = maybe_lock(Profile, AppInfo, Seen, State, Level),
+ {_, AppInfo1} = maybe_fetch(AppInfo, Profile, Upgrade, Seen, NewState),
+ {AppInfo2, _, _, _, _} =
+ handle_dep(NewState, Profile, DepsDir, AppInfo1, Locks, Level),
+ AppInfo3 = rebar_app_info:deps(AppInfo2, Deps),
+ {[AppInfo3 | Fetched], NewSeen, NewState}
+ end.
maybe_lock(Profile, AppInfo, Seen, State, Level) ->
Name = rebar_app_info:name(AppInfo),
@@ -266,7 +271,7 @@ maybe_lock(Profile, AppInfo, Seen, State, Level) ->
{sets:add_element(Name, Seen), State}
end.
-package_to_app(DepsDir, Packages, {Name, Vsn, Level}, IsLock, State) ->
+package_to_app(DepsDir, Packages, {Parent, Name, Vsn, Level}, IsLock, State) ->
case dict:find({Name, Vsn}, Packages) of
error ->
case rebar_packages:check_registry(Name, Vsn, State) of
@@ -277,11 +282,11 @@ package_to_app(DepsDir, Packages, {Name, Vsn, Level}, IsLock, State) ->
end;
{ok, PkgDeps} ->
Source = {pkg, Name, Vsn},
- AppInfo = new_dep(DepsDir, Name, Vsn, Source, IsLock, State),
+ AppInfo = new_dep(root, DepsDir, Name, Vsn, Source, IsLock, State),
AppInfo1 = rebar_app_info:dep_level(rebar_app_info:deps(AppInfo, PkgDeps), Level),
BaseDir = rebar_state:get(State, base_dir, []),
AppState1 = rebar_state:set(rebar_app_info:state(AppInfo1), base_dir, BaseDir),
- rebar_app_info:state(AppInfo1, AppState1)
+ rebar_app_info:parent(rebar_app_info:state(AppInfo1, AppState1), Parent)
end.
-spec update_src_deps(atom(), non_neg_integer(), list(), list(), list(), rebar_state:t(), boolean(), sets:set(binary()), list()) -> {list(), list(), list(), rebar_state:t(), sets:set(binary()), list()}.
@@ -394,7 +399,7 @@ handle_dep(State, Profile, DepsDir, AppInfo, Locks, Level) ->
NewLocks = [{DepName, Source, LockLevel+Level} ||
{DepName, Source, LockLevel} <- rebar_state:get(S5, {locks, default}, [])],
AppInfo3 = rebar_app_info:deps(AppInfo2, rebar_state:deps_names(Deps)),
- {SrcDeps, PkgDeps} = parse_deps(DepsDir, Deps, S5, Locks, Level+1),
+ {SrcDeps, PkgDeps} = parse_deps(rebar_app_info:name(AppInfo3), DepsDir, Deps, S5, Locks, Level+1),
{AppInfo3, SrcDeps, PkgDeps, Locks++NewLocks, State}.
-spec maybe_fetch(rebar_app_info:t(), atom(), boolean(),
@@ -414,13 +419,16 @@ maybe_fetch(AppInfo, Profile, Upgrade, Seen, State) ->
{true, AppInfo1} ->
%% Preserve the state we created with overrides
AppState = rebar_app_info:state(AppInfo),
- AppInfo2 = rebar_app_info:state(AppInfo1, AppState),
+ Parent = rebar_app_info:parent(AppInfo),
+ Source = rebar_app_info:source(AppInfo),
+ AppInfo2 = rebar_app_info:parent(rebar_app_info:state(AppInfo1, AppState), Parent),
+ AppInfo3 = rebar_app_info:source(AppInfo2, Source),
case sets:is_element(rebar_app_info:name(AppInfo), Seen) of
true ->
- {false, AppInfo2};
+ {false, AppInfo3};
false ->
- maybe_symlink_default(State, Profile, AppDir, AppInfo2),
- {maybe_upgrade(AppInfo, AppDir, Upgrade, State), AppInfo2}
+ maybe_symlink_default(State, Profile, AppDir, AppInfo3),
+ {maybe_upgrade(AppInfo, AppDir, Upgrade, State), AppInfo3}
end
end
end.
@@ -470,6 +478,9 @@ make_relative_to_root(State, Path) when is_list(Path) ->
-spec parse_deps(binary(), list(), rebar_state:t(), list(), integer()) -> {[rebar_app_info:t()], [tuple()]}.
parse_deps(DepsDir, Deps, State, Locks, Level) ->
+ parse_deps(root, DepsDir, Deps, State, Locks, Level).
+
+parse_deps(Parent, DepsDir, Deps, State, Locks, Level) ->
lists:foldl(fun(Dep, Acc) ->
Name = case Dep of
Dep when is_tuple(Dep) ->
@@ -479,68 +490,69 @@ parse_deps(DepsDir, Deps, State, Locks, Level) ->
end,
case lists:keyfind(ec_cnv:to_binary(Name), 1, Locks) of
false ->
- parse_dep(Dep, Acc, DepsDir, false, State);
+ parse_dep(Parent, Dep, Acc, DepsDir, false, State);
LockedDep ->
LockedLevel = element(3, LockedDep),
case LockedLevel > Level of
true ->
- parse_dep(Dep, Acc, DepsDir, false, State);
+ parse_dep(Parent, Dep, Acc, DepsDir, false, State);
false ->
- parse_dep(LockedDep, Acc, DepsDir, true, State)
+ parse_dep(Parent, LockedDep, Acc, DepsDir, true, State)
end
end
end, {[], []}, Deps).
-parse_dep({Name, Vsn}, {SrcDepsAcc, PkgDepsAcc}, DepsDir, IsLock, State) when is_list(Vsn) ->
+parse_dep(Parent, {Name, Vsn}, {SrcDepsAcc, PkgDepsAcc}, DepsDir, IsLock, State) when is_list(Vsn) ->
%% Versioned Package dependency
CheckoutsDir = ec_cnv:to_list(rebar_dir:checkouts_dir(State, Name)),
case rebar_app_info:discover(CheckoutsDir) of
{ok, _App} ->
- Dep = new_dep(DepsDir, Name, [], [], IsLock, State),
+ Dep = new_dep(root, DepsDir, Name, [], [], IsLock, State),
{[Dep | SrcDepsAcc], PkgDepsAcc};
not_found ->
- {SrcDepsAcc, [parse_goal(ec_cnv:to_binary(Name)
+ {SrcDepsAcc, [parse_goal(Parent
+ ,ec_cnv:to_binary(Name)
,ec_cnv:to_binary(Vsn)) | PkgDepsAcc]}
end;
-parse_dep(Name, {SrcDepsAcc, PkgDepsAcc}, DepsDir, IsLock, State) when is_atom(Name); is_binary(Name) ->
+parse_dep(Parent, 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)),
case rebar_app_info:discover(CheckoutsDir) of
{ok, _App} ->
- Dep = new_dep(DepsDir, Name, [], [], IsLock, State),
+ Dep = new_dep(root, DepsDir, Name, [], [], IsLock, State),
{[Dep | SrcDepsAcc], PkgDepsAcc};
not_found ->
- {SrcDepsAcc, [{PkgName, PkgVsn} | PkgDepsAcc]}
+ {SrcDepsAcc, [{Parent, PkgName, PkgVsn} | PkgDepsAcc]}
end;
-parse_dep({Name, Source}, {SrcDepsAcc, PkgDepsAcc}, DepsDir, IsLock, State) when is_tuple(Source) ->
- Dep = new_dep(DepsDir, Name, [], Source, IsLock, State),
+parse_dep(Parent, {Name, Source}, {SrcDepsAcc, PkgDepsAcc}, DepsDir, IsLock, State) when is_tuple(Source) ->
+ Dep = new_dep(Parent, DepsDir, Name, [], Source, IsLock, State),
{[Dep | SrcDepsAcc], PkgDepsAcc};
-parse_dep({Name, _Vsn, Source}, {SrcDepsAcc, PkgDepsAcc}, DepsDir, IsLock, State) when is_tuple(Source) ->
- Dep = new_dep(DepsDir, Name, [], Source, IsLock, State),
+parse_dep(Parent, {Name, _Vsn, Source}, {SrcDepsAcc, PkgDepsAcc}, DepsDir, IsLock, State) when is_tuple(Source) ->
+ Dep = new_dep(Parent, DepsDir, Name, [], Source, IsLock, State),
{[Dep | SrcDepsAcc], PkgDepsAcc};
-parse_dep({Name, _Vsn, Source, Opts}, {SrcDepsAcc, PkgDepsAcc}, DepsDir, IsLock, State) when is_tuple(Source) ->
+parse_dep(Parent, {Name, _Vsn, Source, Opts}, {SrcDepsAcc, PkgDepsAcc}, DepsDir, IsLock, State) when is_tuple(Source) ->
?WARN("Dependency option list ~p in ~p is not supported and will be ignored", [Opts, Name]),
- Dep = new_dep(DepsDir, Name, [], Source, IsLock, State),
+ Dep = new_dep(Parent, DepsDir, Name, [], Source, IsLock, State),
{[Dep | SrcDepsAcc], PkgDepsAcc};
-parse_dep({_Name, {pkg, Name, Vsn}, Level}, {SrcDepsAcc, PkgDepsAcc}, DepsDir, IsLock, State) when is_integer(Level) ->
+parse_dep(Parent, {_Name, {pkg, Name, Vsn}, Level}, {SrcDepsAcc, PkgDepsAcc}, DepsDir, IsLock, State) when is_integer(Level) ->
CheckoutsDir = ec_cnv:to_list(rebar_dir:checkouts_dir(State, Name)),
case rebar_app_info:discover(CheckoutsDir) of
{ok, _App} ->
- Dep = new_dep(DepsDir, Name, [], [], IsLock, State),
+ Dep = new_dep(root, DepsDir, Name, [], [], IsLock, State),
{[Dep | SrcDepsAcc], PkgDepsAcc};
not_found ->
- {SrcDepsAcc, [{Name, Vsn} | PkgDepsAcc]}
+ {SrcDepsAcc, [{Parent, Name, Vsn} | PkgDepsAcc]}
end;
-parse_dep({Name, Source, Level}, {SrcDepsAcc, PkgDepsAcc}, DepsDir, IsLock, State) when is_tuple(Source)
- , is_integer(Level) ->
- Dep = new_dep(DepsDir, Name, [], Source, IsLock, State),
+parse_dep(Parent, {Name, Source, Level}, {SrcDepsAcc, PkgDepsAcc}, DepsDir, IsLock, State) when is_tuple(Source)
+ , is_integer(Level) ->
+ Dep = new_dep(Parent, DepsDir, Name, [], Source, IsLock, State),
{[Dep | SrcDepsAcc], PkgDepsAcc};
-parse_dep(Dep, _, _, _, _) ->
+parse_dep(_, Dep, _, _, _, _) ->
throw(?PRV_ERROR({parse_dep, Dep})).
-new_dep(DepsDir, Name, Vsn, Source, IsLock, State) ->
+new_dep(Parent, DepsDir, Name, Vsn, Source, IsLock, State) ->
CheckoutsDir = ec_cnv:to_list(rebar_dir:checkouts_dir(State, Name)),
{ok, Dep} = case rebar_app_info:discover(CheckoutsDir) of
{ok, App} ->
@@ -561,7 +573,8 @@ new_dep(DepsDir, Name, Vsn, Source, IsLock, State) ->
ParentOverrides = rebar_state:overrides(State),
Dep1 = rebar_app_info:state(Dep,
rebar_state:overrides(S, ParentOverrides++Overrides)),
- rebar_app_info:is_lock(rebar_app_info:source(Dep1, Source), IsLock).
+ AppInfo = rebar_app_info:is_lock(rebar_app_info:source(Dep1, Source), IsLock),
+ rebar_app_info:parent(AppInfo, Parent).
fetch_app(AppInfo, AppDir, State) ->
?INFO("Fetching ~s (~p)", [rebar_app_info:name(AppInfo), rebar_app_info:source(AppInfo)]),
@@ -573,13 +586,15 @@ fetch_app(AppInfo, AppDir, State) ->
%% be read in an parsed.
update_app_info(AppDir, AppInfo) ->
{ok, Found} = rebar_app_info:discover(AppDir),
+ Parent = rebar_app_info:parent(AppInfo),
+ Source = rebar_app_info:source(AppInfo),
AppDetails = rebar_app_info:app_details(Found),
Applications = proplists:get_value(applications, AppDetails, []),
IncludedApplications = proplists:get_value(included_applications, AppDetails, []),
AppInfo1 = rebar_app_info:applications(
rebar_app_info:app_details(AppInfo, AppDetails),
IncludedApplications++Applications),
- rebar_app_info:valid(AppInfo1, false).
+ rebar_app_info:source(rebar_app_info:parent(rebar_app_info:valid(AppInfo1, false), Parent), Source).
maybe_upgrade(AppInfo, AppDir, Upgrade, State) ->
Source = rebar_app_info:source(AppInfo),
@@ -602,13 +617,13 @@ maybe_upgrade(AppInfo, AppDir, Upgrade, State) ->
false
end.
--spec parse_goal(binary(), binary()) -> {binary(), binary()} | {binary(), binary(), binary()}.
-parse_goal(Name, Constraint) ->
+-spec parse_goal(binary() | root, binary(), binary()) -> {binary(), binary()} | {binary(), binary(), binary()}.
+parse_goal(Parent, Name, Constraint) ->
case re:run(Constraint, "([^\\d]*)(\\d.*)", [{capture, [1,2], binary}]) of
{match, [<<>>, Vsn]} ->
- {Name, Vsn};
+ {Parent, Name, Vsn};
{match, [Op, Vsn]} ->
- {Name, Vsn, binary_to_atom(Op, utf8)};
+ {Parent, Name, Vsn, binary_to_atom(Op, utf8)};
nomatch ->
throw(?PRV_ERROR({bad_constraint, Name, Constraint}))
end.