Add deps.check
This commit is contained in:
@@ -266,7 +266,7 @@ defmodule ExUnit.Assertions do
|
||||
if name == ExUnit.AssertionError do
|
||||
raise(error)
|
||||
else
|
||||
flunk "Expected exception #{inspect exception}, got #{inspect name}"
|
||||
flunk "Expected exception #{inspect exception}, got #{inspect name} (#{error.message})"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -188,7 +188,7 @@ defmodule ExUnit.AssertionsTest do
|
||||
end
|
||||
rescue
|
||||
error in [ExUnit.AssertionError] ->
|
||||
"Expected exception ArgumentError, got UndefinedFunctionError" = error.message
|
||||
"Expected exception ArgumentError, got UndefinedFunctionError (undefined function: Certainly.Undefined.function/3)" = error.message
|
||||
end
|
||||
end
|
||||
|
||||
@@ -199,7 +199,7 @@ defmodule ExUnit.AssertionsTest do
|
||||
end
|
||||
rescue
|
||||
error in [ExUnit.AssertionError] ->
|
||||
"Expected exception SyntaxError, got FunctionClauseError" = error.message
|
||||
"Expected exception SyntaxError, got FunctionClauseError (no function clause matching: :lists.flatten(1))" = error.message
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ defmodule Mix.CLI do
|
||||
@moduledoc false
|
||||
|
||||
defmacrop exceptions do
|
||||
[Mix.Error, Mix.NoTaskError, Mix.InvalidTaskError, Mix.NoProjectError]
|
||||
[Mix.Error, Mix.NoTaskError, Mix.InvalidTaskError, Mix.NoProjectError, Mix.NotMetDepsError]
|
||||
end
|
||||
|
||||
@doc """
|
||||
|
||||
@@ -12,4 +12,6 @@ end
|
||||
|
||||
defexception Mix.NoProjectError, message: "Could not find a Mix.Project"
|
||||
|
||||
defexception Mix.Error, message: nil
|
||||
defexception Mix.Error, message: nil
|
||||
|
||||
defexception Mix.NotMetDepsError, message: "Some dependencies were not met"
|
||||
@@ -1,5 +1,5 @@
|
||||
defmodule Mix.SCM.Git do
|
||||
def cloned?(path) do
|
||||
def available?(path) do
|
||||
File.dir?(File.join(path, ".git"))
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,32 @@
|
||||
defmodule Mix.Tasks.Deps.Check do
|
||||
use Mix.Task
|
||||
|
||||
import Mix.Tasks.Deps, [all: 0, format_dep: 1, format_status: 1]
|
||||
|
||||
@moduledoc """
|
||||
Checks if all dependencies are valid and if not, abort.
|
||||
Prints the invalid dependencies status before aborting.
|
||||
|
||||
This task is not exhibited in `mix help` but it is part
|
||||
of mix public API and can be depended on.
|
||||
"""
|
||||
def run(_) do
|
||||
case Enum.partition all, match?({ _, _, _, { :ok, _ }, _ }, &1) do
|
||||
{ _, [] } -> :ok
|
||||
{ _, not_ok } ->
|
||||
if Enum.all? not_ok, match?({ _, _, _, { :unavailable, _ }, _ }, &1) do
|
||||
raise Mix.NotMetDepsError, message:
|
||||
"Dependencies are not available, run `mix deps.get` before proceeding"
|
||||
else
|
||||
shell = Mix.shell
|
||||
|
||||
Enum.each not_ok, fn(dep) ->
|
||||
shell.error "* #{format_dep(dep)}"
|
||||
shell.error " #{format_status elem(dep, 4)}"
|
||||
end
|
||||
|
||||
raise Mix.NotMetDepsError
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -3,6 +3,10 @@ defmodule Mix.Tasks.Deps do
|
||||
|
||||
@shortdoc "List dependencies and their status"
|
||||
|
||||
@moduledoc """
|
||||
List all dependencies and their status.
|
||||
"""
|
||||
|
||||
@doc """
|
||||
Returns all dependencies in the following format:
|
||||
|
||||
@@ -24,18 +28,25 @@ defmodule Mix.Tasks.Deps do
|
||||
Enum.map deps, with_scm_and_status(&1)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Get all dependencies that match the specific `status`.
|
||||
"""
|
||||
def all(status) do
|
||||
Enum.filter all, match?({ _, _, _, { ^status, _ }, _ }, &1)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Formats the status of a dependency. It can be either:
|
||||
|
||||
* `{ :ok, vsn }` - Everything is :ok, got version `vsn`;
|
||||
* `{ :uncloned, path }` - The dependency is not checked out;
|
||||
* `{ :unavailable, path }` - The dependency is not available;
|
||||
* `{ :noappfile, path }` - The .app file at path could not be found;
|
||||
* `{ :invalidapp, path }` - The .app file at path is not properly formatted;
|
||||
* `{ :invalidvsn, actual }` - The dependency does not match the specified requirement, got `actual`;
|
||||
|
||||
"""
|
||||
def format_status({ :ok, _vsn }), do: "ok"
|
||||
def format_status({ :uncloned, path }), do: "the dependency is not checked out at: #{path}"
|
||||
def format_status({ :unavailable, _ }), do: "the dependency is not available, run `mix deps.get`"
|
||||
def format_status({ :noappfile, path }), do: "could not find app file at #{path}"
|
||||
def format_status({ :invalidapp, path }), do: "the app file at #{path} is invalid"
|
||||
def format_status({ :invalidvsn, vsn }), do: "the dependency does not match the specified version, got #{vsn}"
|
||||
@@ -57,13 +68,10 @@ defmodule Mix.Tasks.Deps do
|
||||
"#{app} #{version}[#{opts}]"
|
||||
end
|
||||
|
||||
@doc """
|
||||
|
||||
"""
|
||||
def run(_) do
|
||||
shell = Mix.shell
|
||||
|
||||
Enum.map all, fn(dep) ->
|
||||
Enum.each all, fn(dep) ->
|
||||
shell.info "* #{format_dep(dep)}"
|
||||
shell.info " #{format_status elem(dep, 4)}"
|
||||
end
|
||||
@@ -97,11 +105,11 @@ defmodule Mix.Tasks.Deps do
|
||||
|
||||
defp status(scm, app, req, _) do
|
||||
deps_path = deps_path(app)
|
||||
if scm.cloned? deps_path do
|
||||
if scm.available? deps_path do
|
||||
app_path = File.join deps_path, "ebin/#{app}.app"
|
||||
validate_app_file(app_path, app, req)
|
||||
else
|
||||
{ :uncloned, deps_path }
|
||||
{ :unavailable, deps_path }
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
defmodule Mix.Tasks.Deps.Get do
|
||||
use Mix.Task
|
||||
|
||||
@shortdoc "Get uncloned dependencies"
|
||||
@shortdoc "Get all unavailable dependencies"
|
||||
end
|
||||
@@ -17,7 +17,28 @@ defmodule Mix.Tasks.DepsTest do
|
||||
end
|
||||
end
|
||||
|
||||
test "mix deps prints list of dependencies and their status" do
|
||||
defmodule SuccessfulDepsApp do
|
||||
def project do
|
||||
[
|
||||
deps: [
|
||||
{ "ok", "0.1.0", git: "https://github.com/elixir-lang/ok.git" }
|
||||
]
|
||||
]
|
||||
end
|
||||
end
|
||||
|
||||
defmodule UnclonedDepsApp do
|
||||
def project do
|
||||
[
|
||||
deps: [
|
||||
{ "uncloned", "0.1.0", git: "https://github.com/elixir-lang/uncloned.git" }
|
||||
]
|
||||
]
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
test "prints list of dependencies and their status" do
|
||||
Mix.Project.push DepsApp
|
||||
|
||||
in_fixture "deps_status", fn ->
|
||||
@@ -32,7 +53,56 @@ defmodule Mix.Tasks.DepsTest do
|
||||
assert_received { :mix_shell, :info, ["* noappfile [git: \"https://github.com/elixir-lang/noappfile.git\"]"] }
|
||||
assert_received { :mix_shell, :info, [" could not find app file at deps/noappfile/ebin/noappfile.app"] }
|
||||
assert_received { :mix_shell, :info, ["* uncloned [git: \"https://github.com/elixir-lang/uncloned.git\"]"] }
|
||||
assert_received { :mix_shell, :info, [" the dependency is not checked out at: deps/uncloned"] }
|
||||
assert_received { :mix_shell, :info, [" the dependency is not available, run `mix deps.get`"] }
|
||||
end
|
||||
after
|
||||
Mix.Project.pop
|
||||
end
|
||||
|
||||
test "check list of dependencies and their status on success" do
|
||||
Mix.Project.push SuccessfulDepsApp
|
||||
|
||||
in_fixture "deps_status", fn ->
|
||||
Mix.Tasks.Deps.Check.run []
|
||||
end
|
||||
after
|
||||
Mix.Project.pop
|
||||
end
|
||||
|
||||
test "check list of dependencies and their status on first run" do
|
||||
Mix.Project.push UnclonedDepsApp
|
||||
|
||||
in_fixture "deps_status", fn ->
|
||||
assert_raise Mix.NotMetDepsError, "Dependencies are not available, run `mix deps.get` before proceeding", fn ->
|
||||
Mix.Tasks.Deps.Check.run []
|
||||
end
|
||||
|
||||
refute_received { :mix_shell, :error, ["* uncloned [git: \"https://github.com/elixir-lang/uncloned.git\"]"] }
|
||||
refute_received { :mix_shell, :error, [" the dependency is not available, run `mix deps.get`"] }
|
||||
end
|
||||
after
|
||||
Mix.Project.pop
|
||||
end
|
||||
|
||||
test "check list of dependencies and their status on failure" do
|
||||
Mix.Project.push DepsApp
|
||||
|
||||
in_fixture "deps_status", fn ->
|
||||
assert_raise Mix.NotMetDepsError, fn ->
|
||||
Mix.Tasks.Deps.Check.run []
|
||||
end
|
||||
|
||||
refute_received { :mix_shell, :error, ["* ok (0.1.0) [git: \"https://github.com/elixir-lang/ok.git\"]"] }
|
||||
refute_received { :mix_shell, :error, [" ok"] }
|
||||
|
||||
assert_received { :mix_shell, :error, ["* invalidvsn [git: \"https://github.com/elixir-lang/invalidvsn.git\"]"] }
|
||||
assert_received { :mix_shell, :error, [" the dependency does not match the specified version, got 0.1.0"] }
|
||||
assert_received { :mix_shell, :error, ["* invalidapp [git: \"https://github.com/elixir-lang/invalidapp.git\"]"] }
|
||||
assert_received { :mix_shell, :error, [" the app file at deps/invalidapp/ebin/invalidapp.app is invalid"] }
|
||||
assert_received { :mix_shell, :error, ["* noappfile [git: \"https://github.com/elixir-lang/noappfile.git\"]"] }
|
||||
assert_received { :mix_shell, :error, [" could not find app file at deps/noappfile/ebin/noappfile.app"] }
|
||||
assert_received { :mix_shell, :error, ["* uncloned [git: \"https://github.com/elixir-lang/uncloned.git\"]"] }
|
||||
assert_received { :mix_shell, :error, [" the dependency is not available, run `mix deps.get`"] }
|
||||
end
|
||||
after
|
||||
Mix.Project.pop
|
||||
|
||||
Reference in New Issue
Block a user