@@ -32,36 +32,28 @@ 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
4335 root_path = Project . root_path ( project )
4436
4537 { path_result , 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 ( ) }
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 ( ) }
5042 end
5143
5244 case path_result do
5345 nil ->
54- { :error , :" #{ exe } _not_found" }
46+ { :error , :no_elixir }
5547
5648 executable when is_binary ( executable ) ->
5749 { :ok , executable , env }
5850 end
5951 end
6052
61- defp version_manager_path_and_env ( manager , exe , root_path ) do
53+ defp version_manager_path_and_env ( manager , root_path ) do
6254 with true <- is_binary ( System . find_executable ( manager ) ) ,
63- env = reset_env ( manager , exe , root_path ) ,
64- { path , 0 } <- System . cmd ( manager , [ " which" , exe ] , cd: root_path , env: env ) do
55+ env = reset_env ( manager , root_path ) ,
56+ { path , 0 } <- System . cmd ( manager , ~w ( which elixir ) , cd: root_path , env: env ) do
6557 { String . trim ( path ) , env }
6658 else
6759 _ ->
@@ -72,36 +64,26 @@ defmodule Expert.Port do
7264 # We launch expert by asking the version managers to provide an environment,
7365 # which contains path munging. This initial environment is present in the running
7466 # VM, and needs to be undone so we can find the correct elixir executable in the project.
75- defp reset_env ( "asdf" , exe , root_path ) do
76- { env , _ } = System . cmd ( "asdf" , [ "env" , exe ] , cd: root_path )
77-
78- env =
79- env
80- |> String . trim ( )
81- |> String . split ( "\n " )
82- |> Enum . map ( fn key_and_value ->
83- [ key , value ] =
84- key_and_value
85- |> String . split ( "=" , parts: 2 )
86- |> Enum . map ( & String . trim / 1 )
67+ defp reset_env ( "asdf" , root_path ) do
68+ data_dir = System . get_env ( "ASDF_DATA_DIR" ) || Path . join ( System . user_home! ( ) , ".asdf" )
69+ installs_dir = Path . join ( data_dir , "installs" )
8770
88- { key , value }
89- end )
90- |> Enum . reject ( & is_nil / 1 )
71+ { current , 0 } = System . cmd ( "asdf" , [ "list" ] , cd: root_path )
9172
92- asdf_path =
93- case List . keyfind ( env , "ASDF_INSTALL_PATH" , 0 ) do
94- { _ , path } -> Path . join ( path , "../../../shims" )
95- _ -> ""
96- end
73+ versions = parse_asdf_installed_versions ( current , % { } )
74+
75+ installed_bin_paths =
76+ versions
77+ |> Enum . map ( fn { tool , version } -> Path . join ( [ installs_dir , tool , version , "bin" ] ) end )
78+ |> Enum . join ( ":" )
9779
9880 Enum . map ( System . get_env ( ) , fn
99- { "PATH" , path } -> { "PATH" , "#{ asdf_path } :#{ path } " }
81+ { "PATH" , path } -> { "PATH" , "#{ installed_bin_paths } :#{ path } " }
10082 other -> other
10183 end )
10284 end
10385
104- defp reset_env ( "rtx" , _exe , root_path ) do
86+ defp reset_env ( "rtx" , root_path ) do
10587 { env , _ } = System . cmd ( "rtx" , ~w( env -s bash) , cd: root_path )
10688
10789 env
@@ -126,7 +108,7 @@ defmodule Expert.Port do
126108 |> Enum . reject ( & is_nil / 1 )
127109 end
128110
129- defp reset_env ( "mise" , _exe , root_path ) do
111+ defp reset_env ( "mise" , root_path ) do
130112 { env , _ } = System . cmd ( "mise" , ~w( env -s bash) , cd: root_path )
131113
132114 env
@@ -151,6 +133,39 @@ defmodule Expert.Port do
151133 |> Enum . reject ( & is_nil / 1 )
152134 end
153135
136+ defp parse_asdf_installed_versions ( output , acc ) when is_binary ( output ) do
137+ output
138+ |> String . split ( "\n " , trim: true )
139+ |> parse_asdf_installed_versions ( acc )
140+ end
141+
142+ defp parse_asdf_installed_versions ( [ ] , acc ) , do: acc
143+
144+ defp parse_asdf_installed_versions ( [ line | rest ] , acc ) do
145+ tool_fn? = & ( not String . starts_with? ( & 1 , " " ) )
146+
147+ case tool_fn? . ( line ) do
148+ true ->
149+ { versions , rest } = Enum . split_while ( rest , & ( not tool_fn? . ( & 1 ) ) )
150+ versions = Enum . map ( versions , & String . trim / 1 )
151+ version = Enum . find ( versions , & String . starts_with? ( & 1 , "*" ) )
152+
153+ case version do
154+ nil ->
155+ parse_asdf_installed_versions ( rest , acc )
156+
157+ version when is_binary ( version ) ->
158+ version = String . trim ( version , "*" )
159+ acc = Map . put ( acc , line , version )
160+
161+ parse_asdf_installed_versions ( rest , acc )
162+ end
163+
164+ false ->
165+ parse_asdf_installed_versions ( rest , acc )
166+ end
167+ end
168+
154169 @ doc """
155170 Launches an executable in the project context via a port.
156171 """
0 commit comments