From d45bacb73bd1a255a5042929a49c81ab298df946 Mon Sep 17 00:00:00 2001 From: Fred Hebert Date: Tue, 5 Dec 2017 13:05:14 -0500 Subject: Run a soft purge while within the compiler step Prevents the killing of a plugin with itself --- src/rebar_prv_compile.erl | 2 +- src/rebar_utils.erl | 6 +++++- systest/all_SUITE.erl | 12 +++++++++++- systest/all_SUITE_data/grisp_explode/rebar.config | 16 ++++++++++++++++ systest/all_SUITE_data/grisp_explode/rebar.lock | 8 ++++++++ .../grisp_explode/src/mygrispproject.app.src | 17 +++++++++++++++++ .../grisp_explode/src/mygrispproject.erl | 15 +++++++++++++++ .../grisp_explode/src/mygrispproject_sup.erl | 19 +++++++++++++++++++ 8 files changed, 92 insertions(+), 3 deletions(-) create mode 100644 systest/all_SUITE_data/grisp_explode/rebar.config create mode 100644 systest/all_SUITE_data/grisp_explode/rebar.lock create mode 100644 systest/all_SUITE_data/grisp_explode/src/mygrispproject.app.src create mode 100644 systest/all_SUITE_data/grisp_explode/src/mygrispproject.erl create mode 100644 systest/all_SUITE_data/grisp_explode/src/mygrispproject_sup.erl diff --git a/src/rebar_prv_compile.erl b/src/rebar_prv_compile.erl index 72320fb..75e6eee 100644 --- a/src/rebar_prv_compile.erl +++ b/src/rebar_prv_compile.erl @@ -145,7 +145,7 @@ compile(State, Providers, AppInfo) -> code:add_pathsa(PluginDepsPaths), AppFileCompileResult = rebar_otp_app:compile(State, AppInfo4), %% Clean up after ourselves, leave things as they were. - rebar_utils:remove_from_code_path(PluginDepsPaths), + rebar_utils:remove_from_code_path(PluginDepsPaths, soft_purge), case AppFileCompileResult of {ok, AppInfo5} -> diff --git a/src/rebar_utils.erl b/src/rebar_utils.erl index 5ea0452..64d4952 100644 --- a/src/rebar_utils.erl +++ b/src/rebar_utils.erl @@ -49,6 +49,7 @@ update_code/1, update_code/2, remove_from_code_path/1, + remove_from_code_path/2, cleanup_code_path/1, args_to_tasks/1, expand_env_variable/3, @@ -753,6 +754,9 @@ update_code(Paths, Opts) -> end, Paths). remove_from_code_path(Paths) -> + remove_from_code_path(Paths, purge). + +remove_from_code_path(Paths, Type) when Type == purge; Type == soft_purge -> lists:foreach(fun(Path) -> Name = filename:basename(Path, "/ebin"), App = list_to_atom(Name), @@ -763,7 +767,7 @@ remove_from_code_path(Paths) -> ok; {ok, Modules} -> application:unload(App), - [begin code:purge(M), code:delete(M) end || M <- Modules] + [begin code:Type(M), code:delete(M) end || M <- Modules] end, code:del_path(Path) end, lists:usort(Paths)). diff --git a/systest/all_SUITE.erl b/systest/all_SUITE.erl index a0cfd3f..ba06a9c 100644 --- a/systest/all_SUITE.erl +++ b/systest/all_SUITE.erl @@ -29,7 +29,7 @@ end_per_testcase(_Name, Config) -> Config. all() -> - [noop, resource_plugins, alias_clash]. + [noop, resource_plugins, alias_clash, grisp_explode]. %groups() -> % [{plugins, [shuffle], []}, @@ -66,6 +66,16 @@ alias_clash(Config) -> ?assertNotEqual(nomatch, re:run(Output, "Not adding provider default test from module rebar_prv_alias_test " "because it already exists from module rebar_prv_alias_test")), + +grisp_explode() -> + [{doc, "Don't force purge a plugin that runs the compile job itself"}]. +grisp_explode(Config) -> + %% When the purge handling is wrong, the run fails violently. + {error, {_,Output}} = rebar3("grisp deploy -n robot -v 0.1.0", Config), + ct:pal("Rebar3 Output:~n~s",[Output]), + ?assertNotEqual(nomatch, + re:run(Output, "No releases exist in the system for robot:0.1.0!") + ), ok. %%%%%%%%%%%%%%% diff --git a/systest/all_SUITE_data/grisp_explode/rebar.config b/systest/all_SUITE_data/grisp_explode/rebar.config new file mode 100644 index 0000000..43c9f63 --- /dev/null +++ b/systest/all_SUITE_data/grisp_explode/rebar.config @@ -0,0 +1,16 @@ +{deps, [grisp]}. + +{plugins, [{rebar3_grisp, "0.1.0"}]}. + +{erl_opts, [debug_info]}. + +{grisp, [ + {otp_release, "19"}, + {deploy, [ + {destination, "/path/to/SD-card"} + ]} +]}. + +{relx, [ + {release, {mygrispproject, "0.1.0"}, [mygrispproject]} +]}. diff --git a/systest/all_SUITE_data/grisp_explode/rebar.lock b/systest/all_SUITE_data/grisp_explode/rebar.lock new file mode 100644 index 0000000..2523b13 --- /dev/null +++ b/systest/all_SUITE_data/grisp_explode/rebar.lock @@ -0,0 +1,8 @@ +{"1.1.0", +[{<<"grisp">>,{pkg,<<"grisp">>,<<"0.1.1">>},0}, + {<<"mapz">>,{pkg,<<"mapz">>,<<"0.3.0">>},1}]}. +[ +{pkg_hash,[ + {<<"grisp">>, <<"5A1318E7B1582D7C5B1E446D149A6F93428A380BCFE7D740E57E4F6B6CDB19DD">>}, + {<<"mapz">>, <<"438D24746CE5A252101E00B2032EFDF7FC69EB32689D3B805DE5E6DD7F52614F">>}]} +]. diff --git a/systest/all_SUITE_data/grisp_explode/src/mygrispproject.app.src b/systest/all_SUITE_data/grisp_explode/src/mygrispproject.app.src new file mode 100644 index 0000000..0f0a396 --- /dev/null +++ b/systest/all_SUITE_data/grisp_explode/src/mygrispproject.app.src @@ -0,0 +1,17 @@ +{application, mygrispproject, [ + {description, "A GRiSP application"}, + {vsn, "0.1.0"}, + {registered, []}, + {mod, {mygrispproject, []}}, + {applications, [ + kernel, + stdlib, + grisp + ]}, + {env,[]}, + {modules, []}, + + {maintainers, []}, + {licenses, ["Apache 2.0"]}, + {links, []} +]}. diff --git a/systest/all_SUITE_data/grisp_explode/src/mygrispproject.erl b/systest/all_SUITE_data/grisp_explode/src/mygrispproject.erl new file mode 100644 index 0000000..a9152fe --- /dev/null +++ b/systest/all_SUITE_data/grisp_explode/src/mygrispproject.erl @@ -0,0 +1,15 @@ +% @doc mygrispproject public API. +% @end +-module(mygrispproject). + +-behavior(application). + +% Callbacks +-export([start/2]). +-export([stop/1]). + +%--- Callbacks ----------------------------------------------------------------- + +start(_Type, _Args) -> mygrispproject_sup:start_link(). + +stop(_State) -> ok. diff --git a/systest/all_SUITE_data/grisp_explode/src/mygrispproject_sup.erl b/systest/all_SUITE_data/grisp_explode/src/mygrispproject_sup.erl new file mode 100644 index 0000000..aef0d4f --- /dev/null +++ b/systest/all_SUITE_data/grisp_explode/src/mygrispproject_sup.erl @@ -0,0 +1,19 @@ +% @doc mygrispproject top level supervisor. +% @end +-module(mygrispproject_sup). + +-behavior(supervisor). + +% API +-export([start_link/0]). + +% Callbacks +-export([init/1]). + +%--- API ----------------------------------------------------------------------- + +start_link() -> supervisor:start_link({local, ?MODULE}, ?MODULE, []). + +%--- Callbacks ----------------------------------------------------------------- + +init([]) -> {ok, { {one_for_all, 0, 1}, []} }. -- cgit v1.1 From f12871451f2c60bc35da053198ccc48d1b1db687 Mon Sep 17 00:00:00 2001 From: Fred Hebert Date: Wed, 6 Dec 2017 08:53:12 -0500 Subject: Safer purge switch Rather than the caller having to think of what to purge or not, use erlang:check_process_code/2 to detect if the caller (rebar3) may die because of the operation. If so, do a soft purge with a conditional delete instead of a hard purge with a mandatory delete. --- src/rebar_prv_compile.erl | 2 +- src/rebar_utils.erl | 12 +++++++----- systest/all_SUITE.erl | 1 + 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/rebar_prv_compile.erl b/src/rebar_prv_compile.erl index 75e6eee..72320fb 100644 --- a/src/rebar_prv_compile.erl +++ b/src/rebar_prv_compile.erl @@ -145,7 +145,7 @@ compile(State, Providers, AppInfo) -> code:add_pathsa(PluginDepsPaths), AppFileCompileResult = rebar_otp_app:compile(State, AppInfo4), %% Clean up after ourselves, leave things as they were. - rebar_utils:remove_from_code_path(PluginDepsPaths, soft_purge), + rebar_utils:remove_from_code_path(PluginDepsPaths), case AppFileCompileResult of {ok, AppInfo5} -> diff --git a/src/rebar_utils.erl b/src/rebar_utils.erl index 64d4952..b633760 100644 --- a/src/rebar_utils.erl +++ b/src/rebar_utils.erl @@ -49,7 +49,6 @@ update_code/1, update_code/2, remove_from_code_path/1, - remove_from_code_path/2, cleanup_code_path/1, args_to_tasks/1, expand_env_variable/3, @@ -754,9 +753,6 @@ update_code(Paths, Opts) -> end, Paths). remove_from_code_path(Paths) -> - remove_from_code_path(Paths, purge). - -remove_from_code_path(Paths, Type) when Type == purge; Type == soft_purge -> lists:foreach(fun(Path) -> Name = filename:basename(Path, "/ebin"), App = list_to_atom(Name), @@ -767,7 +763,13 @@ remove_from_code_path(Paths, Type) when Type == purge; Type == soft_purge -> ok; {ok, Modules} -> application:unload(App), - [begin code:Type(M), code:delete(M) end || M <- Modules] + [case erlang:check_process_code(self(), M) of + false -> + code:purge(M), code:delete(M); + _ -> + ?DEBUG("~p can't purge ~p safely, doing a soft purge", [self(), M]), + code:soft_purge(M) andalso code:delete(M) + end || M <- Modules] end, code:del_path(Path) end, lists:usort(Paths)). diff --git a/systest/all_SUITE.erl b/systest/all_SUITE.erl index ba06a9c..6d2f14f 100644 --- a/systest/all_SUITE.erl +++ b/systest/all_SUITE.erl @@ -66,6 +66,7 @@ alias_clash(Config) -> ?assertNotEqual(nomatch, re:run(Output, "Not adding provider default test from module rebar_prv_alias_test " "because it already exists from module rebar_prv_alias_test")), + ok. grisp_explode() -> [{doc, "Don't force purge a plugin that runs the compile job itself"}]. -- cgit v1.1