Skip to content
Merged
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
79 changes: 58 additions & 21 deletions apps/expert/lib/expert/port.ex
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,10 @@ defmodule Expert.Port do

path =
if shell_available?(shell_env) do
path_env_at_directory(root_path, shell_env)
case path_env_at_directory(root_path, shell_env) do
{:ok, path} -> path
{:error, :timeout} -> filter_release_root_from_path()
end
else
filter_release_root_from_path()
end
Expand Down Expand Up @@ -260,35 +263,69 @@ defmodule Expert.Port do
{"PATH", System.get_env("PATH", @default_unix_path)}
]

shell_name = Path.basename(shell)
args = path_fetch_cmd_args(shell, directory)

maybe_cmd_output =
case cmd_with_timeout(shell, args, env, 1_000) do
{:ok, result} ->
{:ok, result}

{:error, :timeout} ->
if Enum.member?(args, "-i") do
# If the command contained the -i flag, try again without it.
# Some users have exec calls or blocking prompts in their .bashrc,
# so we would hang here without the timeout
args = Enum.reject(args, &(&1 == "-i"))
cmd_with_timeout(shell, args, env, 1_000)
else
{:error, :timeout}
end
end

args =
case shell_name do
"fish" ->
cmd =
"cd #{directory}; printf \"#{@path_marker}:%s:#{@path_marker}\" (string join ':' $PATH)"
case maybe_cmd_output do
{:ok, {output, exit_code}} ->
case Regex.run(~r/#{@path_marker}:(.*?):#{@path_marker}/s, output) do
[_, clean_path] when exit_code == 0 ->
{:ok, clean_path}

["-l", "-c", cmd]
_ ->
{:ok, output |> String.trim() |> String.split("\n") |> List.last()}
end

"nu" ->
cmd =
"cd #{directory}; print $\"#{@path_marker}:($env.PATH | str join \":\"):#{@path_marker}\""
{:error, :timeout} ->
{:error, :timeout}
end
end

["-l", "-c", cmd]
defp path_fetch_cmd_args(shell, directory) do
case Path.basename(shell) do
"fish" ->
cmd =
"cd #{directory}; printf \"#{@path_marker}:%s:#{@path_marker}\" (string join ':' $PATH)"

_ ->
cmd = "cd #{directory} && printf \"#{@path_marker}:%s:#{@path_marker}\" \"$PATH\""
["-i", "-l", "-c", cmd]
end
["-l", "-c", cmd]

"nu" ->
cmd =
"cd #{directory}; print $\"#{@path_marker}:($env.PATH | str join \":\"):#{@path_marker}\""

["-l", "-c", cmd]

_ ->
cmd = "cd #{directory} && printf \"#{@path_marker}:%s:#{@path_marker}\" \"$PATH\""
["-i", "-l", "-c", cmd]
end
end

{output, exit_code} = System.cmd(shell, args, env: env)
defp cmd_with_timeout(shell, args, env, timeout) do
task = Task.async(fn -> System.cmd(shell, args, env: env) end)

case Regex.run(~r/#{@path_marker}:(.*?):#{@path_marker}/s, output) do
[_, clean_path] when exit_code == 0 ->
clean_path
case Task.yield(task, timeout) || Task.shutdown(task) do
{:ok, result} ->
{:ok, result}

_ ->
output |> String.trim() |> String.split("\n") |> List.last()
{:error, :timeout}
end
end

Expand Down
Loading