Skip to content

Commit 5dacce4

Browse files
authored
fix: let the system figure out the elixir version for the project (#162)
* fix: let the system figure out the elixir version for the project * fix: use GenLSP logger
1 parent 555b6b6 commit 5dacce4

File tree

2 files changed

+18
-107
lines changed

2 files changed

+18
-107
lines changed

apps/expert/lib/expert/engine_node.ex

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -171,8 +171,12 @@ 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+
lsp = Expert.get_lsp()
175+
project_name = Project.name(project)
174176
{:ok, elixir, env} = Expert.Port.elixir_executable(project)
175177

178+
GenLSP.info(lsp, "Found elixir for #{project_name} at #{elixir}")
179+
176180
expert_priv = :code.priv_dir(:expert)
177181
packaged_engine_source = Path.join([expert_priv, "engine_source", "apps", "engine"])
178182

@@ -200,12 +204,9 @@ defmodule Expert.EngineNode do
200204

201205
launcher = Expert.Port.path()
202206

203-
GenLSP.info(
204-
Expert.get_lsp(),
205-
"Finding or building engine for project #{Project.name(project)}"
206-
)
207+
GenLSP.info(lsp, "Finding or building engine for project #{project_name}")
207208

208-
with_progress(project, "Building engine for #{Project.name(project)}", fn ->
209+
with_progress(project, "Building engine for #{project_name}", fn ->
209210
port =
210211
Port.open(
211212
{:spawn_executable, launcher},

apps/expert/lib/expert/port.ex

Lines changed: 12 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -34,113 +34,23 @@ defmodule Expert.Port do
3434
def elixir_executable(%Project{} = project) do
3535
root_path = Project.root_path(project)
3636

37-
{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()}
42-
end
37+
# We run a shell in interactive mode to populate the PATH with the right value
38+
# at the project root. Otherwise, we either can't find an elixir executable,
39+
# we use the wrong version if the user uses a version manager like asdf/mise,
40+
# or we get an incomplete PATH not including erl or any other version manager
41+
# managed programs.
42+
shell = System.get_env("SHELL")
4343

44-
case path_result do
45-
nil ->
46-
{:error, :no_elixir}
47-
48-
executable when is_binary(executable) ->
49-
{:ok, executable, env}
50-
end
51-
end
52-
53-
defp version_manager_path_and_env(manager, root_path) do
54-
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
57-
{String.trim(path), env}
58-
else
59-
_ ->
60-
nil
61-
end
62-
end
63-
64-
# We launch expert by asking the version managers to provide an environment,
65-
# which contains path munging. This initial environment is present in the running
66-
# 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)
44+
{path, 0} = System.cmd(shell, ["-i", "-l", "-c", "cd #{root_path} && echo $PATH"])
45+
elixir = :os.find_executable(~c"elixir", to_charlist(path))
6946

7047
env =
71-
env
72-
|> String.trim()
73-
|> String.split("\n")
74-
|> Enum.map(fn key_and_value ->
75-
[key, value] =
76-
key_and_value
77-
|> String.split("=", parts: 2)
78-
|> Enum.map(&String.trim/1)
79-
80-
{key, value}
48+
Enum.map(System.get_env(), fn
49+
{"PATH", _path} -> {"PATH", path}
50+
other -> other
8151
end)
82-
|> Enum.reject(&is_nil/1)
8352

84-
asdf_path =
85-
case List.keyfind(env, "ASDF_INSTALL_PATH", 0) do
86-
{_, path} -> Path.join(path, "../../../shims")
87-
_ -> ""
88-
end
89-
90-
Enum.map(System.get_env(), fn
91-
{"PATH", path} -> {"PATH", "#{asdf_path}:#{path}"}
92-
other -> other
93-
end)
94-
end
95-
96-
defp reset_env("rtx", root_path) do
97-
{env, _} = System.cmd("rtx", ~w(env -s bash), cd: root_path)
98-
99-
env
100-
|> String.trim()
101-
|> String.split("\n")
102-
|> Enum.map(fn
103-
"export " <> key_and_value ->
104-
[key, value] =
105-
key_and_value
106-
|> String.split("=", parts: 2)
107-
|> Enum.map(&String.trim/1)
108-
|> then(fn
109-
["PATH", path] -> ["PATH", String.trim(path, "'")]
110-
other -> other
111-
end)
112-
113-
{key, value}
114-
115-
_ ->
116-
nil
117-
end)
118-
|> Enum.reject(&is_nil/1)
119-
end
120-
121-
defp reset_env("mise", root_path) do
122-
{env, _} = System.cmd("mise", ~w(env -s bash), cd: root_path)
123-
124-
env
125-
|> String.trim()
126-
|> String.split("\n")
127-
|> Enum.map(fn
128-
"export " <> key_and_value ->
129-
[key, value] =
130-
key_and_value
131-
|> String.split("=", parts: 2)
132-
|> Enum.map(&String.trim/1)
133-
|> then(fn
134-
["PATH", path] -> ["PATH", String.trim(path, "'")]
135-
other -> other
136-
end)
137-
138-
{key, value}
139-
140-
_ ->
141-
nil
142-
end)
143-
|> Enum.reject(&is_nil/1)
53+
{:ok, elixir, env}
14454
end
14555

14656
@doc """

0 commit comments

Comments
 (0)