Skip to content

Commit 155a081

Browse files
committed
fix: resolves issue #91
1 parent 0767fb4 commit 155a081

File tree

2 files changed

+88
-12
lines changed

2 files changed

+88
-12
lines changed

apps/expert/lib/expert/engine_node.ex

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,9 +171,11 @@ defmodule Expert.EngineNode do
171171
# Expert release, and we build it on the fly for the project elixir+opt
172172
# versions if it was not built yet.
173173
defp glob_paths(%Project{} = project) do
174+
{:ok, erl, _env} = Expert.Port.erlang_executable(project)
174175
{:ok, elixir, env} = Expert.Port.elixir_executable(project)
175176

176177
expert_priv = :code.priv_dir(:expert)
178+
root_path = Project.root_path(project)
177179
packaged_engine_source = Path.join([expert_priv, "engine_source", "apps", "engine"])
178180

179181
engine_source =
@@ -183,6 +185,8 @@ defmodule Expert.EngineNode do
183185

184186
build_engine_script = Path.join(expert_priv, "build_engine.exs")
185187

188+
:ok = patch_versions_file(root_path, engine_source, erl, elixir)
189+
186190
opts =
187191
[
188192
:stderr_to_stdout,
@@ -238,6 +242,70 @@ defmodule Expert.EngineNode do
238242
|> Path.join("lib/**/ebin")
239243
|> Path.wildcard()
240244
end
245+
246+
defp patch_versions_file(root_path, engine_source, erl, elixir) do
247+
{elixir_version, 0} = System.cmd(elixir, ["--short-version"], cd: root_path)
248+
249+
{erl_version, 0} =
250+
System.cmd(
251+
erl,
252+
[
253+
"-eval",
254+
"{ok, Version} = file:read_file(filename:join([code:root_dir(), \"releases\", erlang:system_info(otp_release), \"OTP_VERSION\"])), io:fwrite(Version), halt().",
255+
"-noshell"
256+
],
257+
cd: root_path
258+
)
259+
260+
versions_path = Path.join([engine_source, ".tool-versions"])
261+
262+
overrides = %{
263+
"elixir" => String.trim(elixir_version),
264+
"erlang" => String.trim(erl_version)
265+
}
266+
267+
with true <- File.exists?(versions_path),
268+
{:ok, versions} <- read_versions(versions_path) do
269+
updated = Map.merge(versions, overrides)
270+
content = versions_to_iodata(updated)
271+
272+
File.write(versions_path, content)
273+
else
274+
false ->
275+
content = versions_to_iodata(overrides)
276+
277+
File.write(versions_path, content)
278+
279+
error ->
280+
error
281+
end
282+
end
283+
284+
defp versions_to_iodata(versions) do
285+
Enum.map(versions, fn {lang, version} -> [lang, " ", version, "\n"] end)
286+
end
287+
288+
defp read_versions(path) do
289+
case File.read(path) do
290+
{:ok, content} ->
291+
versions =
292+
content
293+
|> String.split("\n")
294+
|> Enum.map(&String.trim/1)
295+
|> Enum.reject(&(&1 == ""))
296+
|> Enum.reduce(%{}, fn line, acc ->
297+
case String.split(line) do
298+
[lang, version] -> Map.put(acc, lang, version)
299+
[] -> acc
300+
end
301+
end)
302+
303+
{:ok, versions}
304+
305+
{:error, _reason} = error ->
306+
error
307+
end
308+
end
241309
end
242310

243311
@stop_timeout 1_000

apps/expert/lib/expert/port.ex

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -32,28 +32,36 @@ defmodule Expert.Port do
3232
end
3333

3434
def elixir_executable(%Project{} = project) do
35+
find_executable(project, "elixir")
36+
end
37+
38+
def erlang_executable(%Project{} = project) do
39+
find_executable(project, "erl")
40+
end
41+
42+
defp find_executable(project, exe) do
3543
root_path = Project.root_path(project)
3644

3745
{path_result, env} =
38-
with nil <- version_manager_path_and_env("asdf", root_path),
39-
nil <- version_manager_path_and_env("mise", root_path),
40-
nil <- version_manager_path_and_env("rtx", root_path) do
41-
{File.cd!(root_path, fn -> System.find_executable("elixir") end), System.get_env()}
46+
with nil <- version_manager_path_and_env("asdf", exe, root_path),
47+
nil <- version_manager_path_and_env("mise", exe, root_path),
48+
nil <- version_manager_path_and_env("rtx", exe, root_path) do
49+
{File.cd!(root_path, fn -> System.find_executable(exe) end), System.get_env()}
4250
end
4351

4452
case path_result do
4553
nil ->
46-
{:error, :no_elixir}
54+
{:error, :"#{exe}_not_found"}
4755

4856
executable when is_binary(executable) ->
4957
{:ok, executable, env}
5058
end
5159
end
5260

53-
defp version_manager_path_and_env(manager, root_path) do
61+
defp version_manager_path_and_env(manager, exe, root_path) do
5462
with true <- is_binary(System.find_executable(manager)),
55-
env = reset_env(manager, root_path),
56-
{path, 0} <- System.cmd(manager, ~w(which elixir), cd: root_path, env: env) do
63+
env = reset_env(manager, exe, root_path),
64+
{path, 0} <- System.cmd(manager, ["which", exe], cd: root_path, env: env) do
5765
{String.trim(path), env}
5866
else
5967
_ ->
@@ -64,8 +72,8 @@ defmodule Expert.Port do
6472
# We launch expert by asking the version managers to provide an environment,
6573
# which contains path munging. This initial environment is present in the running
6674
# VM, and needs to be undone so we can find the correct elixir executable in the project.
67-
defp reset_env("asdf", root_path) do
68-
{env, _} = System.cmd("asdf", ~w(env elixir), cd: root_path)
75+
defp reset_env("asdf", exe, root_path) do
76+
{env, _} = System.cmd("asdf", ["env", exe], cd: root_path)
6977

7078
env =
7179
env
@@ -93,7 +101,7 @@ defmodule Expert.Port do
93101
end)
94102
end
95103

96-
defp reset_env("rtx", root_path) do
104+
defp reset_env("rtx", _exe, root_path) do
97105
{env, _} = System.cmd("rtx", ~w(env -s bash), cd: root_path)
98106

99107
env
@@ -118,7 +126,7 @@ defmodule Expert.Port do
118126
|> Enum.reject(&is_nil/1)
119127
end
120128

121-
defp reset_env("mise", root_path) do
129+
defp reset_env("mise", _exe, root_path) do
122130
{env, _} = System.cmd("mise", ~w(env -s bash), cd: root_path)
123131

124132
env

0 commit comments

Comments
 (0)