Skip to content

Commit afaf889

Browse files
maennchenjosevalim
authored andcommitted
Follow XDG base dir specification in Mix (#8933)
1 parent e436fa7 commit afaf889

File tree

4 files changed

+79
-4
lines changed

4 files changed

+79
-4
lines changed

lib/mix/lib/mix/cli.ex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ defmodule Mix.CLI do
125125
end
126126

127127
defp load_dot_config do
128-
path = Path.join(Mix.Utils.mix_home(), "config.exs")
128+
path = Path.join(Mix.Utils.mix_config_home(), "config.exs")
129129

130130
if File.regular?(path) do
131131
Mix.Task.run("loadconfig", [path])

lib/mix/lib/mix/utils.ex

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ defmodule Mix.Utils do
44
@doc """
55
Gets the Mix home.
66
7-
It defaults to `~/.mix` unless the `MIX_HOME`
8-
environment variable is set.
7+
It uses the the locations `MIX_HOME`, `XDG_DATA_HOME/mix`,
8+
`~/.mix` with decreasing priority.
99
1010
Developers should only store entries in the
1111
`MIX_HOME` directory which are guaranteed to
@@ -15,7 +15,29 @@ defmodule Mix.Utils do
1515
stored there.
1616
"""
1717
def mix_home do
18-
System.get_env("MIX_HOME") || Path.expand("~/.mix")
18+
case {System.get_env("MIX_HOME"), System.get_env("XDG_DATA_HOME")} do
19+
{directory, _} when is_binary(directory) -> directory
20+
{nil, directory} when is_binary(directory) -> :filename.basedir(:user_data, "mix")
21+
{nil, nil} -> Path.expand("~/.mix")
22+
end
23+
end
24+
25+
@doc """
26+
Gets possible location of global Mix configuration.
27+
28+
Possible locations:
29+
30+
* `~/.mix`
31+
* `MIX_HOME`
32+
* `XDG_CONFIG_HOME/mix`
33+
34+
"""
35+
def mix_config_home do
36+
case {System.get_env("MIX_HOME"), System.get_env("XDG_CONFIG_HOME")} do
37+
{directory, _} when is_binary(directory) -> directory
38+
{nil, directory} when is_binary(directory) -> :filename.basedir(:user_config, "mix")
39+
{nil, nil} -> Path.expand("~/.mix")
40+
end
1941
end
2042

2143
@doc """

lib/mix/test/mix/utils_test.exs

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,23 @@ defmodule Mix.UtilsTest do
77
use MixTest.Case
88
doctest Mix.Utils
99

10+
setup do
11+
# Store state before test
12+
mix_home = System.get_env("MIX_HOME")
13+
14+
# Clear all variables to get a reproducible test
15+
System.delete_env("MIX_HOME")
16+
System.delete_env("XDG_DATA_HOME")
17+
System.delete_env("XDG_CONFIG_HOME")
18+
19+
# Reset Env Variables
20+
on_exit(fn ->
21+
System.put_env("MIX_HOME", mix_home)
22+
System.delete_env("XDG_DATA_HOME")
23+
System.delete_env("XDG_CONFIG_HOME")
24+
end)
25+
end
26+
1027
test "command to module" do
1128
assert Mix.Utils.command_to_module("cheers", Mix.Tasks) == {:module, Mix.Tasks.Cheers}
1229
assert Mix.Utils.command_to_module("unknown", Mix.Tasks) == {:error, :nofile}
@@ -103,6 +120,40 @@ defmodule Mix.UtilsTest do
103120
Mix.Utils.read_path("http://10.0.0.0/", timeout: 0)
104121
end
105122

123+
describe "mix_home/0" do
124+
test "prefers MIX_HOME over XDG_DATA_HOME" do
125+
System.put_env("MIX_HOME", "mix_home")
126+
System.put_env("XDG_DATA_HOME", "xdg_data_home")
127+
assert "mix_home" = Mix.Utils.mix_home()
128+
end
129+
130+
test "falls back to XDG_DATA_HOME/mix" do
131+
System.put_env("XDG_DATA_HOME", "xdg_data_home")
132+
assert :filename.basedir(:user_data, "mix") == Mix.Utils.mix_home()
133+
end
134+
135+
test "falls back to $HOME/.mix" do
136+
assert Path.expand("~/.mix") == Mix.Utils.mix_home()
137+
end
138+
end
139+
140+
describe "mix_config_home/0" do
141+
test "prefers MIX_HOME over XDG_CONFIG_HOME" do
142+
System.put_env("MIX_HOME", "mix_home")
143+
System.put_env("XDG_CONFIG_HOME", "xdg_data_home")
144+
assert "mix_home" = Mix.Utils.mix_config_home()
145+
end
146+
147+
test "falls back to XDG_CONFIG_HOME/mix" do
148+
System.put_env("XDG_CONFIG_HOME", "xdg_config_home")
149+
assert :filename.basedir(:user_config, "mix") == Mix.Utils.mix_config_home()
150+
end
151+
152+
test "falls back to $HOME/.mix" do
153+
assert Path.expand("~/.mix") == Mix.Utils.mix_config_home()
154+
end
155+
end
156+
106157
defp assert_ebin_symlinked_or_copied(result) do
107158
case result do
108159
{:ok, paths} ->

lib/mix/test/test_helper.exs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,8 @@ end
185185
home = MixTest.Case.tmp_path(".mix")
186186
File.mkdir_p!(home)
187187
System.put_env("MIX_HOME", home)
188+
System.delete_env("XDG_DATA_HOME")
189+
System.delete_env("XDG_CONFIG_HOME")
188190

189191
rebar = System.get_env("REBAR") || Path.expand("fixtures/rebar", __DIR__)
190192
File.cp!(rebar, Path.join(home, "rebar"))

0 commit comments

Comments
 (0)