 
   defp with_deps(deps, fun) do
     Process.put(:mix_deps, deps)
-    Mix.Project.push ProcessDepsApp
+    Mix.Project.push(ProcessDepsApp)
     fun.()
   after
-    Mix.Project.pop
+    Mix.Project.pop()
   end
 
   defp assert_wrong_dependency(deps) do
-    with_deps deps, fn ->
+    with_deps(deps, fn ->
       assert_raise Mix.Error, ~r"Dependency specified in the wrong format", fn ->
         Mix.Dep.loaded([])
       end
-    end
+    end)
   end
 
   test "respects the MIX_NO_DEPS flag" do
-    Mix.Project.push DepsApp
+    Mix.Project.push(DepsApp)
 
     in_fixture "deps_status", fn ->
       deps = Mix.Dep.cached()

  end

  test "fails on invalid dependencies" do
    assert_wrong_dependency [{:ok}]
    assert_wrong_dependency [{:ok, nil}]
    assert_wrong_dependency [{:ok, nil, []}]
  end

  test "use requirements for dependencies" do
    with_deps [{:ok, "~> 0.1", path: "deps/ok"}], fn ->
      in_fixture "deps_status", fn ->
        deps = Mix.Dep.loaded([])
        assert Enum.find deps, &match?(%Mix.Dep{app: :ok, status: {:ok, _}}, &1)
      end
    end
  end

  test "raises when no SCM is specified" do
    with_deps [{:ok, "~> 0.1", not_really: :ok}], fn ->
      in_fixture "deps_status", fn ->
        send self(), {:mix_shell_input, :yes?, false}
        msg = "Could not find an SCM for dependency :ok from Mix.DepTest.ProcessDepsApp"
        assert_raise Mix.Error, msg, fn -> Mix.Dep.loaded([]) end
      end
    end
  end

  test "does not set the manager before the dependency was loaded" do
    # It is important to not eagerly set the manager because the dependency
    # needs to be loaded (i.e. available in the filesystem) in order to get
    # the proper manager.
    Mix.Project.push DepsApp

    {_, true, _} =
      Mix.Dep.Converger.converge(false, [], nil, fn dep, acc, lock ->

        Mix.env(:prod)
        Mix.Tasks.Deps.Loadpaths.run([])
      end
    end)
  end

  test "nested deps selects only prod dependencies" do
    Process.put(:custom_deps_git_repo_opts, only: :test)
    deps = [{:deps_repo, "0.1.0", path: "custom/deps_repo"}]

    with_deps(deps, fn ->
      in_fixture "deps_status", fn ->
        loaded = Mix.Dep.loaded([])
        assert [:deps_repo] = Enum.map(loaded, & &1.app)

        loaded = Mix.Dep.loaded(env: :test)
        assert [:deps_repo] = Enum.map(loaded, & &1.app)
      end
    end)
  end

  test "nested deps on only matching" do
    # deps_repo wants git_repo for test, git_repo is restricted to only test
    # We assert the dependencies match as expected, happens in umbrella apps
    Process.put(:custom_deps_git_repo_opts, only: :test)

    # We need to pass env: :test so the child dependency is loaded
    # in the first place (otherwise only :prod deps are loaded)
    deps = [
      {:deps_repo, "0.1.0", path: "custom/deps_repo", env: :test},
      {:git_repo, "0.2.0", git: MixTest.Case.fixture_path("git_repo"), only: :test}
    ]

    with_deps(deps, fn ->
      in_fixture "deps_status", fn ->
        loaded = Mix.Dep.loaded([])
        assert [:git_repo, :deps_repo] = Enum.map(loaded, & &1.app)
        assert [unavailable: _, noappfile: _] = Enum.map(loaded, & &1.status)

        loaded = Mix.Dep.loaded(env: :dev)
        assert [:deps_repo] = Enum.map(loaded, & &1.app)
        assert [noappfile: _] = Enum.map(loaded, & &1.status)

        loaded = Mix.Dep.loaded(env: :test)
        assert [:git_repo, :deps_repo] = Enum.map(loaded, & &1.app)
        assert [unavailable: _, noappfile: _] = Enum.map(loaded, & &1.status)
      end
    end)
  end

  test "nested deps on only conflict" do
    # deps_repo wants all git_repo, git_repo is restricted to only test
    deps = [
      {:deps_repo, "0.1.0", path: "custom/deps_repo"},
      {:git_repo, "0.2.0", git: MixTest.Case.fixture_path("git_repo"), only: :test}
    ]

    with_deps(deps, fn ->
      in_fixture "deps_status", fn ->
        loaded = Mix.Dep.loaded([])
        assert [:git_repo, :deps_repo] = Enum.map(loaded, & &1.app)
        assert [divergedonly: _, noappfile: _] = Enum.map(loaded, & &1.status)

        loaded = Mix.Dep.loaded(env: :dev)
        assert [:git_repo, :deps_repo] = Enum.map(loaded, & &1.app)
        assert [divergedonly: _, noappfile: _] = Enum.map(loaded, & &1.status)

        loaded = Mix.Dep.loaded(env: :test)
        assert [:git_repo, :deps_repo] = Enum.map(loaded, & &1.app)
        assert [divergedonly: _, noappfile: _] = Enum.map(loaded, & &1.status)

        Mix.Tasks.Deps.run([])
        assert_received {:mix_shell, :info, ["* git_repo" <> _]}
        assert_received {:mix_shell, :info, [msg]}
        assert msg =~ "Remove the :only restriction from your dep"
      end
    end)
  end

  test "nested deps on only conflict does not happen with optional deps" do
    Process.put(:custom_deps_git_repo_opts, optional: true)

    # deps_repo wants all git_repo, git_repo is restricted to only test
    deps = [
      {:deps_repo, "0.1.0", path: "custom/deps_repo"},
      {:git_repo, "0.2.0", git: MixTest.Case.fixture_path("git_repo"), only: :test}
    ]

    with_deps(deps, fn ->
      in_fixture "deps_status", fn ->
        loaded = Mix.Dep.loaded([])
        assert [:git_repo, :deps_repo] = Enum.map(loaded, & &1.app)
        assert [unavailable: _, noappfile: _] = Enum.map(loaded, & &1.status)

        loaded = Mix.Dep.loaded(env: :dev)
        assert [:deps_repo] = Enum.map(loaded, & &1.app)
        assert [noappfile: _] = Enum.map(loaded, & &1.status)

        loaded = Mix.Dep.loaded(env: :test)
        assert [:git_repo, :deps_repo] = Enum.map(loaded, & &1.app)
        assert [unavailable: _, noappfile: _] = Enum.map(loaded, & &1.status)
      end
    end)
  end

  test "nested deps with valid only subset" do
    # deps_repo wants git_repo for prod, git_repo is restricted to only prod and test
    deps = [
      {:deps_repo, "0.1.0", path: "custom/deps_repo", only: :prod},
      {:git_repo, "0.2.0", git: MixTest.Case.fixture_path("git_repo"), only: [:prod, :test]}
    ]

    with_deps(deps, fn ->
      in_fixture "deps_status", fn ->
        loaded = Mix.Dep.loaded([])
        assert [:git_repo, :deps_repo] = Enum.map(loaded, & &1.app)
        assert [unavailable: _, noappfile: _] = Enum.map(loaded, & &1.status)

        loaded = Mix.Dep.loaded(env: :dev)
        assert [] = Enum.map(loaded, & &1.app)

        loaded = Mix.Dep.loaded(env: :test)
        assert [:git_repo] = Enum.map(loaded, & &1.app)
        assert [unavailable: _] = Enum.map(loaded, & &1.status)

        loaded = Mix.Dep.loaded(env: :prod)
        assert [:git_repo, :deps_repo] = Enum.map(loaded, & &1.app)
        assert [unavailable: _, noappfile: _] = Enum.map(loaded, & &1.status)
      end
    end)
  end

  test "nested deps with invalid only subset" do
    # deps_repo wants git_repo for dev, git_repo is restricted to only test
    deps = [
      {:deps_repo, "0.1.0", path: "custom/deps_repo", only: :dev},
      {:git_repo, "0.2.0", git: MixTest.Case.fixture_path("git_repo"), only: [:test]}
    ]

    with_deps(deps, fn ->
      in_fixture "deps_status", fn ->
        loaded = Mix.Dep.loaded([])
        assert [:git_repo, :deps_repo] = Enum.map(loaded, & &1.app)
        assert [divergedonly: _, noappfile: _] = Enum.map(loaded, & &1.status)

        loaded = Mix.Dep.loaded(env: :dev)
        assert [:git_repo, :deps_repo] = Enum.map(loaded, & &1.app)
        assert [divergedonly: _, noappfile: _] = Enum.map(loaded, & &1.status)

        loaded = Mix.Dep.loaded(env: :test)
        assert [:git_repo] = Enum.map(loaded, & &1.app)
        assert [unavailable: _] = Enum.map(loaded, & &1.status)

        Mix.Tasks.Deps.run([])
        assert_received {:mix_shell, :info, ["* git_repo" <> _]}
        assert_received {:mix_shell, :info, [msg]}
        assert msg =~ "Ensure you specify at least the same environments in :only in your dep"
      end
    end)
  end

  test "nested deps with valid only in both parent and child" do
    Process.put(:custom_deps_git_repo_opts, only: :test)

    # deps_repo has environment set to test so it loads the deps_git_repo set to test too
    deps = [
      {:deps_repo, "0.1.0", path: "custom/deps_repo", env: :test, only: [:dev, :test]},
      {:git_repo, "0.1.0", git: MixTest.Case.fixture_path("git_repo"), only: :test}
    ]

    with_deps(deps, fn ->
      in_fixture "deps_status", fn ->
        loaded = Mix.Dep.loaded([])
        assert [:git_repo, :deps_repo] = Enum.map(loaded, & &1.app)
        assert [unavailable: _, noappfile: _] = Enum.map(loaded, & &1.status)

        loaded = Mix.Dep.loaded(env: :dev)
        assert [:deps_repo] = Enum.map(loaded, & &1.app)
        assert [noappfile: _] = Enum.map(loaded, & &1.status)

        loaded = Mix.Dep.loaded(env: :test)
        assert [:git_repo, :deps_repo] = Enum.map(loaded, & &1.app)
        assert [unavailable: _, noappfile: _] = Enum.map(loaded, & &1.status)

        loaded = Mix.Dep.loaded(env: :prod)
        assert [] = Enum.map(loaded, & &1.app)
      end
    end)
  end

  test "nested deps converge and diverge when only is not in_upper" do
    loaded_only = fn deps ->
      with_deps(deps, fn ->
        in_fixture "deps_status", fn ->
          File.mkdir_p!("custom/other_repo")

          File.write!("custom/other_repo/mix.exs", """
          defmodule OtherRepo do
            use Mix.Project

