소스 검색

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 년 전
부모
커밋
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).

불러오는 중...
취소
저장