Skip to content

Commit b026e88

Browse files
author
José Valim
committed
--elixirc-paths should be a subset of project paths
Since the manifest is shared, --elixirc-paths must be a subset as we need to know what to change and what to not change in the manifest file. Signed-off-by: José Valim <[email protected]>
1 parent 597381b commit b026e88

File tree

3 files changed

+53
-31
lines changed

3 files changed

+53
-31
lines changed

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

Lines changed: 35 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@ defmodule Mix.Compilers.Elixir do
1313
in between modules, which helps it recompile only the modules that
1414
have changed at runtime.
1515
"""
16-
def compile(manifest, srcs, exts, dest, force, on_start) do
17-
all = Mix.Utils.extract_files(srcs, exts)
18-
all_entries = read_manifest(manifest)
16+
def compile(manifest, srcs, skip, exts, dest, force, on_start) do
17+
all = Mix.Utils.extract_files(srcs -- skip, exts)
18+
{all_entries, skip_entries} = read_manifest(manifest, skip)
1919

2020
removed =
2121
for {_b, _m, source, _d, _f, _bin} <- all_entries, not(source in all), do: source
@@ -41,15 +41,15 @@ defmodule Mix.Compilers.Elixir do
4141
do: source)
4242
end
4343

44-
{entries, changed} = remove_stale_entries(all_entries, removed ++ changed, [], [])
44+
{entries, changed} = remove_stale_entries(all_entries, removed ++ changed)
4545
stale = changed -- removed
4646

4747
cond do
4848
stale != [] ->
49-
compile_manifest(manifest, entries, stale, dest, on_start)
49+
compile_manifest(manifest, entries ++ skip_entries, stale, dest, on_start)
5050
:ok
5151
removed != [] ->
52-
write_manifest(manifest, entries)
52+
write_manifest(manifest, entries ++ skip_entries)
5353
:ok
5454
true ->
5555
:noop
@@ -102,7 +102,7 @@ defmodule Mix.Compilers.Elixir do
102102
entries
103103
end
104104
after
105-
Agent.stop pid
105+
Agent.stop(pid, :infinity)
106106
end
107107

108108
:ok
@@ -144,7 +144,7 @@ defmodule Mix.Compilers.Elixir do
144144

145145
# This function receives the manifest entries and some source
146146
# files that have changed. It then, recursively, figures out
147-
# all the files that changed (thanks to the dependencies) and
147+
# all the files that changed (via the module dependencies) and
148148
# return their sources as the remaining entries.
149149
defp remove_stale_entries(all, []) do
150150
{all, []}
@@ -181,27 +181,40 @@ defmodule Mix.Compilers.Elixir do
181181

182182
# Reads the manifest returning the results as tuples.
183183
# The beam files are read, removed and stored in memory.
184-
defp read_manifest(manifest) do
184+
defp read_manifest(manifest, skip_paths) do
185+
initial = {[], []}
186+
185187
case File.read(manifest) do
186188
{:ok, contents} ->
187-
Enum.reduce String.split(contents, "\n"), [], fn x, acc ->
188-
case String.split(x, "\t") do
189-
[beam, module, source|deps] ->
190-
{deps, files} =
191-
case Enum.split_while(deps, &(&1 != "Elixir")) do
192-
{deps, ["Elixir"|files]} -> {deps, files}
193-
{deps, _} -> {deps, []}
194-
end
195-
[{beam, module, source, deps, files, nil}|acc]
196-
_ ->
197-
acc
198-
end
189+
skip_paths = Enum.map(skip_paths, &(&1 <> "/"))
190+
Enum.reduce String.split(contents, "\n"), initial, fn x, acc ->
191+
read_manifest_entry(String.split(x, "\t"), acc, skip_paths)
199192
end
200193
{:error, _} ->
201-
[]
194+
initial
202195
end
203196
end
204197

198+
defp read_manifest_entry([beam, module, source|deps], {keep, skip}, skip_paths) do
199+
{deps, files} =
200+
case Enum.split_while(deps, &(&1 != "Elixir")) do
201+
{deps, ["Elixir"|files]} -> {deps, files}
202+
{deps, _} -> {deps, []}
203+
end
204+
205+
entry = {beam, module, source, deps, files, nil}
206+
207+
if String.starts_with?(source, skip_paths) do
208+
{keep, [entry|skip]}
209+
else
210+
{[entry|keep], skip}
211+
end
212+
end
213+
214+
defp read_manifest_entry(_, acc, _skip_paths) do
215+
acc
216+
end
217+
205218
# Writes the manifest separating entries by tabs.
206219
defp write_manifest(_manifest, []) do
207220
:ok

lib/mix/lib/mix/tasks/compile.elixir.ex

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@ defmodule Mix.Tasks.Compile.Elixir do
2222
* `--debug-info` (`--no-debug-info`) - attach (or not) debug info to compiled modules
2323
* `--ignore-module-conflict` - do not emit warnings if a module was previously defined
2424
* `--warnings-as-errors` - treat warnings as errors and return a non-zero exit code
25-
* `--elixirc-paths` - paths to lookup for Elixir source.
26-
Can be given multiple times and, once given, overrides the project elixirc_paths config.
25+
* `--elixirc-paths` - restrict the original elixirc paths to
26+
a subset of the ones specified. Can be given multiple times.
2727
2828
## Configuration
2929
@@ -51,18 +51,20 @@ defmodule Mix.Tasks.Compile.Elixir do
5151

5252
project = Mix.Project.config
5353
dest = Mix.Project.compile_path(project)
54-
srcs = case Keyword.get_values(opts, :elixirc_paths) do
55-
[] -> project[:elixirc_paths]
56-
ep -> ep
57-
end
54+
srcs = project[:elixirc_paths]
55+
skip =
56+
case Keyword.get_values(opts, :elixirc_paths) do
57+
[] -> []
58+
ep -> srcs -- ep
59+
end
5860

5961
manifest = manifest()
6062
configs = Mix.Project.config_files ++ Mix.Tasks.Compile.Erlang.manifests
6163

6264
force = opts[:force] || local_deps_changed?(manifest)
6365
|| Mix.Utils.stale?(configs, [manifest])
6466

65-
Mix.Compilers.Elixir.compile(manifest, srcs, [:ex], dest, force, fn ->
67+
Mix.Compilers.Elixir.compile(manifest, srcs, skip, [:ex], dest, force, fn ->
6668
true = Code.prepend_path(dest)
6769
set_compiler_opts(project, opts, [])
6870
end)

lib/mix/test/mix/tasks/compile.elixir_test.exs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ defmodule Mix.Tasks.Compile.ElixirTest do
173173

174174
defmodule SourcePathsProject do
175175
def project do
176-
[app: :source_paths, elixirc_paths: ["unknown"]]
176+
[app: :source_paths, elixirc_paths: ["web", "lib"]]
177177
end
178178
end
179179

@@ -182,11 +182,18 @@ defmodule Mix.Tasks.Compile.ElixirTest do
182182

183183
in_fixture "no_mixfile", fn ->
184184
# Nothing to compile with the custom source paths
185-
assert Mix.Tasks.Compile.Elixir.run([])
185+
assert Mix.Tasks.Compile.Elixir.run(["--elixirc-paths", "web"])
186186
refute_received {:mix_shell, :info, ["Compiled lib/a.ex"]}
187187

188188
assert Mix.Tasks.Compile.Elixir.run(["--elixirc-paths", "lib"])
189189
assert_received {:mix_shell, :info, ["Compiled lib/a.ex"]}
190+
191+
# Compiling just web does not remove lib artifacts
192+
assert Mix.Tasks.Compile.Elixir.run(["--elixirc-paths", "web"])
193+
refute_received {:mix_shell, :info, ["Compiled lib/a.ex"]}
194+
195+
assert Mix.Tasks.Compile.Elixir.run(["--elixirc-paths", "lib"])
196+
refute_received {:mix_shell, :info, ["Compiled lib/a.ex"]}
190197
end
191198
end
192199
end

0 commit comments

Comments
 (0)