Compare commits

...
4 Commits
Author SHA1 Message Date
José Valim 8ca85ed2a8 Release v1.7.3 2018-08-24 20:46:27 +02:00
José Valim af64fe7e98 Consider :runtime and :app from mix.exs (#8109)
Since those values are not stored on Hex, we should not
expect them to be available on Mix.Dep.cached. Instead
we traverse the deps in `mix.exs` to lift this information.

Signed-off-by: José Valim <jose.valim@plataformatec.com.br>
2018-08-24 20:13:26 +02:00
Fernando Tapia Rico 28cf40fe03 Fix arity of try/1 in :elixir_import.special_form (#8079)
Fixes #8078

Signed-off-by: José Valim <jose.valim@plataformatec.com.br>
2018-08-14 12:57:12 +02:00
José Valim d38a189907 Do not use protocols while consolidating
This avoids a race condition in tests.

Signed-off-by: José Valim <jose.valim@plataformatec.com.br>
2018-08-06 07:47:22 +02:00
8 changed files with 60 additions and 57 deletions
+12
View File
@@ -116,6 +116,18 @@ Percentage | Module
77.19% | Total
```
## v1.7.3 (2018-08-24)
### 1. Bug fixes
#### ExUnit
* [ExUnit.Assertions] Do not attempt to expand `try/1` as it is a special form
#### Mix
* [mix compile.app] Do not include applications with `runtime: false` as a runtime dependency for applications coming from Hex
## v1.7.2 (2018-08-05)
### 1. Bug fixes
+1 -1
View File
@@ -1 +1 @@
1.7.2
1.7.3
+1 -1
View File
@@ -239,6 +239,6 @@ special_form('for', _) -> true;
special_form('with', _) -> true;
special_form('cond', 1) -> true;
special_form('case', 2) -> true;
special_form('try', 2) -> true;
special_form('try', 1) -> true;
special_form('receive', 1) -> true;
special_form(_, _) -> false.
+7 -15
View File
@@ -117,11 +117,6 @@ defmodule Mix.Dep do
end
end
# optional and runtime only matter at the top level.
# Any non-top level dependency that is optional and
# is still available means it has been fulfilled.
@child_keep_opts [:optional, :runtime]
defp load_and_cache(_config, top, top, env) do
converge(env: env)
end
@@ -136,21 +131,18 @@ defmodule Mix.Dep do
for dep <- deps,
dep.app == app,
child <- dep.deps,
do: {child.app, Keyword.take(child.opts, @child_keep_opts)},
do: {child.app, Keyword.get(child.opts, :optional, false)},
into: %{}
Enum.map(children, fn %{app: app} = dep ->
Enum.map(children, fn %{app: app, opts: opts} = dep ->
# optional only matters at the top level. Any non-top level dependency
# that is optional and is still available means it has been fulfilled.
case top_level do
%{^app => child_opts} ->
opts =
dep.opts
|> Keyword.drop(@child_keep_opts)
|> Keyword.merge(child_opts)
%{dep | top_level: true, opts: opts}
%{^app => optional} ->
%{dep | top_level: true, opts: Keyword.put(opts, :optional, optional)}
%{} ->
%{dep | top_level: false}
%{dep | top_level: false, opts: Keyword.delete(opts, :optional)}
end
end)
end
+19 -4
View File
@@ -208,7 +208,7 @@ defmodule Mix.Tasks.Compile.App do
apps =
properties
|> Keyword.get(:applications)
|> Kernel.||(apps_from_prod_non_optional_deps(properties))
|> Kernel.||(apps_from_prod_non_optional_deps(properties, config))
|> normalize_apps(extra, config)
Keyword.put(properties, :applications, apps)
@@ -313,17 +313,32 @@ defmodule Mix.Tasks.Compile.App do
end)
end
defp apps_from_prod_non_optional_deps(properties) do
defp apps_from_prod_non_optional_deps(properties, config) do
included_applications = Keyword.get(properties, :included_applications, [])
non_runtime_deps = non_runtime_deps(config)
for %{app: app, opts: opts, top_level: true} <- Mix.Dep.cached(),
Keyword.get(opts, :app, true),
Keyword.get(opts, :runtime, true),
not Keyword.get(opts, :optional, false),
not Map.has_key?(non_runtime_deps, app),
app not in included_applications,
do: app
end
defp non_runtime_deps(config) do
for config_dep <- Keyword.get(config, :deps, []),
not runtime_dep?(config_dep),
do: {elem(config_dep, 0), true},
into: %{}
end
defp runtime_dep?({_app, opts}) when is_list(opts), do: runtime_opts?(opts)
defp runtime_dep?({_app, _req, opts}) when is_list(opts), do: runtime_opts?(opts)
defp runtime_dep?(_), do: true
defp runtime_opts?(opts) do
Keyword.get(opts, :runtime, true) and Keyword.get(opts, :app, true)
end
defp normalize_apps(apps, extra, config) do
Enum.uniq([:kernel, :stdlib] ++ language_app(config) ++ extra ++ apps)
end
+10 -4
View File
@@ -145,10 +145,10 @@ defmodule Mix.Tasks.Compile.Protocols do
case Protocol.consolidate(protocol, impls) do
{:ok, binary} ->
File.write!(Path.join(output, "#{protocol}.beam"), binary)
File.write!(Path.join(output, "#{Atom.to_string(protocol)}.beam"), binary)
if opts[:verbose] do
Mix.shell().info("Consolidated #{inspect(protocol)}")
Mix.shell().info("Consolidated #{inspect_protocol(protocol)}")
end
# If we remove a dependency and we have implemented one of its
@@ -161,11 +161,17 @@ defmodule Mix.Tasks.Compile.Protocols do
remove_consolidated(protocol, output)
if opts[:verbose] do
Mix.shell().info("Unavailable #{inspect(protocol)}")
Mix.shell().info("Unavailable #{inspect_protocol(protocol)}")
end
end
end
# We cannot use the inspect protocol while consolidating
# since inspect may not be available.
defp inspect_protocol(protocol) do
Code.Identifier.inspect_as_atom(protocol)
end
defp reload(module) do
:code.purge(module)
:code.delete(module)
@@ -227,6 +233,6 @@ defmodule Mix.Tasks.Compile.Protocols do
end
defp remove_consolidated(protocol, output) do
File.rm(Path.join(output, "#{protocol}.beam"))
File.rm(Path.join(output, "#{Atom.to_string(protocol)}.beam"))
end
end
+6 -2
View File
@@ -93,8 +93,12 @@ defmodule Mix.Tasks.Deps do
and override it by setting the `:override` option in a top-level project.
* `:runtime` - whether the dependency is part of runtime applications.
Defaults to `true` which automatically adds the application to the list
of apps that are started automatically and included in releases
If the `:applications` key is not provided in `def application` in your
mix.exs file, Mix will automatically included all dependencies as a runtime
application, except if `runtime: false` is given. Defaults to true.
* `:system_env` - an enumerable of key-value tuples of binaries to be set
as environment variables when loading or compiling the dependency
### Git options (`:git`)
+4 -30
View File
@@ -534,7 +534,7 @@ defmodule Mix.DepTest do
end)
end
test "nested deps with runtime override on parent" do
test "nested deps considers runtime from current app" do
Process.put(:custom_deps_git_repo_opts, runtime: false)
deps = [
@@ -544,38 +544,12 @@ defmodule Mix.DepTest do
with_deps(deps, fn ->
in_fixture("deps_status", fn ->
File.mkdir_p!("custom/deps_repo/lib")
File.write!("custom/deps_repo/lib/a.ex", """
# Check that the child dependency is top_level and optional
[%Mix.Dep{app: :git_repo, top_level: true, opts: opts}] = Mix.Dep.cached()
false = Keyword.fetch!(opts, :runtime)
""")
Mix.Tasks.Deps.Get.run([])
Mix.Tasks.Deps.Compile.run([])
end)
end)
end
test "nested deps with runtime override on child" do
deps = [
{:deps_repo, "0.1.0", path: "custom/deps_repo"},
{:git_repo, "0.1.0", git: MixTest.Case.fixture_path("git_repo"), runtime: false}
]
{:ok, [{:application, :deps_repo, opts}]} =
:file.consult("_build/dev/lib/deps_repo/ebin/deps_repo.app")
with_deps(deps, fn ->
in_fixture("deps_status", fn ->
File.mkdir_p!("custom/deps_repo/lib")
File.write!("custom/deps_repo/lib/a.ex", """
# Check that the child dependency is top_level and optional
[%Mix.Dep{app: :git_repo, top_level: true, opts: opts}] = Mix.Dep.cached()
false = Keyword.has_key?(opts, :runtime)
""")
Mix.Tasks.Deps.Get.run([])
Mix.Tasks.Deps.Compile.run([])
assert :git_repo not in Keyword.get(opts, :applications)
end)
end)
end