Просмотр исходного кода

Rebar agent reloads the config file on every run

This allows proper checking of new configurations, deps, or plugins, and
makes sure they are detected during an active shell session.
pull/473/head
Fred Hebert 10 лет назад
Родитель
Сommit
3de325aa49
2 измененных файлов: 68 добавлений и 35 удалений
  1. +67
    -34
      src/rebar_agent.erl
  2. +1
    -1
      src/rebar_prv_shell.erl

+ 67
- 34
src/rebar_agent.erl Просмотреть файл

@ -4,6 +4,8 @@
handle_call/3, handle_cast/2, handle_info/2,
code_change/3, terminate/2]).
-include("rebar.hrl").
-record(state, {state,
cwd}).
@ -16,39 +18,16 @@ do(Command) when is_atom(Command) ->
do(Namespace, Command) when is_atom(Namespace), is_atom(Command) ->
gen_server:call(?MODULE, {cmd, Namespace, Command}, infinity).
init(State0) ->
Cwd = file:get_cwd(),
State = rebar_state:update_code_paths(State0, default, code:get_path()),
init(State) ->
{ok, Cwd} = file:get_cwd(),
{ok, #state{state=State, cwd=Cwd}}.
handle_call({cmd, Command}, _From, State=#state{state=RState, cwd=Cwd}) ->
Res = try
case file:get_cwd() of
Cwd ->
case rebar_core:process_command(RState, Command) of
{ok, _} ->
refresh(RState),
ok;
{error, Err} when is_list(Err) ->
refresh(RState),
{error, lists:flatten(Err)};
{error, Err} ->
refresh(RState),
{error, Err}
end;
_ ->
{error, cwd_changed}
end
catch
Type:Reason ->
{error, {Type, Reason}}
end,
{reply, Res, State};
handle_call({cmd, Namespace, Command}, From, State = #state{state=RState}) ->
{reply, Res, _} = handle_call({cmd, Command}, From, State#state{
state = rebar_state:namespace(RState, Namespace)
}),
{reply, Res, State};
{Res, NewRState} = run(default, Command, RState, Cwd),
{reply, Res, State#state{state=NewRState}};
handle_call({cmd, Namespace, Command}, _From, State = #state{state=RState, cwd=Cwd}) ->
{Res, NewRState} = run(Namespace, Command, RState, Cwd),
{reply, Res, State#state{state=NewRState}};
handle_call(_Call, _From, State) ->
{noreply, State}.
@ -64,8 +43,62 @@ code_change(_OldVsn, State, _Extra) ->
terminate(_Reason, _State) ->
ok.
refresh(RState) ->
ToRefresh = rebar_state:code_paths(RState, all_deps)
run(Namespace, Command, RState, Cwd) ->
try
case file:get_cwd() of
{ok, Cwd} ->
Args = [atom_to_list(Namespace), atom_to_list(Command)],
CmdState0 = refresh_state(RState, Cwd),
CmdState1 = rebar_state:set(CmdState0, task, atom_to_list(Command)),
CmdState = rebar_state:set(CmdState1, caller, api),
case rebar3:run(CmdState, Args) of
{ok, TmpState} ->
refresh_paths(TmpState),
{ok, CmdState};
{error, Err} when is_list(Err) ->
refresh_paths(CmdState),
{{error, lists:flatten(Err)}, CmdState};
{error, Err} ->
refresh_paths(CmdState),
{{error, Err}, CmdState}
end;
_ ->
{{error, cwd_changed}, RState}
end
catch
Type:Reason ->
?DEBUG("Agent Stacktrace: ~p", [erlang:get_stacktrace()]),
{{error, {Type, Reason}}, RState}
end.
refresh_paths(RState) ->
ToRefresh = (rebar_state:code_paths(RState, all_deps)
%% TODO: add plugin paths here when the other change is merged
++ [filename:join([rebar_app_info:out_dir(App), "test"])
|| App <- rebar_state:project_apps(RState)]
%% make sure to never reload self; halt()s the VM
-- [filename:dirname(code:which(?MODULE))],
rebar_utils:update_code(ToRefresh).
) -- [filename:dirname(code:which(?MODULE))],
%% Similar to rebar_utils:update_code/1, but also forces a reload
%% of used modules.
lists:foreach(fun(Path) ->
Name = filename:basename(Path, "/ebin"),
App = list_to_atom(Name),
application:load(App),
case application:get_key(App, modules) of
undefined ->
code:add_patha(Path),
ok;
{ok, Modules} ->
?DEBUG("reloading ~p from ~s", [Modules, Path]),
code:replace_path(Name, Path),
[begin code:purge(M), code:delete(M), code:load_file(M) end
|| M <- Modules]
end
end, ToRefresh).
refresh_state(RState, _Dir) ->
lists:foldl(
fun(F, State) -> F(State) end,
rebar3:init_config(),
[fun(S) -> rebar_state:current_profiles(S, rebar_state:current_profiles(RState)) end]
).

+ 1
- 1
src/rebar_prv_shell.erl Просмотреть файл

@ -82,8 +82,8 @@ shell(State) ->
setup_paths(State),
ok = reread_config(State),
maybe_boot_apps(State),
rebar_agent:start_link(State),
setup_shell(),
rebar_agent:start_link(State),
%% try to read in sys.config file
%% this call never returns (until user quits shell)
timer:sleep(infinity).

Загрузка…
Отмена
Сохранить