Skip to content

Commit d71de51

Browse files
committed
Allow key-deletions and atom keys in System.put_env/1
1 parent e15388b commit d71de51

File tree

5 files changed

+40
-19
lines changed

5 files changed

+40
-19
lines changed

lib/elixir/lib/system.ex

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -733,11 +733,28 @@ defmodule System do
733733
Sets multiple environment variables.
734734
735735
Sets a new value for each environment variable corresponding
736-
to each `{key, value}` pair in `enum`.
736+
to each `{key, value}` pair in `enum`. Keys are automatically
737+
converted to strings, values are sent as is. `nil` values erase
738+
the given keys.
737739
"""
738740
@spec put_env(Enumerable.t()) :: :ok
739741
def put_env(enum) do
740-
Enum.each(enum, fn {key, val} -> put_env(key, val) end)
742+
Enum.each(enum, fn
743+
{key, nil} ->
744+
:os.unsetenv(to_charlist(key))
745+
746+
{key, val} ->
747+
key = to_charlist(key)
748+
749+
case :string.find(key, "=") do
750+
:nomatch ->
751+
:os.putenv(key, to_charlist(val))
752+
753+
_ ->
754+
raise ArgumentError,
755+
"cannot execute System.put_env/1 for key with \"=\", got: #{inspect(key)}"
756+
end
757+
end)
741758
end
742759

743760
@doc """

lib/elixir/test/elixir/system_test.exs

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ defmodule SystemTest do
5050

5151
@test_var "SYSTEM_ELIXIR_ENV_TEST_VAR"
5252

53-
test "*_env/*" do
53+
test "get_env/put_env/delete_env" do
5454
assert System.get_env(@test_var) == nil
5555
assert System.get_env(@test_var, "SAMPLE") == "SAMPLE"
5656
assert System.fetch_env(@test_var) == :error
@@ -68,14 +68,22 @@ defmodule SystemTest do
6868
System.delete_env(@test_var)
6969
assert System.get_env(@test_var) == nil
7070

71-
System.put_env(%{@test_var => "OTHER_SAMPLE"})
72-
assert System.get_env(@test_var) == "OTHER_SAMPLE"
73-
7471
assert_raise ArgumentError, ~r[cannot execute System.put_env/2 for key with \"=\"], fn ->
7572
System.put_env("FOO=BAR", "BAZ")
7673
end
7774
end
7875

76+
test "put_env/2" do
77+
System.put_env(%{@test_var => "MAP_STRING"})
78+
assert System.get_env(@test_var) == "MAP_STRING"
79+
80+
System.put_env([{String.to_atom(@test_var), "KW_ATOM"}])
81+
assert System.get_env(@test_var) == "KW_ATOM"
82+
83+
System.put_env([{String.to_atom(@test_var), nil}])
84+
assert System.get_env(@test_var) == nil
85+
end
86+
7987
test "cmd/2 raises for null bytes" do
8088
assert_raise ArgumentError, ~r"cannot execute System.cmd/3 for program with null byte", fn ->
8189
System.cmd("null\0byte", [])

lib/mix/lib/mix.ex

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -567,9 +567,8 @@ defmodule Mix do
567567
apps
568568
569569
* `:system_env` (since v1.13.0) - a list or a map of system environment variable
570-
names as binary keys and their respective values as binaries. The system environment
571-
is made part of the `Mix.install/2` cache, so different configurations will lead
572-
to different apps
570+
names with respective values as binaries. The system environment is made part
571+
of the `Mix.install/2` cache, so different configurations will lead to different apps
573572
574573
## Examples
575574
@@ -589,7 +588,7 @@ defmodule Mix do
589588
nx: [default_backend: EXLA]
590589
],
591590
system_env: [
592-
{"XLA_TARGET", "cuda111"}
591+
XLA_TARGET: "cuda111"
593592
]
594593
)
595594

lib/mix/lib/mix/dep/loader.ex

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -61,20 +61,15 @@ defmodule Mix.Dep.Loader do
6161
def with_system_env(%Mix.Dep{system_env: new_env}, callback) do
6262
old_env =
6363
for {key, _} <- new_env do
64+
key = to_string(key)
6465
{key, System.get_env(key)}
6566
end
6667

6768
try do
6869
System.put_env(new_env)
6970
callback.()
7071
after
71-
for {key, value} <- old_env do
72-
if value do
73-
System.put_env(key, value)
74-
else
75-
System.delete_env(key)
76-
end
77-
end
72+
System.put_env(old_env)
7873
end
7974
end
8075

@@ -208,7 +203,7 @@ defmodule Mix.Dep.Loader do
208203
requirement: req,
209204
status: scm_status(scm, opts),
210205
opts: Keyword.put_new(opts, :env, :prod),
211-
system_env: system_env
206+
system_env: Enum.to_list(system_env)
212207
}
213208
end
214209

lib/mix/test/mix_test.exs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,13 +141,15 @@ defmodule MixTest do
141141
{:install_test, path: Path.join(tmp_dir, "install_test")}
142142
],
143143
config: [unknown_app: [foo: :bar]],
144-
system_env: %{"MIX_INSTALL_FOO" => "BAR"}
144+
system_env: %{"MIX_INSTALL_FOO" => "BAR", MIX_INSTALL_BAZ: "BAT"}
145145
)
146146

147147
assert Application.fetch_env!(:unknown_app, :foo) == :bar
148148
assert System.fetch_env!("MIX_INSTALL_FOO") == "BAR"
149+
assert System.fetch_env!("MIX_INSTALL_BAZ") == "BAT"
149150
after
150151
System.delete_env("MIX_INSTALL_FOO")
152+
System.delete_env("MIX_INSTALL_BAZ")
151153
Application.delete_env(:unknown_app, :foo, persistent: true)
152154
end
153155

0 commit comments

Comments
 (0)