From fb160ebf718364e8cb4edd4ead9ebf097024c037 Mon Sep 17 00:00:00 2001 From: Fred Hebert Date: Sat, 23 May 2015 01:31:31 +0000 Subject: Adding app auto-boot to rebar shell - moved path addition, config loading and app boot to before the shell is available - apps successfully booting are in an INFO message, failed to boot into an ERROR message - A warning is printed when apps are booted informing to please use releases for actual deployment, and is omitted otherwise. - Some minor refactorings otherwise. --- src/rebar_prv_shell.erl | 98 +++++++++++++++++++++++++++++++------------------ 1 file changed, 63 insertions(+), 35 deletions(-) (limited to 'src') diff --git a/src/rebar_prv_shell.erl b/src/rebar_prv_shell.erl index 8c0b7ff..cf600e9 100644 --- a/src/rebar_prv_shell.erl +++ b/src/rebar_prv_shell.erl @@ -45,14 +45,21 @@ -spec init(rebar_state:t()) -> {ok, rebar_state:t()}. init(State) -> - State1 = rebar_state:add_provider(State, providers:create([{name, ?PROVIDER}, - {module, ?MODULE}, - {bare, false}, - {deps, ?DEPS}, - {example, "rebar3 shell"}, - {short_desc, "Run shell with project apps and deps in path."}, - {desc, info()}, - {opts, [{config, undefined, "config", string, "Path to the config file to use. Defaults to the sys_config defined for relx, if present."}]}])), + State1 = rebar_state:add_provider( + State, + providers:create([ + {name, ?PROVIDER}, + {module, ?MODULE}, + {bare, false}, + {deps, ?DEPS}, + {example, "rebar3 shell"}, + {short_desc, "Run shell with project apps and deps in path."}, + {desc, info()}, + {opts, [{config, undefined, "config", string, + "Path to the config file to use. Defaults to the " + "sys_config defined for relx, if present."}]} + ]) + ), {ok, State1}. -spec do(rebar_state:t()) -> {ok, rebar_state:t()} | {error, string()}. @@ -72,6 +79,18 @@ format_error(Reason) -> %% immediately kill the script. ctrl-g, however, works fine shell(State) -> + setup_paths(State), + ok = reread_config(State), + maybe_boot_apps(State), + setup_shell(), + %% try to read in sys.config file + %% this call never returns (until user quits shell) + timer:sleep(infinity). + +info() -> + "Start a shell with project and deps preloaded similar to~n'erl -pa ebin -pa deps/*/ebin'.~n". + +setup_shell() -> %% scan all processes for any with references to the old user and save them to %% update later NeedsUpdate = [Pid || Pid <- erlang:processes(), @@ -91,18 +110,41 @@ shell(State) -> %% disable the simple error_logger (which may have been added multiple %% times). removes at most the error_logger added by init and the %% error_logger added by the tty handler - ok = remove_error_handler(3), + ok = remove_error_handler(3). + +setup_paths(State) -> %% Add deps to path code:add_pathsa(rebar_state:code_paths(State, all_deps)), %% add project app test paths - ok = add_test_paths(State), - %% try to read in sys.config file - ok = reread_config(State), - %% this call never returns (until user quits shell) - timer:sleep(infinity). + ok = add_test_paths(State). -info() -> - "Start a shell with project and deps preloaded similar to~n'erl -pa ebin -pa deps/*/ebin'.~n". +reread_config(State) -> + case find_config(State) of + no_config -> + ok; + ConfigList -> + _ = [application:set_env(Application, Key, Val) + || {Application, Items} <- ConfigList, + {Key, Val} <- Items], + ok + end. + +maybe_boot_apps(State) -> + case rebar_state:get(State, shell_apps, undefined) of + 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 + end. remove_error_handler(0) -> ?WARN("Unable to remove simple error_logger handler", []); @@ -124,28 +166,14 @@ wait_until_user_started(Timeout) -> end. add_test_paths(State) -> - lists:foreach(fun(App) -> - AppDir = rebar_app_info:out_dir(App), - %% ignore errors resulting from non-existent directories - _ = code:add_path(filename:join([AppDir, "test"])) - end, rebar_state:project_apps(State)), + _ = [begin + AppDir = rebar_app_info:out_dir(App), + %% ignore errors resulting from non-existent directories + _ = code:add_path(filename:join([AppDir, "test"])) + end || App <- rebar_state:project_apps(State)], _ = code:add_path(filename:join([rebar_dir:base_dir(State), "test"])), ok. -reread_config(State) -> - case find_config(State) of - no_config -> - ok; - ConfigList -> - lists:foreach(fun ({Application, Items}) -> - lists:foreach(fun ({Key, Val}) -> - application:set_env(Application, Key, Val) - end, - Items) - end, - ConfigList) - end. - % First try the --config flag, then try the relx sys_config -spec find_config(rebar_state:t()) -> [tuple()] | no_config. find_config(State) -> -- cgit v1.1 From 51e822e54cf862e3026d23a1f9e74797c4e7f9eb Mon Sep 17 00:00:00 2001 From: Fred Hebert Date: Tue, 26 May 2015 01:07:02 +0000 Subject: Add a shell agent The shell agent allows to run rebar3 commands and autoload compiled modules when that is done. --- src/r3.erl | 7 +++++ src/rebar_agent.erl | 71 +++++++++++++++++++++++++++++++++++++++++++++++++ src/rebar_prv_shell.erl | 24 ++++++++++------- 3 files changed, 92 insertions(+), 10 deletions(-) create mode 100644 src/r3.erl create mode 100644 src/rebar_agent.erl (limited to 'src') 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) -> -- cgit v1.1 From 2fabfe1ee824e3d1d0764e2770309c242ae771d9 Mon Sep 17 00:00:00 2001 From: Fred Hebert Date: Thu, 28 May 2015 02:16:12 +0000 Subject: 'do' returns its final state. While 'do' skips state updates between subcommands so that: rebar3 do a, b == (rebar3 a && rebar3 b) The final state of 'b' does not need to be discarded and might in fact be useful to get when dealing with Rebar3 as an API. This can be done without breaking the equality relation already established. --- src/rebar_prv_do.erl | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src') diff --git a/src/rebar_prv_do.erl b/src/rebar_prv_do.erl index aee3a27..29ef054 100644 --- a/src/rebar_prv_do.erl +++ b/src/rebar_prv_do.erl @@ -47,6 +47,8 @@ do_tasks([{TaskStr, Args}|Tail], State) -> default -> %% The first task we hit might be a namespace! case maybe_namespace(State2, Task, Args) of + {ok, FinalState} when Tail =:= [] -> + {ok, FinalState}; {ok, _} -> do_tasks(Tail, State); {error, Reason} -> @@ -56,6 +58,8 @@ do_tasks([{TaskStr, Args}|Tail], State) -> %% We're already in a non-default namespace, check the %% task directly. case rebar_core:process_command(State2, Task) of + {ok, FinalState} when Tail =:= [] -> + {ok, FinalState}; {ok, _} -> do_tasks(Tail, State); {error, Reason} -> -- cgit v1.1 From 3de325aa497e2b05ada5c84ea75d980d58aba645 Mon Sep 17 00:00:00 2001 From: Fred Hebert Date: Thu, 28 May 2015 02:21:07 +0000 Subject: 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. --- src/rebar_agent.erl | 101 ++++++++++++++++++++++++++++++++---------------- src/rebar_prv_shell.erl | 2 +- 2 files changed, 68 insertions(+), 35 deletions(-) (limited to 'src') diff --git a/src/rebar_agent.erl b/src/rebar_agent.erl index 849e67c..f04afe3 100644 --- a/src/rebar_agent.erl +++ b/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] + ). diff --git a/src/rebar_prv_shell.erl b/src/rebar_prv_shell.erl index 143becc..b5f3cf8 100644 --- a/src/rebar_prv_shell.erl +++ b/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). -- cgit v1.1 From c79eedf2dba5d490988dc59ffe189ba875b750b8 Mon Sep 17 00:00:00 2001 From: Fred Hebert Date: Fri, 29 May 2015 04:14:48 +0000 Subject: Display experimental warning The feature may still be modified in the future. --- src/rebar_agent.erl | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/rebar_agent.erl b/src/rebar_agent.erl index f04afe3..0432fb8 100644 --- a/src/rebar_agent.erl +++ b/src/rebar_agent.erl @@ -7,7 +7,8 @@ -include("rebar.hrl"). -record(state, {state, - cwd}). + cwd, + show_warning=true}). start_link(State) -> gen_server:start_link({local, ?MODULE}, ?MODULE, State, []). @@ -23,11 +24,13 @@ init(State) -> {ok, #state{state=State, cwd=Cwd}}. handle_call({cmd, Command}, _From, State=#state{state=RState, cwd=Cwd}) -> + MidState = maybe_show_warning(State), {Res, NewRState} = run(default, Command, RState, Cwd), - {reply, Res, State#state{state=NewRState}}; + {reply, Res, MidState#state{state=NewRState}}; handle_call({cmd, Namespace, Command}, _From, State = #state{state=RState, cwd=Cwd}) -> + MidState = maybe_show_warning(State), {Res, NewRState} = run(Namespace, Command, RState, Cwd), - {reply, Res, State#state{state=NewRState}}; + {reply, Res, MidState#state{state=NewRState}}; handle_call(_Call, _From, State) -> {noreply, State}. @@ -71,9 +74,14 @@ run(Namespace, Command, RState, Cwd) -> {{error, {Type, Reason}}, RState} end. +maybe_show_warning(S=#state{show_warning=true}) -> + ?WARN("This feature is experimental and may be modified or removed at any time.", []), + S#state{show_warning=false}; +maybe_show_warning(State) -> + State. + 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 -- cgit v1.1 From 2e7eb8f4102900031e2a7cbb28bedf7b0034e392 Mon Sep 17 00:00:00 2001 From: Fred Hebert Date: Fri, 29 May 2015 13:55:36 +0000 Subject: Get prebooted apps to acknowledge sys.config Change the order from load-config -> start-apps to load-apps -> load-config -> start-apps --- src/rebar_prv_shell.erl | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/rebar_prv_shell.erl b/src/rebar_prv_shell.erl index b5f3cf8..9ecadf4 100644 --- a/src/rebar_prv_shell.erl +++ b/src/rebar_prv_shell.erl @@ -80,11 +80,9 @@ format_error(Reason) -> shell(State) -> setup_paths(State), - ok = reread_config(State), maybe_boot_apps(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). @@ -133,11 +131,26 @@ reread_config(State) -> maybe_boot_apps(State) -> case rebar_state:get(State, shell_apps, undefined) of undefined -> - ok; + %% try to read in sys.config file + ok = reread_config(State); Apps -> + %% load apps, then check config, then boot them. + load_apps(Apps), + ok = reread_config(State), boot_apps(Apps) end. +load_apps(Apps) -> + [case application:load(App) of + ok -> + {ok, Ks} = application:get_all_key(App), + load_apps(proplists:get_value(applications, Ks)); + _ -> + error % will be caught when starting the app + end || App <- Apps, + not lists:keymember(App, 1, application:loaded_applications())], + ok. + boot_apps(Apps) -> ?WARN("The rebar3 shell is a development tool; to deploy " "applications in production, consider using releases " -- cgit v1.1 From 398204b13e9b9073e14ce7311be6e54eb1eb956b Mon Sep 17 00:00:00 2001 From: Fred Hebert Date: Fri, 29 May 2015 14:06:49 +0000 Subject: Add support to boot apps from releases in shell Precedence still goes to shell_apps. --- src/rebar_prv_shell.erl | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/rebar_prv_shell.erl b/src/rebar_prv_shell.erl index 9ecadf4..74e2386 100644 --- a/src/rebar_prv_shell.erl +++ b/src/rebar_prv_shell.erl @@ -129,7 +129,7 @@ reread_config(State) -> end. maybe_boot_apps(State) -> - case rebar_state:get(State, shell_apps, undefined) of + case find_apps_to_boot(State) of undefined -> %% try to read in sys.config file ok = reread_config(State); @@ -140,6 +140,19 @@ maybe_boot_apps(State) -> boot_apps(Apps) end. +find_apps_to_boot(State) -> + %% Try the shell_apps option + case rebar_state:get(State, shell_apps, undefined) of + undefined -> + %% Get to the relx tuple instead + case lists:keyfind(release, 1, rebar_state:get(State, relx, [])) of + {_, _, Apps} -> Apps; + false -> undefined + end; + Apps -> + Apps + end. + load_apps(Apps) -> [case application:load(App) of ok -> -- cgit v1.1 From 30847ec66103bdbaa8b7787577677c24d583500f Mon Sep 17 00:00:00 2001 From: Fred Hebert Date: Sat, 30 May 2015 02:48:59 +0000 Subject: Fix config loading in shell Config files from the command line would expect the wrong format: {app1, [...]}. {app2, [...]}. Instead of the correct sys.config format: [{app1, [...]}, {app2, [...]}] Not supported yet: the recursive file references documented in http://www.erlang.org/doc/man/config.html --- src/rebar_prv_shell.erl | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/rebar_prv_shell.erl b/src/rebar_prv_shell.erl index 74e2386..5110f52 100644 --- a/src/rebar_prv_shell.erl +++ b/src/rebar_prv_shell.erl @@ -237,4 +237,7 @@ find_config_relx(State) -> consult_config(State, Filename) -> Fullpath = filename:join(rebar_dir:root_dir(State), Filename), ?DEBUG("Loading configuration from ~p", [Fullpath]), - rebar_file_utils:try_consult(Fullpath). + case rebar_file_utils:try_consult(Fullpath) of + [T] -> T; + [] -> [] + end. -- cgit v1.1 From c87f2a2c73ccdff29c0b320070c5599716b47fca Mon Sep 17 00:00:00 2001 From: Fred Hebert Date: Sat, 30 May 2015 14:50:09 +0000 Subject: Optionally allow node names to the rebar3 shell. Helps with integration efforts, but unfortunately can't support the '-sname' and '-name' options, only '--sname' and '--name'. --- src/rebar_prv_shell.erl | 42 ++++++++++++++++++++++++++++++------------ 1 file changed, 30 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/rebar_prv_shell.erl b/src/rebar_prv_shell.erl index 5110f52..c80badf 100644 --- a/src/rebar_prv_shell.erl +++ b/src/rebar_prv_shell.erl @@ -57,7 +57,11 @@ init(State) -> {desc, info()}, {opts, [{config, undefined, "config", string, "Path to the config file to use. Defaults to the " - "sys_config defined for relx, if present."}]} + "sys_config defined for relx, if present."}, + {name, undefined, "name", atom, + "Gives a long name to the node."}, + {sname, undefined, "sname", atom, + "Gives a short name to the node."}]} ]) ), {ok, State1}. @@ -79,6 +83,7 @@ format_error(Reason) -> %% immediately kill the script. ctrl-g, however, works fine shell(State) -> + setup_name(State), setup_paths(State), maybe_boot_apps(State), setup_shell(), @@ -117,17 +122,6 @@ setup_paths(State) -> %% add project app test paths ok = add_test_paths(State). -reread_config(State) -> - case find_config(State) of - no_config -> - ok; - ConfigList -> - _ = [application:set_env(Application, Key, Val) - || {Application, Items} <- ConfigList, - {Key, Val} <- Items], - ok - end. - maybe_boot_apps(State) -> case find_apps_to_boot(State) of undefined -> @@ -140,6 +134,19 @@ maybe_boot_apps(State) -> boot_apps(Apps) end. +setup_name(State) -> + {Opts, _} = rebar_state:command_parsed_args(State), + case {proplists:get_value(name, Opts), proplists:get_value(sname, Opts)} of + {undefined, undefined} -> + ok; + {Name, undefined} -> + net_kernel:start([Name, longnames]); + {undefined, SName} -> + net_kernel:start([SName, shortnames]); + {_, _} -> + ?ABORT("Cannot have both short and long node names defined", []) + end. + find_apps_to_boot(State) -> %% Try the shell_apps option case rebar_state:get(State, shell_apps, undefined) of @@ -164,6 +171,17 @@ load_apps(Apps) -> not lists:keymember(App, 1, application:loaded_applications())], ok. +reread_config(State) -> + case find_config(State) of + no_config -> + ok; + ConfigList -> + _ = [application:set_env(Application, Key, Val) + || {Application, Items} <- ConfigList, + {Key, Val} <- Items], + ok + end. + boot_apps(Apps) -> ?WARN("The rebar3 shell is a development tool; to deploy " "applications in production, consider using releases " -- cgit v1.1