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(-) 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