Skip to content

Commit af64fe7

Browse files
josevalimJosé Valim
authored and
José Valim
committed
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 <[email protected]>
1 parent 28cf40f commit af64fe7

File tree

4 files changed

+36
-51
lines changed

4 files changed

+36
-51
lines changed

lib/mix/lib/mix/dep.ex

Lines changed: 7 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -117,11 +117,6 @@ defmodule Mix.Dep do
117117
end
118118
end
119119

120-
# optional and runtime only matter at the top level.
121-
# Any non-top level dependency that is optional and
122-
# is still available means it has been fulfilled.
123-
@child_keep_opts [:optional, :runtime]
124-
125120
defp load_and_cache(_config, top, top, env) do
126121
converge(env: env)
127122
end
@@ -136,21 +131,18 @@ defmodule Mix.Dep do
136131
for dep <- deps,
137132
dep.app == app,
138133
child <- dep.deps,
139-
do: {child.app, Keyword.take(child.opts, @child_keep_opts)},
134+
do: {child.app, Keyword.get(child.opts, :optional, false)},
140135
into: %{}
141136

142-
Enum.map(children, fn %{app: app} = dep ->
137+
Enum.map(children, fn %{app: app, opts: opts} = dep ->
138+
# optional only matters at the top level. Any non-top level dependency
139+
# that is optional and is still available means it has been fulfilled.
143140
case top_level do
144-
%{^app => child_opts} ->
145-
opts =
146-
dep.opts
147-
|> Keyword.drop(@child_keep_opts)
148-
|> Keyword.merge(child_opts)
149-
150-
%{dep | top_level: true, opts: opts}
141+
%{^app => optional} ->
142+
%{dep | top_level: true, opts: Keyword.put(opts, :optional, optional)}
151143

152144
%{} ->
153-
%{dep | top_level: false}
145+
%{dep | top_level: false, opts: Keyword.delete(opts, :optional)}
154146
end
155147
end)
156148
end

lib/mix/lib/mix/tasks/compile.app.ex

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,7 @@ defmodule Mix.Tasks.Compile.App do
208208
apps =
209209
properties
210210
|> Keyword.get(:applications)
211-
|> Kernel.||(apps_from_prod_non_optional_deps(properties))
211+
|> Kernel.||(apps_from_prod_non_optional_deps(properties, config))
212212
|> normalize_apps(extra, config)
213213

214214
Keyword.put(properties, :applications, apps)
@@ -313,17 +313,32 @@ defmodule Mix.Tasks.Compile.App do
313313
end)
314314
end
315315

316-
defp apps_from_prod_non_optional_deps(properties) do
316+
defp apps_from_prod_non_optional_deps(properties, config) do
317317
included_applications = Keyword.get(properties, :included_applications, [])
318+
non_runtime_deps = non_runtime_deps(config)
318319

319320
for %{app: app, opts: opts, top_level: true} <- Mix.Dep.cached(),
320-
Keyword.get(opts, :app, true),
321-
Keyword.get(opts, :runtime, true),
322321
not Keyword.get(opts, :optional, false),
322+
not Map.has_key?(non_runtime_deps, app),
323323
app not in included_applications,
324324
do: app
325325
end
326326

327+
defp non_runtime_deps(config) do
328+
for config_dep <- Keyword.get(config, :deps, []),
329+
not runtime_dep?(config_dep),
330+
do: {elem(config_dep, 0), true},
331+
into: %{}
332+
end
333+
334+
defp runtime_dep?({_app, opts}) when is_list(opts), do: runtime_opts?(opts)
335+
defp runtime_dep?({_app, _req, opts}) when is_list(opts), do: runtime_opts?(opts)
336+
defp runtime_dep?(_), do: true
337+
338+
defp runtime_opts?(opts) do
339+
Keyword.get(opts, :runtime, true) and Keyword.get(opts, :app, true)
340+
end
341+
327342
defp normalize_apps(apps, extra, config) do
328343
Enum.uniq([:kernel, :stdlib] ++ language_app(config) ++ extra ++ apps)
329344
end

lib/mix/lib/mix/tasks/deps.ex

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,8 +93,12 @@ defmodule Mix.Tasks.Deps do
9393
and override it by setting the `:override` option in a top-level project.
9494
9595
* `:runtime` - whether the dependency is part of runtime applications.
96-
Defaults to `true` which automatically adds the application to the list
97-
of apps that are started automatically and included in releases
96+
If the `:applications` key is not provided in `def application` in your
97+
mix.exs file, Mix will automatically included all dependencies as a runtime
98+
application, except if `runtime: false` is given. Defaults to true.
99+
100+
* `:system_env` - an enumerable of key-value tuples of binaries to be set
101+
as environment variables when loading or compiling the dependency
98102
99103
### Git options (`:git`)
100104

lib/mix/test/mix/dep_test.exs

Lines changed: 4 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -534,7 +534,7 @@ defmodule Mix.DepTest do
534534
end)
535535
end
536536

537-
test "nested deps with runtime override on parent" do
537+
test "nested deps considers runtime from current app" do
538538
Process.put(:custom_deps_git_repo_opts, runtime: false)
539539

540540
deps = [
@@ -544,38 +544,12 @@ defmodule Mix.DepTest do
544544

545545
with_deps(deps, fn ->
546546
in_fixture("deps_status", fn ->
547-
File.mkdir_p!("custom/deps_repo/lib")
548-
549-
File.write!("custom/deps_repo/lib/a.ex", """
550-
# Check that the child dependency is top_level and optional
551-
[%Mix.Dep{app: :git_repo, top_level: true, opts: opts}] = Mix.Dep.cached()
552-
false = Keyword.fetch!(opts, :runtime)
553-
""")
554-
555-
Mix.Tasks.Deps.Get.run([])
556547
Mix.Tasks.Deps.Compile.run([])
557-
end)
558-
end)
559-
end
560548

561-
test "nested deps with runtime override on child" do
562-
deps = [
563-
{:deps_repo, "0.1.0", path: "custom/deps_repo"},
564-
{:git_repo, "0.1.0", git: MixTest.Case.fixture_path("git_repo"), runtime: false}
565-
]
566-
567-
with_deps(deps, fn ->
568-
in_fixture("deps_status", fn ->
569-
File.mkdir_p!("custom/deps_repo/lib")
570-
571-
File.write!("custom/deps_repo/lib/a.ex", """
572-
# Check that the child dependency is top_level and optional
573-
[%Mix.Dep{app: :git_repo, top_level: true, opts: opts}] = Mix.Dep.cached()
574-
false = Keyword.has_key?(opts, :runtime)
575-
""")
549+
{:ok, [{:application, :deps_repo, opts}]} =
550+
:file.consult("_build/dev/lib/deps_repo/ebin/deps_repo.app")
576551

577-
Mix.Tasks.Deps.Get.run([])
578-
Mix.Tasks.Deps.Compile.run([])
552+
assert :git_repo not in Keyword.get(opts, :applications)
579553
end)
580554
end)
581555
end

0 commit comments

Comments
 (0)