Skip to content

Commit d2bfd10

Browse files
author
José Valim
committed
Merge pull request #1715 from ericmj/mix-deps-order
Preserve correct order when deps are overriding
2 parents 429fc20 + b2e32e4 commit d2bfd10

File tree

6 files changed

+59
-24
lines changed

6 files changed

+59
-24
lines changed

lib/mix/lib/mix/deps.ex

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -105,22 +105,25 @@ defmodule Mix.Deps do
105105
defdelegate children(), to: Mix.Deps.Retriever
106106
107107
@doc """
108-
Return all dependencies depending on the given dependencies.
108+
Return all given dependencies and their depending dependencies.
109109
"""
110-
def depending(deps, all_deps // all)
110+
def with_depending(deps, all_deps // all) do
111+
deps ++ do_with_depending(deps, all_deps)
112+
|> Enum.uniq(&(&1.app))
113+
end
111114
112-
def depending([], _all_deps) do
115+
defp do_with_depending([], _all_deps) do
113116
[]
114117
end
115118
116-
def depending(deps, all_deps) do
119+
defp do_with_depending(deps, all_deps) do
117120
dep_names = Enum.map(deps, fn dep -> dep.app end)
118121
119122
parents = Enum.filter all_deps, fn dep ->
120123
Enum.any?(dep.deps, fn child_dep -> child_dep.app in dep_names end)
121124
end
122125
123-
parents ++ depending(parents, all_deps)
126+
do_with_depending(parents, all_deps) ++ parents
124127
end
125128
126129
@doc """

lib/mix/lib/mix/deps/converger.ex

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,9 @@ defmodule Mix.Deps.Converger do
8383

8484
# Look for an overriding dep in the upper breadths, if
8585
# found return a new acc without the overriden dep and
86-
# with the proper status set on the overrider
86+
# with the proper status set on the overrider. The
87+
# overrider is moved to the front of the accumulator to
88+
# preserve the position of the removed dep.
8789
defp overriden_deps(acc, upper_breadths, dep) do
8890
overriden = Enum.any?(upper_breadths, fn(other) ->
8991
other.app == dep.app
@@ -92,18 +94,21 @@ defmodule Mix.Deps.Converger do
9294
if overriden do
9395
Mix.Dep[app: app] = dep
9496

95-
Enum.map(acc, fn other ->
96-
Mix.Dep[app: other_app, opts: other_opts] = other
97+
{ overrider, acc } =
98+
Enum.reduce(acc, { nil , [] }, fn other, { overrider, acc } ->
99+
Mix.Dep[app: other_app, opts: other_opts] = other
97100

98-
cond do
99-
app == other_app && (other_opts[:override] || converge?(dep, other)) ->
100-
other
101-
app == other_app ->
102-
other.status({ :overriden, dep })
103-
true ->
104-
other
105-
end
106-
end)
101+
cond do
102+
app == other_app && (other_opts[:override] || converge?(dep, other)) ->
103+
{ other, acc }
104+
app == other_app ->
105+
{ other.status({ :overriden, dep }), acc }
106+
true ->
107+
{ overrider, [other|acc] }
108+
end
109+
end)
110+
111+
[ overrider | Enum.reverse(acc) ]
107112
end
108113
end
109114

lib/mix/lib/mix/tasks/deps.compile.ex

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@ defmodule Mix.Tasks.Deps.Compile do
2929
"""
3030

3131
import Mix.Deps, only: [ all: 0, available?: 1, by_name: 2, compile_paths: 1,
32-
depending: 2, format_dep: 1, make?: 1, mix?: 1, rebar?: 1 ]
32+
with_depending: 2, format_dep: 1, make?: 1, mix?: 1,
33+
rebar?: 1 ]
3334

3435
def run(args) do
3536
Mix.Project.get! # Require the project to be available
@@ -39,8 +40,8 @@ defmodule Mix.Tasks.Deps.Compile do
3940
do_run(Enum.filter(all, &available?/1), opts)
4041
{ opts, tail, _ } ->
4142
all_deps = all
42-
deps = by_name(tail, all_deps)
43-
do_run(deps ++ depending(deps, all_deps), opts)
43+
deps = by_name(tail, all_deps) |> with_depending(all_deps)
44+
do_run(deps, opts)
4445
end
4546
end
4647

lib/mix/lib/mix/tasks/deps.update.ex

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ defmodule Mix.Tasks.Deps.Update do
2222
"""
2323

2424
import Mix.Deps, only: [ all: 0, all: 2, available?: 1, by_name: 2,
25-
depending: 2, format_dep: 1 ]
25+
with_depending: 2, format_dep: 1 ]
2626

2727
def run(args) do
2828
Mix.Project.get! # Require the project to be available
@@ -33,9 +33,10 @@ defmodule Mix.Tasks.Deps.Update do
3333
acc = all(init, &deps_updater/2)
3434
rest != [] ->
3535
all_deps = all
36-
deps = Enum.map by_name(rest, all_deps), &check_unavailable!/1
37-
deps = deps ++ depending(deps, all_deps)
38-
{ _, acc } = Enum.map_reduce deps, init, &deps_updater/2
36+
deps = by_name(rest, all_deps)
37+
|> Enum.map(&check_unavailable!/1)
38+
|> with_depending(all_deps)
39+
{ _, acc } = Enum.map_reduce(deps, init, &deps_updater/2)
3940
true ->
4041
raise Mix.Error, message: "mix deps.update expects dependencies as arguments or " <>
4142
"the --all option to update all dependencies"

lib/mix/test/mix/deps_test.exs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,4 +48,27 @@ defmodule Mix.DepsTest do
4848
after
4949
Mix.Project.pop
5050
end
51+
52+
defmodule ConvergedDepsApp do
53+
def project do
54+
[
55+
app: :raw_sample,
56+
version: "0.1.0",
57+
deps: [
58+
{ :deps_repo, "0.1.0", path: "custom/deps_repo" },
59+
{ :git_repo, "0.1.0", git: MixTest.Case.fixture_path("git_repo") }
60+
]
61+
]
62+
end
63+
end
64+
65+
test "correctly order overriden deps" do
66+
Mix.Project.push ConvergedDepsApp
67+
68+
in_fixture "deps_status", fn ->
69+
assert [:git_repo, :deps_repo] == Enum.map(Mix.Deps.all, &(&1.app))
70+
end
71+
after
72+
Mix.Project.pop
73+
end
5174
end

lib/mix/test/mix/tasks/deps_test.exs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,8 @@ defmodule Mix.Tasks.DepsTest do
283283
assert_received { :mix_shell, :info, ["* Compiling deps_repo"] }
284284
assert_received { :mix_shell, :info, ["Generated git_repo.app"] }
285285

286+
Mix.Task.clear
287+
286288
Mix.Tasks.Deps.Update.run ["--all"]
287289
assert_received { :mix_shell, :info, ["* Updating deps_repo (0.1.0) [path: \"custom/deps_repo\"]"] }
288290
assert_received { :mix_shell, :info, ["* Compiling deps_repo"] }

0 commit comments

Comments
 (0)