Skip to content

Commit 7ff97fb

Browse files
committed
Compute remove entries per dependency, closes #12801
1 parent af378de commit 7ff97fb

File tree

2 files changed

+60
-59
lines changed

2 files changed

+60
-59
lines changed

lib/mix/lib/mix/compilers/elixir.ex

+58-58
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
defmodule Mix.Compilers.Elixir do
22
@moduledoc false
33

4-
@manifest_vsn 19
4+
@manifest_vsn 20
55
@checkpoint_vsn 2
66

77
import Record
@@ -566,72 +566,72 @@ defmodule Mix.Compilers.Elixir do
566566
Enum.any?(enumerable, &Map.has_key?(map, &1))
567567
end
568568

569-
defp stale_local_deps(local_deps, manifest, stale_modules, modified, old_exports) do
569+
defp stale_local_deps(local_deps, manifest, stale_modules, modified, deps_exports) do
570570
base = Path.basename(manifest)
571571

572572
# The stale modules so far will become both stale_modules and stale_exports,
573573
# as any export from a dependency needs to be recompiled.
574574
stale_modules = Map.from_keys(stale_modules, true)
575575

576-
{stale_modules, stale_exports, new_exports} =
577-
for %{opts: opts} <- local_deps,
578-
manifest = Path.join([opts[:build], ".mix", base]),
579-
Mix.Utils.last_modified(manifest) > modified,
580-
reduce: {stale_modules, stale_modules, []} do
581-
{modules, exports, new_exports} ->
582-
{manifest_modules, manifest_sources} = read_manifest(manifest)
583-
584-
dep_modules =
585-
for module(module: module, timestamp: timestamp) <- manifest_modules,
586-
timestamp > modified,
587-
do: module
588-
589-
# If any module has a compile time dependency on a changed module
590-
# within the dependency, they will be recompiled. However, export
591-
# and runtime dependencies won't have recompiled so we need to
592-
# propagate them to the parent app.
593-
{dep_modules, _, _} =
594-
fixpoint_runtime_modules(manifest_sources, Map.from_keys(dep_modules, true))
595-
596-
# Update exports
597-
{exports, new_exports} =
598-
for {module, _} <- dep_modules, reduce: {exports, new_exports} do
599-
{exports, new_exports} ->
600-
export = exports_md5(module, false)
601-
602-
# If the exports are the same, then the API did not change,
603-
# so we do not mark the export as stale. Note this has to
604-
# be very conservative. If the module is not loaded or if
605-
# the exports were not there, we need to consider it a stale
606-
# export.
607-
exports =
608-
if export && old_exports[module] == export,
609-
do: exports,
610-
else: Map.put(exports, module, true)
611-
612-
# Then we store the new export if any
613-
new_exports =
614-
if export,
615-
do: [{module, export} | new_exports],
616-
else: new_exports
617-
618-
{exports, new_exports}
619-
end
620-
621-
{Map.merge(modules, dep_modules), exports, new_exports}
622-
end
576+
for %{app: app, opts: opts} <- local_deps,
577+
manifest = Path.join([opts[:build], ".mix", base]),
578+
Mix.Utils.last_modified(manifest) > modified,
579+
reduce: {stale_modules, stale_modules, deps_exports} do
580+
{modules, exports, deps_exports} ->
581+
{manifest_modules, manifest_sources} = read_manifest(manifest)
582+
583+
dep_modules =
584+
for module(module: module, timestamp: timestamp) <- manifest_modules,
585+
timestamp > modified,
586+
do: module
587+
588+
# If any module has a compile time dependency on a changed module
589+
# within the dependency, they will be recompiled. However, export
590+
# and runtime dependencies won't have recompiled so we need to
591+
# propagate them to the parent app.
592+
{dep_modules, _, _} =
593+
fixpoint_runtime_modules(manifest_sources, Map.from_keys(dep_modules, true))
594+
595+
old_exports = Map.get(deps_exports, app, %{})
596+
597+
# Update exports
598+
{exports, new_exports} =
599+
for {module, _} <- dep_modules, reduce: {exports, []} do
600+
{exports, new_exports} ->
601+
export = exports_md5(module, false)
602+
603+
# If the exports are the same, then the API did not change,
604+
# so we do not mark the export as stale. Note this has to
605+
# be very conservative. If the module is not loaded or if
606+
# the exports were not there, we need to consider it a stale
607+
# export.
608+
exports =
609+
if export && old_exports[module] == export,
610+
do: exports,
611+
else: Map.put(exports, module, true)
612+
613+
# Then we store the new export if any
614+
new_exports =
615+
if export,
616+
do: [{module, export} | new_exports],
617+
else: new_exports
618+
619+
{exports, new_exports}
620+
end
623621

624-
# Any dependency in old export but not in new export
625-
# was removed so we need to mark them as stale too.
626-
new_exports = Map.new(new_exports)
622+
new_exports = Map.new(new_exports)
627623

628-
removed =
629-
for {module, _} <- old_exports,
630-
not is_map_key(new_exports, module),
631-
do: {module, true},
632-
into: %{}
624+
removed =
625+
for {module, _} <- old_exports,
626+
not is_map_key(new_exports, module),
627+
do: {module, true},
628+
into: %{}
633629

634-
{Map.merge(stale_modules, removed), Map.merge(stale_exports, removed), new_exports}
630+
modules = modules |> Map.merge(dep_modules) |> Map.merge(removed)
631+
exports = Map.merge(exports, removed)
632+
deps_exports = Map.put(deps_exports, app, new_exports)
633+
{modules, exports, deps_exports}
634+
end
635635
end
636636

637637
defp fixpoint_runtime_modules(sources, modules) when modules != %{} do

lib/mix/test/mix/umbrella_test.exs

+2-1
Original file line numberDiff line numberDiff line change
@@ -453,7 +453,8 @@ defmodule Mix.UmbrellaTest do
453453
assert_received {:mix_shell, :info, ["Compiled lib/bar.ex"]}
454454

455455
# Recompiles if export dependency is removed
456-
File.rm!("../foo/lib/foo.ex")
456+
File.write!("../foo/lib/foo.ex", "")
457+
ensure_touched("../foo/lib/foo.ex", "_build/dev/lib/bar/.mix/compile.elixir")
457458
Mix.Task.clear()
458459

459460
ExUnit.CaptureIO.capture_io(:stderr, fn ->

0 commit comments

Comments
 (0)