diff options
author | Fred Hebert <mononcqc@ferd.ca> | 2015-05-26 01:07:02 +0000 |
---|---|---|
committer | Fred Hebert <mononcqc@ferd.ca> | 2015-05-26 01:17:54 +0000 |
commit | 51e822e54cf862e3026d23a1f9e74797c4e7f9eb (patch) | |
tree | 059e2061d3dee620591a7bc0d592c5d41521d335 /src | |
parent | fb160ebf718364e8cb4edd4ead9ebf097024c037 (diff) |
Add a shell agent
The shell agent allows to run rebar3 commands and autoload compiled
modules when that is done.
Diffstat (limited to 'src')
-rw-r--r-- | src/r3.erl | 7 | ||||
-rw-r--r-- | src/rebar_agent.erl | 71 | ||||
-rw-r--r-- | src/rebar_prv_shell.erl | 24 |
3 files changed, 92 insertions, 10 deletions
diff --git a/src/r3.erl b/src/r3.erl new file mode 100644 index 0000000..5e8b26d --- /dev/null +++ b/src/r3.erl @@ -0,0 +1,7 @@ +%%% external alias for rebar_agent +-module(r3). +-export([do/1, do/2]). + +do(Command) -> rebar_agent:do(Command). + +do(Namespace, Command) -> rebar_agent:do(Namespace, Command). diff --git a/src/rebar_agent.erl b/src/rebar_agent.erl new file mode 100644 index 0000000..849e67c --- /dev/null +++ b/src/rebar_agent.erl @@ -0,0 +1,71 @@ +-module(rebar_agent). +-export([start_link/1, do/1, do/2]). +-export([init/1, + handle_call/3, handle_cast/2, handle_info/2, + code_change/3, terminate/2]). + +-record(state, {state, + cwd}). + +start_link(State) -> + gen_server:start_link({local, ?MODULE}, ?MODULE, State, []). + +do(Command) when is_atom(Command) -> + gen_server:call(?MODULE, {cmd, Command}, infinity). + +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()), + {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}; +handle_call(_Call, _From, State) -> + {noreply, State}. + +handle_cast(_Cast, State) -> + {noreply, State}. + +handle_info(_Info, State) -> + {noreply, State}. + +code_change(_OldVsn, State, _Extra) -> + {ok, State}. + +terminate(_Reason, _State) -> + ok. + +refresh(RState) -> + ToRefresh = rebar_state:code_paths(RState, all_deps) + %% make sure to never reload self; halt()s the VM + -- [filename:dirname(code:which(?MODULE))], + rebar_utils:update_code(ToRefresh). diff --git a/src/rebar_prv_shell.erl b/src/rebar_prv_shell.erl index cf600e9..143becc 100644 --- a/src/rebar_prv_shell.erl +++ b/src/rebar_prv_shell.erl @@ -82,6 +82,7 @@ shell(State) -> setup_paths(State), ok = reread_config(State), maybe_boot_apps(State), + rebar_agent:start_link(State), setup_shell(), %% try to read in sys.config file %% this call never returns (until user quits shell) @@ -134,18 +135,21 @@ maybe_boot_apps(State) -> undefined -> ok; Apps -> - ?WARN("The rebar3 shell is a development tool; to deploy " - "applications in production, consider using releases " - "(http://www.rebar3.org/v3.0/docs/releases)", []), - Res = [application:ensure_all_started(App) || App <- Apps], - _ = [?INFO("Booted ~p", [App]) - || {ok, Booted} <- Res, - App <- Booted], - _ = [?ERROR("Failed to boot ~p for reason ~p", [App, Reason]) - || {error, {App, Reason}} <- Res], - ok + boot_apps(Apps) end. +boot_apps(Apps) -> + ?WARN("The rebar3 shell is a development tool; to deploy " + "applications in production, consider using releases " + "(http://www.rebar3.org/v3.0/docs/releases)", []), + Res = [application:ensure_all_started(App) || App <- Apps], + _ = [?INFO("Booted ~p", [App]) + || {ok, Booted} <- Res, + App <- Booted], + _ = [?ERROR("Failed to boot ~p for reason ~p", [App, Reason]) + || {error, {App, Reason}} <- Res], + ok. + remove_error_handler(0) -> ?WARN("Unable to remove simple error_logger handler", []); remove_error_handler(N) -> |