2016-09-01 107 views
1

我想解析應用程序樹並生成一張地圖。
我目前正在讀的頂級DEPS,如:什麼是讀取依賴關係樹的正確方法?

top_level_deps = Mix.Dep.loaded([]) |> Enum.filter(& &1.top_level) 

我用Enum.reduce遞歸方法top_level_deps,然後dep.deps
一切都很好,直到第四級,沒有縮影...
例如:
應用程序A需要B,需要C,需要D - 在檢查C代碼時看到空列表(此處也不包含十六進制包)。
當我修改應用程序A或B以要求D和C不需要D時,我會在我的地圖中看到所有的縮放。
什麼是讀取依賴關係樹的正確方法?

重現步驟:
1創建的應用程序一個TMP DIR
2轉到TMP的目錄,並創建4個應用程序,如:

mix new a 
mix new b 
mix new c 
mix new d 

3添加DEPS一個,b和c的應用,如:

defp deps do 
    [{:b, path: "../b"}] # deps for A app 
end 

4添加此任務的lib /混合/任務/一個項目:

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運行組合重現
目前的結果:

%{a: "a", b: "a_b", c: "a_b_c"} 

預期結果:

%{a: "a", b: "a_b", c: "a_b_c", d: "a_b_c_d"} 
+0

不確定爲什麼返回的列表不包括嵌套依賴關係,但我嘗試了一種不同的方法來獲得預期的結果,並且有一個問題:如果'b'也依賴於'd'(如果依賴關係是'a - > b','b - > c','b - > d'和'c - > d')。 – Dogbert

+0

@Dogbert:我將捕獲一個碰撞並執行其中一個操作:第一個結果,最後一個結果(覆蓋前一個)或後備,如:「a_multi_d」 - 取決於配置。 – Eiji

+0

我需要添加一個免責聲明,Mix.Dep是**不是公共API **。你不應該叫它,並且在將來的Elixir版本中不能保證這個模塊或功能將會存在。 :) –

回答

1

我不知道爲什麼Mix.Dep.loaded([])不含有一定水平之後嵌套deps ,但由於所有遞歸依賴項都是直接出現在該列表中,我們可以構建自己的查找映射並使用它。下面是返回你的預期輸出的實現:

defmodule Mix.Tasks.Deps.Map do 
    use Mix.Task 

    def run(_) do 
    app = Mix.Project.config[:app] 
    deps = for %{app: app, deps: deps} <- Mix.Dep.loaded([]), into: %{} do 
     {app, deps} 
    end |> Map.put(app, Enum.filter(Mix.Dep.loaded([]), &(&1.top_level))) 
    recur(deps, app, "") |> Map.put(app, "#{app}") |> IO.inspect 
    end 

    def recur(deps, app, prefix, result \\ Map.new) do 
    Enum.reduce(deps[app], result, fn(dep, result) -> 
     if dep.scm != Hex.SCM do 
     recur(deps, dep.app, "#{prefix}#{app}_", result) 
     |> Map.put_new(dep.app, "#{prefix}#{app}_#{dep.app}") 
     else 
     result 
     end 
    end) 
    end 
end 

有4個包,abc,並d輸出:

%{a: "a", b: "a_b", c: "a_b_c", d: "a_b_c_d"} 

輸出與上面加一個新包ed取決於:

%{a: "a", b: "a_b", c: "a_b_c", d: "a_b_c_d", e: "a_b_c_d_e"} 
+0

要完全完成此主題,我想知道爲什麼我的代碼無法按預期工作。無論如何,謝謝你的幫助。現在它運作得非常好。 – Eiji

相關問題