Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions lib/mix/lib/mix/dep/converger.ex
Original file line number Diff line number Diff line change
Expand Up @@ -94,17 +94,19 @@ defmodule Mix.Dep.Converger do
# on, there is no lock, so we won't hit this branch.
lock = if lock_given?, do: remote.converge(deps, lock), else: lock

deps =
# Build a cache using both dep_name and dep_scm to ensure we only
# return :loaded for deps which have been loaded from the same source.
cache =
deps
|> Enum.reject(&remote.remote?(&1))
|> Enum.into(%{}, &{&1.app, &1})
|> Enum.into(%{}, &{{&1.app, &1.scm}, &1})

# In case no lock was given, we will use the local lock
# which is potentially stale. So remote.deps/2 needs to always
# check if the data it finds in the lock is actually valid.
{deps, rest, lock} =
all(main, apps, callback, rest, lock, env, fn dep ->
if cached = deps[dep.app] do
if cached = cache[{dep.app, dep.scm}] do
{:loaded, cached}
else
{:unloaded, dep, remote.deps(dep, lock)}
Expand Down
40 changes: 39 additions & 1 deletion lib/mix/test/mix/dep_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,7 @@ defmodule Mix.DepTest do
end)
end

## Remove converger
## Remote converger

defmodule IdentityRemoteConverger do
@behaviour Mix.RemoteConverger
Expand Down Expand Up @@ -330,6 +330,44 @@ defmodule Mix.DepTest do
Mix.RemoteConverger.register(nil)
end

defmodule DivergingRemoteConverger do
@behaviour Mix.RemoteConverger

def remote?(%Mix.Dep{app: :deps_repo, scm: Mix.SCM.Path}), do: true
def remote?(%Mix.Dep{app: :git_repo, scm: Mix.SCM.Path}), do: true
def remote?(%Mix.Dep{}), do: false
def deps(%Mix.Dep{app: :deps_repo}, _lock), do: [{:git_repo, path: "custom/git_repo"}]
def deps(%Mix.Dep{app: :git_repo}, _lock), do: []
def post_converge, do: :ok

def converge(_deps, lock) do
lock
|> Map.put(:deps_repo, :custom)
|> Map.put(:git_repo, :custom)
end
end

test "converger detects diverged deps from remote converger" do
deps = [
{:deps_on_git_repo, "0.2.0", git: MixTest.Case.fixture_path("deps_on_git_repo")},
{:deps_repo, "0.1.0", path: "custom/deps_repo"}
]

with_deps(deps, fn ->
Mix.RemoteConverger.register(DivergingRemoteConverger)

in_fixture("deps_status", fn ->
assert_raise Mix.Error, fn ->
Mix.Tasks.Deps.Get.run([])
end

assert_received {:mix_shell, :error, ["Dependencies have diverged:"]}
end)
end)
after
Mix.RemoteConverger.register(nil)
end

test "pass dependencies to remote converger in defined order" do
deps = [
{:ok, "0.1.0", path: "deps/ok"},
Expand Down