Skip to content

Commit 1d7a746

Browse files
authored
Add MIX_INSTALL_DIR and use it in Mix.install/2 (#10825)
1 parent 077b711 commit 1d7a746

File tree

6 files changed

+56
-15
lines changed

6 files changed

+56
-15
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ IO.puts Jason.encode!(%{hello: :world})
1515

1616
`Mix.install/2` also performs protocol consolidation, which gives script developers an option to execute their code in the most performant format possible.
1717

18+
**Note:** `Mix.install/2` is currently experimental and it may change in future releases.
19+
1820
Another improvement to scripting is the ability to trap exit signals via `System.trap_signal/3`. All you need is the signal name and a callback that will be invoked when the signal triggers. For example, ExUnit leverages this functionality to print all currently running tests when you abort the test suite via SIGQUIT (`Ctrl+\\ `):
1921

2022
```

lib/mix/lib/mix.ex

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,8 @@ defmodule Mix do
251251
* `MIX_EXS` - changes the full path to the `mix.exs` file
252252
* `MIX_HOME` - path to Mix's home directory, stores configuration files and scripts used by Mix
253253
(default: `~/.mix`)
254+
* `MIX_INSTALL_DIR` - (since v1.12.0) specifies directory where `Mix.install/2` keeps
255+
installs cache
254256
* `MIX_PATH` - appends extra code paths
255257
* `MIX_QUIET` - does not print information messages to the terminal
256258
* `MIX_REBAR` - path to rebar command that overrides the one Mix installs
@@ -470,12 +472,13 @@ defmodule Mix do
470472
471473
The given `deps` should be in the same format as defined in a regular Mix
472474
project. See `mix help deps` for more information. As a shortcut, an atom
473-
can be given as dependency to mean the latest version, e.g.: specifying
474-
`:decimal` is the same as `{:decimal, ">= 0.0.0"}`.
475+
can be given as dependency to mean the latest version. In other words,
476+
specifying `:decimal` is the same as `{:decimal, ">= 0.0.0"}`.
475477
476478
After each successful installation, a given set of dependencies is cached
477-
so starting another VM and calling `Mix.install` with the same dependencies
478-
will avoid unnecessary downloads and compilations.
479+
so starting another VM and calling `Mix.install/2` with the same dependencies
480+
will avoid unnecessary downloads and compilations. The location of the cache
481+
directory can be controlled using the `MIX_INSTALL_DIR` environment variable.
479482
480483
This function can only be called outside of a Mix project and only once in a
481484
given VM.
@@ -517,10 +520,13 @@ defmodule Mix do
517520
Mix.raise("Mix.install/2 can only be called once")
518521
end
519522

523+
installs_root =
524+
System.get_env("MIX_INSTALL_DIR") ||
525+
Path.join(Mix.Utils.mix_cache(), "installs")
526+
520527
id = deps |> :erlang.term_to_binary() |> :erlang.md5() |> Base.encode16(case: :lower)
521-
tmp_dir = System.tmp_dir()
522528
version = "elixir-#{System.version()}-erts-#{:erlang.system_info(:version)}"
523-
dir = Path.join([tmp_dir, "mix_installs", version, id])
529+
dir = Path.join([installs_root, version, id])
524530

525531
if opts[:verbose] do
526532
Mix.shell().info("using #{dir}")

lib/mix/lib/mix/utils.ex

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,24 @@ defmodule Mix.Utils do
3232
mix_home_xdg_lookup(:user_config)
3333
end
3434

35+
@doc """
36+
Gets possible location of Mix cache.
37+
38+
Possible locations:
39+
40+
* `XDG_CACHE_HOME/mix` (if `MIX_XDG` is set)
41+
* `:filename.basedir(:user_cache, "mix")`
42+
43+
"""
44+
def mix_cache do
45+
if System.get_env("MIX_XDG") in ["1", "true"] do
46+
# XDG lookups are only done for linux OS
47+
:filename.basedir(:user_cache, "mix", %{os: :linux})
48+
else
49+
:filename.basedir(:user_cache, "mix")
50+
end
51+
end
52+
3553
defp mix_home_xdg_lookup(xdg) do
3654
cond do
3755
dir = System.get_env("MIX_HOME") ->

lib/mix/test/mix/utils_test.exs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ defmodule Mix.UtilsTest do
129129
end
130130

131131
@tag :unix
132-
test "falls back to XDG_DATA_HOME/mix" do
132+
test "falls back to XDG_DATA_HOME/mix when MIX_XDG is set" do
133133
System.put_env("MIX_XDG", "1")
134134
assert Mix.Utils.mix_home() == :filename.basedir(:user_data, "mix", %{os: :linux})
135135
end
@@ -147,7 +147,7 @@ defmodule Mix.UtilsTest do
147147
end
148148

149149
@tag :unix
150-
test "falls back to XDG_CONFIG_HOME/mix" do
150+
test "falls back to XDG_CONFIG_HOME/mix when MIX_XDG is set" do
151151
System.put_env("MIX_XDG", "1")
152152
assert Mix.Utils.mix_config() == :filename.basedir(:user_config, "mix", %{os: :linux})
153153
end
@@ -157,6 +157,18 @@ defmodule Mix.UtilsTest do
157157
end
158158
end
159159

160+
describe "mix_cache/0" do
161+
@tag :unix
162+
test "prefers XDG_CACHE_HOME/mix when MIX_XDG is set" do
163+
System.put_env("MIX_XDG", "1")
164+
assert Mix.Utils.mix_cache() == :filename.basedir(:user_cache, "mix", %{os: :linux})
165+
end
166+
167+
test "falls back to user cache dir" do
168+
assert Mix.Utils.mix_cache() == :filename.basedir(:user_cache, "mix")
169+
end
170+
end
171+
160172
defp assert_ebin_symlinked_or_copied(result) do
161173
case result do
162174
{:ok, paths} ->

lib/mix/test/mix_test.exs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,20 @@ defmodule MixTest do
2222

2323
describe "install" do
2424
@describetag :tmp_dir
25+
26+
setup %{tmp_dir: tmp_dir} do
27+
System.put_env("MIX_INSTALL_DIR", Path.join(tmp_dir, "installs"))
28+
end
29+
2530
setup :test_project
2631

2732
test "default options", %{tmp_dir: tmp_dir} do
2833
Mix.install([
2934
{:install_test, path: Path.join(tmp_dir, "install_test")}
3035
])
3136

37+
assert File.dir?(Path.join(tmp_dir, "installs"))
38+
3239
assert Protocol.consolidated?(InstallTest.Protocol)
3340

3441
assert_received {:mix_shell, :info, ["==> install_test"]}

man/mix.1

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -94,13 +94,9 @@ environments
9494
.Pq see above
9595
are not enough to solve the problem.
9696
.It Ev MIX_HOME
97-
Stores configuration files and scripts shared by multiple
98-
.Nm
99-
implementations.
100-
.Pp
101-
See the
102-
.Sy Mix.Utils.mix_home/0
103-
function.
97+
path to Mix's home directory, stores configuration files and scripts used by Mix
98+
.It MIX_INSTALL_DIR
99+
Specifies directory where Mix.install/2 keeps installs cache
104100
.It Ev MIX_PATH
105101
Allows expanding the code path. If the MIX_PATH environment variable has a value which consists of multiple paths, they must be colon-separated
106102
.Pq for Unix-like operating systems

0 commit comments

Comments
 (0)