I want to parse app deps tree and generate a map.
I'm currently reading top-level deps like:
top_level_deps = Mix.Dep.loaded([]) |> Enum.filter(& &1.top_level)
I use Enum.reduce in recursive method for top_level_deps and then for dep.deps.
Everything is good until 4th level where is no deps ...
For example:
App A require B that requires C that requires D - I see empty list when inspect C deps (also no hex packages here).
When I modify app A or B to require D and C not require D then I see all deps in my map.
What is the correct way to read dependency tree?
Steps to reproduce:
1 Create a tmp dir for apps
2 Go to tmp dir and create 4 apps like:
mix new a
mix new b
mix new c
mix new d
3 Add deps for a, b and c apps like:
defp deps do
[{:b, path: "../b"}] # deps for A app
end
4 Add this task to lib/mix/tasks/ to A project:
defmodule Mix.Tasks.Reproduce do
use Mix.Task
def run(_) do
app_atom = Mix.Project.config[:app]
top_level_deps = Mix.Dep.loaded([]) |> Enum.filter(& &1.top_level)
result = reproduce top_level_deps, app_atom
IO.inspect Map.put_new result, app_atom, Atom.to_string(app_atom)
end
defp reproduce deps, prefix, result \\ Map.new do
Enum.reduce deps, result, fn(dep, result) ->
if dep.scm != Hex.SCM do # filter Hex packages here
new_prefix = "#{prefix}_#{dep.app}"
new_result = reproduce dep.deps, new_prefix, result
if dep.app == :c do
IO.puts "No deps here !!!"
IO.inspect dep.deps
end
Map.put_new new_result, dep.app, new_prefix
else
result
end
end
end
end
5 Run mix reproduce
Current results:
%{a: "a", b: "a_b", c: "a_b_c"}
Expected results:
%{a: "a", b: "a_b", c: "a_b_c", d: "a_b_c_d"}
b
also depends ond
(if the dependencies area -> b
,b -> c
,b -> d
, andc -> d
). – Dogbert