Merge pull request #2108 from ericmj/mix-dep-struct

Convert Mix.Dep record to struct
This commit is contained in:
José Valim
2014-03-10 18:13:08 +01:00
13 changed files with 134 additions and 127 deletions
+52 -50
View File
@@ -1,7 +1,6 @@
defrecord Mix.Dep, [ scm: nil, app: nil, requirement: nil, status: nil, opts: nil,
deps: [], extra: nil, manager: nil, from: nil ] do
defmodule Mix.Dep do
@moduledoc """
This is a record that keeps information about your project
This is a struct that keeps information about your project
dependencies. It contains:
* `scm` - a module representing the source code management tool (SCM) operations;
@@ -16,6 +15,11 @@ defrecord Mix.Dep, [ scm: nil, app: nil, requirement: nil, status: nil, opts: ni
the information on this field is private to the scm and
should not be relied on.
"""
@type t :: map
defstruct [ scm: nil, app: nil, requirement: nil, status: nil, opts: nil,
deps: [], extra: nil, manager: nil, from: nil ]
end
defmodule Mix.Deps do
@@ -33,7 +37,7 @@ defmodule Mix.Deps do
and opts is a keyword lists that may include options for the underlying
SCM or options used by Mix. Each set of options is documented below.
Inside Mix, those dependencies are converted to a `Mix.Dep` record.
Inside Mix, those dependencies are converted to a `Mix.Dep` struct.
This module provides conveniences to work with those dependencies
and the dependencies are usually in two specific states: loaded and
unloaded.
@@ -94,7 +98,7 @@ defmodule Mix.Deps do
defdelegate children(otps), to: Mix.Deps.Loader
@doc """
Returns loaded dependencies recursively as a `Mix.Dep` record.
Returns loaded dependencies recursively as a `Mix.Dep` struct.
## Exceptions
@@ -107,8 +111,8 @@ defmodule Mix.Deps do
end
@doc """
Receives a list of dependency names and returns loaded dependency
records. Logs a message if the dependency could not be found.
Receives a list of dependency names and returns loaded `Mix.Dep`s.
Logs a message if the dependency could not be found.
## Exceptions
@@ -121,14 +125,11 @@ defmodule Mix.Deps do
# Ensure all apps are atoms
apps = to_app_names(given)
# We need to keep the order of all, which properly orders deps
deps = Enum.filter all_deps, fn(dep) -> dep.app in apps end
# Now we validate the given atoms
index = Mix.Dep.__record__(:index, :app)
# We need to keep the order of deps, loaded/1 properly orders them
deps = Enum.filter(all_deps, &(&1.app in apps))
Enum.each apps, fn(app) ->
unless List.keyfind(all_deps, app, index) do
unless Enum.any?(all_deps, &(&1.app == app)) do
raise Mix.Error, message: "Unknown dependency #{app} for environment #{Mix.env}"
end
end
@@ -189,7 +190,7 @@ defmodule Mix.Deps do
"""
def in_dependency(dep, post_config \\ [], fun)
def in_dependency(Mix.Dep[app: app, opts: opts], config, fun) do
def in_dependency(%Mix.Dep{app: app, opts: opts}, config, fun) do
# Set the app_path to be the one stored in the dependency.
# This is important because the name of application in the
# mix.exs file can be different than the actual name and we
@@ -211,36 +212,36 @@ defmodule Mix.Deps do
@doc """
Formats the status of a dependency.
"""
def format_status(Mix.Dep[status: { :ok, _vsn }]),
def format_status(%Mix.Dep{status: { :ok, _vsn }}),
do: "ok"
def format_status(Mix.Dep[status: { :noappfile, path }]),
def format_status(%Mix.Dep{status: { :noappfile, path }}),
do: "could not find an app file at #{Path.relative_to_cwd(path)}, " <>
"this may happen when you specified the wrong application name in your deps " <>
"or if the dependency did not compile (which can be amended with `#{mix_env_var}mix deps.compile`)"
def format_status(Mix.Dep[status: { :invalidapp, path }]),
def format_status(%Mix.Dep{status: { :invalidapp, path }}),
do: "the app file at #{Path.relative_to_cwd(path)} is invalid"
def format_status(Mix.Dep[status: { :invalidvsn, vsn }]),
def format_status(%Mix.Dep{status: { :invalidvsn, vsn }}),
do: "the app file contains an invalid version: #{inspect vsn}"
def format_status(Mix.Dep[status: { :nomatchvsn, vsn }, requirement: req]),
def format_status(%Mix.Dep{status: { :nomatchvsn, vsn }, requirement: req}),
do: "the dependency does not match the requirement #{inspect req}, got #{inspect vsn}"
def format_status(Mix.Dep[status: { :lockmismatch, _ }]),
def format_status(%Mix.Dep{status: { :lockmismatch, _ }}),
do: "lock mismatch: the dependency is out of date"
def format_status(Mix.Dep[status: :lockoutdated]),
def format_status(%Mix.Dep{status: :lockoutdated}),
do: "lock outdated: the lock is outdated compared to the options in your mixfile"
def format_status(Mix.Dep[status: :nolock]),
def format_status(%Mix.Dep{status: :nolock}),
do: "the dependency is not locked"
def format_status(Mix.Dep[status: :compile]),
def format_status(%Mix.Dep{status: :compile}),
do: "the dependency build is outdated, please run `#{mix_env_var}mix deps.compile`"
def format_status(Mix.Dep[app: app, status: { :divergedreq, other }] = dep) do
def format_status(%Mix.Dep{app: app, status: { :divergedreq, other }} = dep) do
"the dependency #{app} defined\n" <>
"#{dep_status(dep)}" <>
"\n does not match the requirement specified\n" <>
@@ -248,19 +249,19 @@ defmodule Mix.Deps do
"\n Ensure they match or specify one of the above in your #{inspect Mix.Project.get} deps and set `override: true`"
end
def format_status(Mix.Dep[app: app, status: { :diverged, other }] = dep) do
def format_status(%Mix.Dep{app: app, status: { :diverged, other }} = dep) do
"different specs were given for the #{app} app:\n" <>
"#{dep_status(dep)}#{dep_status(other)}" <>
"\n Ensure they match or specify one of the above in your #{inspect Mix.Project.get} deps and set `override: true`"
end
def format_status(Mix.Dep[app: app, status: { :overridden, other }] = dep) do
def format_status(%Mix.Dep{app: app, status: { :overridden, other }} = dep) do
"the dependency #{app} in #{Path.relative_to_cwd(dep.from)} is overriding a child dependency:\n" <>
"#{dep_status(dep)}#{dep_status(other)}" <>
"\n Ensure they match or specify one of the above in your #{inspect Mix.Project.get} deps and set `override: true`"
end
def format_status(Mix.Dep[status: { :unavailable, _ }, scm: scm]) do
def format_status(%Mix.Dep{status: { :unavailable, _ }, scm: scm}) do
if scm.fetchable? do
"the dependency is not available, run `mix deps.get`"
else
@@ -268,10 +269,10 @@ defmodule Mix.Deps do
end
end
def format_status(Mix.Dep[status: { :elixirlock, _ }]),
def format_status(%Mix.Dep{status: { :elixirlock, _ }}),
do: "the dependency is built with an out-of-date elixir version, run `#{mix_env_var}mix deps.compile`"
defp dep_status(Mix.Dep[app: app, requirement: req, opts: opts, from: from]) do
defp dep_status(%Mix.Dep{app: app, requirement: req, opts: opts, from: from}) do
info = { app, req, Dict.drop(opts, [:dest, :lock, :env, :build]) }
"\n > In #{Path.relative_to_cwd(from)}:\n #{inspect info}\n"
end
@@ -279,7 +280,7 @@ defmodule Mix.Deps do
@doc """
Checks the lock for the given dependency and update its status accordingly.
"""
def check_lock(Mix.Dep[scm: scm, app: app, opts: opts] = dep, lock) do
def check_lock(%Mix.Dep{scm: scm, app: app, opts: opts} = dep, lock) do
if rev = lock[app] do
opts = Keyword.put(opts, :lock, rev)
end
@@ -287,42 +288,43 @@ defmodule Mix.Deps do
if available?(dep) do
case scm.lock_status(opts) do
:mismatch ->
dep.status(if rev, do: { :lockmismatch, rev }, else: :nolock).opts(opts)
status = if rev, do: { :lockmismatch, rev }, else: :nolock
%{dep | status: status, opts: opts}
:outdated ->
# Don't include the lock in the dependency if it is outdated
dep.status(:lockoutdated)
%{dep | status: :lockoutdated}
:ok ->
if vsn = old_elixir_lock(dep) do
dep.status({ :elixirlock, vsn }).opts(opts)
%{dep | status: { :elixirlock, vsn }, opts: opts}
else
dep.opts(opts)
%{dep | opts: opts}
end
end
else
dep.opts(opts)
%{dep | opts: opts}
end
end
@doc """
Returns true if the dependency is ok.
"""
def ok?(Mix.Dep[status: { :ok, _ }]), do: true
def ok?(Mix.Dep[]), do: false
def ok?(%Mix.Dep{status: { :ok, _ }}), do: true
def ok?(%Mix.Dep{}), do: false
@doc """
Checks if a dependency is available. Available dependencies
are the ones that can be loaded.
"""
def available?(Mix.Dep[status: { :overridden, _ }]), do: false
def available?(Mix.Dep[status: { :diverged, _ }]), do: false
def available?(Mix.Dep[status: { :divergedreq, _ }]), do: false
def available?(Mix.Dep[status: { :unavailable, _ }]), do: false
def available?(Mix.Dep[]), do: true
def available?(%Mix.Dep{status: { :overridden, _ }}), do: false
def available?(%Mix.Dep{status: { :diverged, _ }}), do: false
def available?(%Mix.Dep{status: { :divergedreq, _ }}), do: false
def available?(%Mix.Dep{status: { :unavailable, _ }}), do: false
def available?(%Mix.Dep{}), do: true
@doc """
Formats a dependency for printing.
"""
def format_dep(Mix.Dep[scm: scm, app: app, status: status, opts: opts]) do
def format_dep(%Mix.Dep{scm: scm, app: app, status: status, opts: opts}) do
version =
case status do
{ :ok, vsn } when vsn != nil -> "#{vsn} "
@@ -336,7 +338,7 @@ defmodule Mix.Deps do
Returns all load paths for the given dependency. Automatically
derived from source paths.
"""
def load_paths(Mix.Dep[opts: opts] = dep) do
def load_paths(%Mix.Dep{opts: opts} = dep) do
build_path = Path.dirname(opts[:build])
Enum.map source_paths(dep), fn path ->
Path.join [build_path, Path.basename(path), "ebin"]
@@ -349,7 +351,7 @@ defmodule Mix.Deps do
Source paths are the directories that contains ebin files for a given
dependency. All managers, except rebar, have only one source path.
"""
def source_paths(Mix.Dep[manager: :rebar, opts: opts, extra: extra]) do
def source_paths(%Mix.Dep{manager: :rebar, opts: opts, extra: extra}) do
# Add root dir and all sub dirs with ebin/ directory
sub_dirs = Enum.map(extra[:sub_dirs] || [], fn path ->
Path.join(opts[:dest], path)
@@ -361,28 +363,28 @@ defmodule Mix.Deps do
|> Enum.filter(fn p -> p |> Path.join("ebin") |> File.dir? end)
end
def source_paths(Mix.Dep[opts: opts]) do
def source_paths(%Mix.Dep{opts: opts}) do
[opts[:dest]]
end
@doc """
Return `true` if dependency is a mix project.
"""
def mix?(Mix.Dep[manager: manager]) do
def mix?(%Mix.Dep{manager: manager}) do
manager == :mix
end
@doc """
Return `true` if dependency is a rebar project.
"""
def rebar?(Mix.Dep[manager: manager]) do
def rebar?(%Mix.Dep{manager: manager}) do
manager == :rebar
end
@doc """
Return `true` if dependency is a make project.
"""
def make?(Mix.Dep[manager: manager]) do
def make?(%Mix.Dep{manager: manager}) do
manager == :make
end
@@ -402,7 +404,7 @@ defmodule Mix.Deps do
end
end
defp old_elixir_lock(Mix.Dep[opts: opts]) do
defp old_elixir_lock(%Mix.Dep{opts: opts}) do
old_vsn = Mix.Deps.Lock.elixir_vsn(opts[:build])
if old_vsn && old_vsn != System.version do
old_vsn
+17 -17
View File
@@ -11,20 +11,20 @@ defmodule Mix.Deps.Converger do
graph = :digraph.new
try do
Enum.each deps, fn Mix.Dep[app: app] ->
Enum.each(deps, fn %Mix.Dep{app: app} ->
:digraph.add_vertex(graph, app)
end
end)
Enum.each deps, fn Mix.Dep[app: app, deps: other_deps] ->
Enum.each other_deps, fn Mix.Dep[app: other_app] ->
Enum.each(deps, fn %Mix.Dep{app: app, deps: other_deps} ->
Enum.each(other_deps, fn %Mix.Dep{app: other_app} ->
:digraph.add_edge(graph, other_app, app)
end
end
end)
end)
if apps = :digraph_utils.topsort(graph) do
Enum.map apps, fn(app) ->
Enum.find(deps, fn(Mix.Dep[app: other_app]) -> app == other_app end)
end
Enum.map(apps, fn(app) ->
Enum.find(deps, fn(%Mix.Dep{app: other_app}) -> app == other_app end)
end)
else
raise Mix.Error, message: "Could not sort dependencies. There are cycles in the dependency graph."
end
@@ -143,7 +143,7 @@ defmodule Mix.Deps.Converger do
Mix.Deps.Loader.load(dep)
end
dep = dep.update_deps(&reject_non_fullfilled_optional(&1, current_breadths))
dep = %{dep | deps: reject_non_fullfilled_optional(dep.deps, current_breadths)}
{ acc, rest } = all(t, [dep|acc], upper_breadths, current_breadths, callback, rest, cache)
all(dep.deps, acc, current_breadths, Enum.map(dep.deps, &(&1.app)) ++ current_breadths, callback, rest, cache)
end
@@ -164,12 +164,12 @@ defmodule Mix.Deps.Converger do
# also check for the override option and mark the dependency
# as overridden instead of diverged.
defp diverged_deps(list, upper_breadths, dep) do
Mix.Dep[app: app] = dep
%Mix.Dep{app: app} = dep
in_upper? = app in upper_breadths
{ acc, match } =
Enum.map_reduce list, false, fn(other, match) ->
Mix.Dep[app: other_app, opts: other_opts] = other
%Mix.Dep{app: other_app, opts: other_opts} = other
cond do
app != other_app ->
@@ -180,30 +180,30 @@ defmodule Mix.Deps.Converger do
{ with_matching_req(other, dep), true }
true ->
tag = if in_upper?, do: :overridden, else: :diverged
{ other.status({ tag, dep }), true }
{ %{other | status: { tag, dep }}, true }
end
end
if match, do: acc
end
defp converge?(Mix.Dep[scm: scm1, opts: opts1], Mix.Dep[scm: scm2, opts: opts2]) do
defp converge?(%Mix.Dep{scm: scm1, opts: opts1}, %Mix.Dep{scm: scm2, opts: opts2}) do
scm1 == scm2 and scm1.equal?(opts1, opts2)
end
defp reject_non_fullfilled_optional(children, upper_breadths) do
Enum.reject children, fn Mix.Dep[app: app, opts: opts] ->
Enum.reject children, fn %Mix.Dep{app: app, opts: opts} ->
opts[:optional] && not(app in upper_breadths)
end
end
defp with_matching_req(Mix.Dep[] = other, Mix.Dep[] = dep) do
defp with_matching_req(%Mix.Dep{} = other, %Mix.Dep{} = dep) do
case other.status do
{ :ok, vsn } when not nil?(vsn) ->
if Mix.Deps.Loader.vsn_match?(dep.requirement, vsn, dep.app) do
other
else
other.status({ :divergedreq, dep })
%{other | status: { :divergedreq, dep }}
end
_ ->
other
+7 -7
View File
@@ -33,7 +33,7 @@ defmodule Mix.Deps.Fetcher do
end
defp do_fetch(dep, { acc, lock }) do
Mix.Dep[app: app, scm: scm, opts: opts] = dep = check_lock(dep, lock)
%Mix.Dep{app: app, scm: scm, opts: opts} = dep = check_lock(dep, lock)
cond do
# Dependencies that cannot be fetched are always compiled afterwards
@@ -63,11 +63,11 @@ defmodule Mix.Deps.Fetcher do
end
end
defp out_of_date?(Mix.Dep[status: { :lockmismatch, _ }]), do: true
defp out_of_date?(Mix.Dep[status: :lockoutdated]), do: true
defp out_of_date?(Mix.Dep[status: :nolock]), do: true
defp out_of_date?(Mix.Dep[status: { :unavailable, _ }]), do: true
defp out_of_date?(Mix.Dep[]), do: false
defp out_of_date?(%Mix.Dep{status: { :lockmismatch, _ }}), do: true
defp out_of_date?(%Mix.Dep{status: :lockoutdated}), do: true
defp out_of_date?(%Mix.Dep{status: :nolock}), do: true
defp out_of_date?(%Mix.Dep{status: { :unavailable, _ }}), do: true
defp out_of_date?(%Mix.Dep{}), do: false
defp do_finalize({ all_deps, { apps, new_lock } }, old_lock, opts) do
# Let's get the loaded versions of deps
@@ -101,7 +101,7 @@ defmodule Mix.Deps.Fetcher do
defp require_compilation(deps) do
envs = Path.wildcard("_build/*/lib")
for Mix.Dep[app: app] <- deps, env <- envs do
for %Mix.Dep{app: app} <- deps, env <- envs do
File.touch Path.join [env, app, ".compile"]
end
end
+21 -20
View File
@@ -6,7 +6,7 @@ defmodule Mix.Deps.Loader do
@doc """
Gets all direct children of the current `Mix.Project`
as a `Mix.Dep` record. Umbrella project dependencies
as a `Mix.Dep` struct. Umbrella project dependencies
are included as children.
By default, it will filter all dependencies that does not match
@@ -24,7 +24,7 @@ defmodule Mix.Deps.Loader do
# Filter deps not matching mix environment
if env = opts[:env] do
deps =
Enum.filter(deps, fn Mix.Dep[opts: opts] ->
Enum.filter(deps, fn %Mix.Dep{opts: opts} ->
only = opts[:only]
if only, do: env in List.wrap(only), else: true
end)
@@ -38,8 +38,8 @@ defmodule Mix.Deps.Loader do
latest status and children.
"""
def load(dep) do
Mix.Dep[manager: manager, scm: scm, opts: opts] = dep
dep = dep.status(scm_status(scm, opts))
%Mix.Dep{manager: manager, scm: scm, opts: opts} = dep
dep = %{dep | status: scm_status(scm, opts)}
dest = opts[:dest]
{ dep, children } =
@@ -51,19 +51,19 @@ defmodule Mix.Deps.Loader do
rebar_dep(dep)
mix?(dest) ->
mix_dep(dep.manager(:mix))
mix_dep(%{dep | manager: :mix})
rebar?(dest) ->
rebar_dep(dep.manager(:rebar))
rebar_dep(%{dep | manager: :rebar})
make?(dest) ->
{ dep.manager(:make), [] }
{ %{dep | manager: :make}, [] }
true ->
{ dep, [] }
end
validate_path(validate_app(dep)).deps(children)
%{validate_path(validate_app(dep)) | deps: children}
end
@doc """
@@ -96,7 +96,7 @@ defmodule Mix.Deps.Loader do
## Helpers
def to_dep(tuple, scms, from, manager \\ nil) do
with_scm_and_app(tuple, scms).from(from).manager(manager)
%{with_scm_and_app(tuple, scms) | from: from, manager: manager}
end
defp with_scm_and_app({ app, opts }, scms) when is_atom(app) and is_list(opts) do
@@ -119,13 +119,12 @@ defmodule Mix.Deps.Loader do
end
if scm do
Mix.Dep[
%Mix.Dep{
scm: scm,
app: app,
requirement: req,
status: scm_status(scm, opts),
opts: opts
]
opts: opts }
else
raise Mix.Error, message: "#{inspect Mix.Project.get} did not specify a supported scm " <>
"for app #{inspect app}, expected one of :git, :path or :in_umbrella"
@@ -176,7 +175,7 @@ defmodule Mix.Deps.Loader do
## Fetching
defp mix_dep(Mix.Dep[opts: opts] = dep) do
defp mix_dep(%Mix.Dep{opts: opts} = dep) do
Mix.Deps.in_dependency(dep, fn _ ->
config = Mix.project
umbrella? = Mix.Project.umbrella?
@@ -191,15 +190,17 @@ defmodule Mix.Deps.Loader do
end
children = children(env: opts[:env] || :prod)
{ dep.manager(:mix).opts(opts).extra(umbrella: umbrella?), children }
dep = %{dep | manager: :mix, opts: opts, extra: [umbrella: umbrella?]}
{ dep, children }
end)
end
defp rebar_dep(Mix.Dep[] = dep) do
defp rebar_dep(%Mix.Dep{} = dep) do
Mix.Deps.in_dependency(dep, fn _ ->
rebar = Mix.Rebar.load_config(".")
extra = Dict.take(rebar, [:sub_dirs])
{ dep.manager(:rebar).extra(extra), rebar_children(rebar) }
dep = %{dep | manager: :rebar, extra: extra}
{ dep, rebar_children(rebar) }
end)
end
@@ -211,7 +212,7 @@ defmodule Mix.Deps.Loader do
end) |> Enum.concat
end
defp validate_path(Mix.Dep[scm: scm, manager: manager] = dep) do
defp validate_path(%Mix.Dep{scm: scm, manager: manager} = dep) do
if scm == Mix.SCM.Path and not manager in [:mix, nil] do
raise Mix.Error, message: ":path option can only be used with mix projects, " <>
"invalid path dependency for #{inspect dep.app}"
@@ -220,7 +221,7 @@ defmodule Mix.Deps.Loader do
end
end
defp validate_app(Mix.Dep[opts: opts, requirement: req, app: app, status: status] = dep) do
defp validate_app(%Mix.Dep{opts: opts, requirement: req, app: app, status: status} = dep) do
opts_app = opts[:app]
build = opts[:build]
@@ -228,13 +229,13 @@ defmodule Mix.Deps.Loader do
not ok?(status) ->
dep
File.exists?(Path.join(opts[:build], ".compile")) ->
dep.status(:compile)
%{dep | status: :compile}
opts_app == false ->
dep
true ->
path = if is_binary(opts_app), do: opts_app, else: "ebin/#{app}.app"
path = Path.expand(path, build)
dep.status app_status(path, app, req)
%{dep | status: app_status(path, app, req)}
end
end
+9 -4
View File
@@ -30,10 +30,10 @@ defmodule Mix.Deps.Umbrella do
Enum.map(deps, fn umbrella_dep ->
umbrella_dep = Mix.Deps.Loader.load(umbrella_dep)
deps = Enum.filter(umbrella_dep.deps, fn Mix.Dep[] = dep ->
deps = Enum.filter(umbrella_dep.deps, fn dep ->
Mix.Deps.available?(dep) and dep.app in apps
end)
umbrella_dep.deps(deps)
%{umbrella_dep | deps: deps}
end) |> Mix.Deps.Converger.topsort
end
@@ -53,8 +53,13 @@ defmodule Mix.Deps.Umbrella do
Enum.map paths, fn({ app, path }) ->
opts = [path: path, dest: Path.expand(path),
env: Mix.env, build: Path.join([build, "lib", app])]
Mix.Dep[scm: Mix.SCM.Path, app: app, requirement: nil, manager: :mix,
status: { :ok, nil }, opts: opts]
%Mix.Dep{
scm: Mix.SCM.Path,
app: app,
requirement: nil,
manager: :mix,
status: { :ok, nil },
opts: opts }
end
end
end
+1 -1
View File
@@ -212,7 +212,7 @@ defmodule Mix.Task do
if umbrella? && recursive && Mix.ProjectStack.enable_recursion do
config = [build_path: Mix.Project.build_path]
res = for Mix.Dep[app: app, opts: opts] <- Mix.Deps.Umbrella.loaded do
res = for %Mix.Dep{app: app, opts: opts} <- Mix.Deps.Umbrella.loaded do
Mix.Project.in_project(app, opts[:path], config, fun)
end
Mix.ProjectStack.disable_recursion
+1 -1
View File
@@ -284,7 +284,7 @@ defmodule Mix.Tasks.Compile.Elixir do
defp path_deps_changed?(manifest) do
manifest = Path.absname(manifest)
deps = Enum.filter(Mix.Deps.children([]), fn(Mix.Dep[] = dep) ->
deps = Enum.filter(Mix.Deps.children([]), fn dep ->
dep.scm == Mix.SCM.Path
end)
+4 -4
View File
@@ -51,10 +51,10 @@ defmodule Mix.Tasks.Deps.Check do
{ Enum.reverse(not_ok), Enum.reverse(compile) }
end
defp compile?(Mix.Dep[status: { :elixirlock, _ }]), do: true
defp compile?(Mix.Dep[status: { :noappfile, _ }]), do: true
defp compile?(Mix.Dep[status: :compile]), do: true
defp compile?(_), do: false
defp compile?(%Mix.Dep{status: { :elixirlock, _ }}), do: true
defp compile?(%Mix.Dep{status: { :noappfile, _ }}), do: true
defp compile?(%Mix.Dep{status: :compile}), do: true
defp compile?(%Mix.Dep{}), do: false
# If the build is per environment, we should be able to look
# at all dependencies and remove the builds that no longer
+7 -8
View File
@@ -47,8 +47,7 @@ defmodule Mix.Tasks.Deps.Compile do
config = Mix.Project.deps_config
compiled =
Enum.map deps, fn(dep) ->
Mix.Dep[app: app, status: status, opts: opts] = dep
Enum.map(deps, fn %Mix.Dep{app: app, status: status, opts: opts} = dep ->
check_unavailable!(app, status)
unless run_opts[:quiet] || opts[:compile] == false do
@@ -72,14 +71,14 @@ defmodule Mix.Tasks.Deps.Compile do
unless mix?(dep), do: build_structure(dep, config)
File.rm(Path.join(opts[:build], ".compile"))
compiled
end
end)
if Enum.any?(compiled), do: Mix.Deps.Lock.touch
end
# All available dependencies can be compiled
# except for umbrella applications.
defp compilable?(Mix.Dep[manager: manager, extra: extra] = dep) do
defp compilable?(%Mix.Dep{manager: manager, extra: extra} = dep) do
available?(dep) and (manager != :mix or !extra[:umbrella?])
end
@@ -108,7 +107,7 @@ defmodule Mix.Tasks.Deps.Compile do
end
end
defp do_rebar(Mix.Dep[app: app] = dep, config) do
defp do_rebar(%Mix.Dep{app: app} = dep, config) do
do_command dep, rebar_cmd(app), "compile skip_deps=true deps_dir=#{inspect config[:deps_path]}"
end
@@ -134,7 +133,7 @@ defmodule Mix.Tasks.Deps.Compile do
do_command(dep, "make")
end
defp do_compile(Mix.Dep[app: app, opts: opts] = dep) do
defp do_compile(%Mix.Dep{app: app, opts: opts} = dep) do
if command = opts[:compile] do
Mix.shell.info("#{app}: #{command}")
do_command(dep, command)
@@ -143,7 +142,7 @@ defmodule Mix.Tasks.Deps.Compile do
end
end
defp do_command(Mix.Dep[app: app, opts: opts], command, extra \\ "") do
defp do_command(%Mix.Dep{app: app, opts: opts}, command, extra \\ "") do
File.cd! opts[:dest], fn ->
if Mix.shell.cmd("#{command} #{extra}") != 0 do
raise Mix.Error, message: "Could not compile dependency #{app}, #{command} command failed. " <>
@@ -153,7 +152,7 @@ defmodule Mix.Tasks.Deps.Compile do
true
end
defp build_structure(Mix.Dep[opts: opts] = dep, config) do
defp build_structure(%Mix.Dep{opts: opts} = dep, config) do
build_path = Path.dirname(opts[:build])
Enum.each Mix.Deps.source_paths(dep), fn source ->
app = Path.join(build_path, Path.basename(source))
+1 -1
View File
@@ -30,7 +30,7 @@ defmodule Mix.Tasks.Deps do
shell = Mix.shell
lock = Mix.Deps.Lock.read
Enum.each loaded(loaded_opts), fn(Mix.Dep[scm: scm] = dep) ->
Enum.each loaded(loaded_opts), fn %Mix.Dep{scm: scm} = dep ->
dep = check_lock(dep, lock)
shell.info "* #{format_dep(dep)}"
if formatted = scm.format_lock(dep.opts) do
+4 -3
View File
@@ -123,9 +123,10 @@ defmodule Mix.Tasks.Escriptize do
end
defp deps_tuples do
Enum.reduce Mix.Deps.loaded(env: Mix.env) || [], [], fn(dep, acc) ->
get_tuples(dep.opts[:build]) ++ acc
end
deps = Mix.Deps.loaded(env: Mix.env) || []
Enum.reduce(deps, [], fn dep, acc ->
get_tuples(%{dep | opts: :build}) ++ acc
end)
end
defp set_perms(filename) do
+8 -8
View File
@@ -40,12 +40,12 @@ defmodule Mix.DepsTest do
in_fixture "deps_status", fn ->
deps = Mix.Deps.loaded([])
assert length(deps) == 6
assert Enum.find deps, &match?(Mix.Dep[app: :ok, status: { :ok, _ }], &1)
assert Enum.find deps, &match?(Mix.Dep[app: :invalidvsn, status: { :invalidvsn, :ok }], &1)
assert Enum.find deps, &match?(Mix.Dep[app: :invalidapp, status: { :invalidapp, _ }], &1)
assert Enum.find deps, &match?(Mix.Dep[app: :noappfile, status: { :noappfile, _ }], &1)
assert Enum.find deps, &match?(Mix.Dep[app: :uncloned, status: { :unavailable, _ }], &1)
assert Enum.find deps, &match?(Mix.Dep[app: :optional, status: { :unavailable, _ }], &1)
assert Enum.find deps, &match?(%Mix.Dep{app: :ok, status: { :ok, _ }}, &1)
assert Enum.find deps, &match?(%Mix.Dep{app: :invalidvsn, status: { :invalidvsn, :ok }}, &1)
assert Enum.find deps, &match?(%Mix.Dep{app: :invalidapp, status: { :invalidapp, _ }}, &1)
assert Enum.find deps, &match?(%Mix.Dep{app: :noappfile, status: { :noappfile, _ }}, &1)
assert Enum.find deps, &match?(%Mix.Dep{app: :uncloned, status: { :unavailable, _ }}, &1)
assert Enum.find deps, &match?(%Mix.Dep{app: :optional, status: { :unavailable, _ }}, &1)
end
end
@@ -54,7 +54,7 @@ defmodule Mix.DepsTest do
in_fixture "deps_status", fn ->
deps = Mix.Deps.loaded([])
assert Enum.find deps, &match?(Mix.Dep[app: :ok, status: { :ok, _ }], &1)
assert Enum.find deps, &match?(%Mix.Dep{app: :ok, status: { :ok, _ }}, &1)
end
end
@@ -226,7 +226,7 @@ defmodule Mix.DepsTest do
{ deps, _acc } = Mix.Deps.unloaded([], [env: :prod], &{ &1, &2 })
assert length(deps) == 1
assert Enum.find deps, &match?(Mix.Dep[app: :foo], &1)
assert Enum.find deps, &match?(%Mix.Dep{app: :foo}, &1)
end
end
+2 -3
View File
@@ -73,10 +73,9 @@ defmodule Mix.RebarTest do
Mix.Project.push(RebarAsDep)
deps = Mix.Deps.loaded([])
assert Enum.find(deps, &match?(Mix.Dep[app: :rebar_dep], &1))
assert Enum.find(deps, &match?(%Mix.Dep{app: :rebar_dep}, &1))
assert Enum.find(deps, fn dep ->
Mix.Dep[app: app, opts: opts] = dep
assert Enum.find(deps, fn %Mix.Dep{app: app, opts: opts} ->
if app == :git_rebar do
assert Enum.find(opts, &match?({:git, "../../test/fixtures/git_rebar"}, &1))
assert Enum.find(opts, &match?({:ref, "master"}, &1))