Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 16 additions & 8 deletions apps/expert/lib/expert/engine_node.ex
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ defmodule Expert.EngineNode do
alias Forge.Project
require Logger

use Expert.Project.Progress.Support

defmodule State do
defstruct [
:project,
Expand Down Expand Up @@ -169,7 +171,7 @@ defmodule Expert.EngineNode do
# Expert release, and we build it on the fly for the project elixir+opt
# versions if it was not built yet.
defp glob_paths(%Project{} = project) do
{:ok, elixir, _} = Expert.Port.elixir_executable(project)
{:ok, elixir, env} = Expert.Port.elixir_executable(project)

expert_priv = :code.priv_dir(:expert)
packaged_engine_source = Path.join([expert_priv, "engine_source", "apps", "engine"])
Expand All @@ -192,20 +194,26 @@ defmodule Expert.EngineNode do
"--vsn",
Expert.vsn()
],
env: Expert.Port.ensure_charlists(env),
cd: engine_source
]

launcher = Expert.Port.path()

Logger.info("Finding or building engine for project #{Project.name(project)}")
GenLSP.info(
Expert.get_lsp(),
"Finding or building engine for project #{Project.name(project)}"
)

port =
Port.open(
{:spawn_executable, launcher},
opts
)
with_progress(project, "Building engine for #{Project.name(project)}", fn ->
port =
Port.open(
{:spawn_executable, launcher},
opts
)

wait_for_engine(port)
wait_for_engine(port)
end)
end

defp wait_for_engine(port) do
Expand Down
30 changes: 24 additions & 6 deletions apps/expert/lib/expert/port.ex
Original file line number Diff line number Diff line change
Expand Up @@ -64,13 +64,31 @@ defmodule Expert.Port do
# We launch expert by asking the version managers to provide an environment,
# which contains path munging. This initial environment is present in the running
# VM, and needs to be undone so we can find the correct elixir executable in the project.
defp reset_env("asdf", _root_path) do
orig_path = System.get_env("PATH_SAVE", System.get_env("PATH"))
defp reset_env("asdf", root_path) do
{env, _} = System.cmd("asdf", ~w(env elixir), cd: root_path)

env =
env
|> String.trim()
|> String.split("\n")
|> Enum.map(fn key_and_value ->
[key, value] =
key_and_value
|> String.split("=", parts: 2)
|> Enum.map(&String.trim/1)

{key, value}
end)
|> Enum.reject(&is_nil/1)

asdf_path =
case List.keyfind(env, "ASDF_INSTALL_PATH", 0) do
{_, path} -> Path.join(path, "../../../shims")
_ -> ""
end

Enum.map(System.get_env(), fn
{"ASDF_ELIXIR_VERSION", _} -> {"ASDF_ELIXIR_VERSION", nil}
{"ASDF_ERLANG_VERSION", _} -> {"ASDF_ERLANG_VERSION", nil}
{"PATH", _} -> {"PATH", orig_path}
{"PATH", path} -> {"PATH", "#{asdf_path}:#{path}"}
other -> other
end)
end
Expand Down Expand Up @@ -169,7 +187,7 @@ defmodule Expert.Port do
raise ArgumentError, "Operating system #{inspect(os_tuple)} is not currently supported"
end

defp ensure_charlists(environment_variables) do
def ensure_charlists(environment_variables) do
Enum.map(environment_variables, fn {key, value} ->
# using to_string ensures nil values won't blow things up
erl_key = key |> to_string() |> String.to_charlist()
Expand Down
Loading