@@ -50,7 +50,8 @@ defmodule Mix.Deps.Converger do
5050 config = [ deps_path: Path . expand ( Mix . project [ :deps_path ] ) ,
5151 root_lockfile: Path . expand ( Mix . project [ :lockfile ] ) ]
5252 main = Mix.Deps.Retriever . children
53- all ( main , [ ] , [ ] , main , config , callback , rest )
53+ apps = Enum . map ( main , & ( & 1 . app ) )
54+ all ( main , [ ] , [ ] , apps , config , callback , rest )
5455 end
5556
5657 # We traverse the tree of dependencies in a breadth-
@@ -105,8 +106,11 @@ defmodule Mix.Deps.Converger do
105106 # dependency), we fetch the dependency including its latest info
106107 # and children information.
107108 { dep , children } = Mix.Deps.Retriever . fetch ( dep , config )
109+ children = reject_non_fullfilled_optional ( children , current_breadths )
110+ dep = dep . deps ( Enum . map ( children , & ( & 1 . app ) ) )
111+
108112 { acc , rest } = all ( t , [ dep | acc ] , upper_breadths , current_breadths , config , callback , rest )
109- all ( children , acc , current_breadths , children ++ current_breadths , config , callback , rest )
113+ all ( children , acc , current_breadths , dep . deps ++ current_breadths , config , callback , rest )
110114 end
111115 end
112116
@@ -120,11 +124,7 @@ defmodule Mix.Deps.Converger do
120124 # overrider is moved to the front of the accumulator to
121125 # preserve the position of the removed dep.
122126 defp overriden_deps ( acc , upper_breadths , dep ) do
123- overriden = Enum . any? ( upper_breadths , fn ( other ) ->
124- other . app == dep . app
125- end )
126-
127- if overriden do
127+ if dep . app in upper_breadths do
128128 Mix.Dep [ app : app ] = dep
129129
130130 { overrider , acc } =
@@ -169,13 +169,23 @@ defmodule Mix.Deps.Converger do
169169 if match , do: acc
170170 end
171171
172+ defp converge? ( _ , Mix.Dep [ scm : Mix . SCM.Optional ] ) do
173+ true
174+ end
175+
172176 defp converge? ( Mix.Dep [ scm : scm , opts: opts1 ] , Mix.Dep [ scm : scm , opts: opts2 ] ) do
173177 scm . equal? ( opts1 , opts2 )
174178 end
175179
176180 defp converge? ( _ , _ ) , do: false
177181
178- def with_matching_req ( Mix.Dep [ ] = other , Mix.Dep [ ] = dep ) do
182+ defp reject_non_fullfilled_optional ( children , upper_breadths ) do
183+ Enum . reject children , fn Mix.Dep [ app : app , opts: opts ] ->
184+ opts [ :optional ] && not ( app in upper_breadths )
185+ end
186+ end
187+
188+ defp with_matching_req ( Mix.Dep [ ] = other , Mix.Dep [ ] = dep ) do
179189 case other . status do
180190 { :ok , vsn } when not nil? ( vsn ) ->
181191 if Mix.Deps.Retriever . vsn_match? ( dep . requirement , vsn ) do
0 commit comments